隐藏窗口在Windows用的非常广泛,比如WSAAsyncSelect等等,需要窗口回调,假如窗口恰好使用的其他库,就容易导致一个问题:消息污染,也就是需要回调的消息与界面库本身需要使用的用户消息相同,导致消息无响应或者界面库异常。解决的思路通常是创建一个隐藏窗口,设置主窗口为用户使用的窗口后,关闭主窗口同时也会自动关闭临时窗口自身,简单粗暴。
以下分享一个创建隐藏窗口以及添加消息事件响应的代码:
hTempWindow.h
#ifndef __H_TEMP_WINDOW_H__
#define __H_TEMP_WINDOW_H__
#pragma once
#include <Windows.h>
#include <tchar.h>
#include <map>
typedef bool (*pMsgHandler)(WPARAM wParam, LPARAM lParam);
typedef bool (*pMsgGroupHandler)(UINT uMsg, WPARAM wParam, LPARAM lParam);
class hTempWindow {
hTempWindow () { };//不可实例化
static LPCTSTR h_name;
static HWND h_hWnd;
static HINSTANCE h_hInstance;
static std::map<UINT, pMsgHandler> h_msgHandler;
static std::map<UINT64, pMsgGroupHandler> h_msgGroupHandler;
static LRESULT WINAPI WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
public:
static bool Create (HINSTANCE hInstance, HWND parent);
static void AddMsgHandler (UINT uMsg, pMsgHandler MsgHandler);
static void DelMsgHandler (UINT uMsg);
static void AddMsgGroupHandler (UINT uMsgLow, UINT uMsgHigh, pMsgGroupHandler MsgGroupHandler);
static void DelMsgGroupHandler (UINT uMsgLow, UINT uMsgHigh);
};
#endif //__H_TEMP_WINDOW_H__
hTempWindow.cpp
#include "hTempWindow.h"
LPCTSTR hTempWindow::h_name = _T ("TempWindow");
HWND hTempWindow::h_hWnd;
HINSTANCE hTempWindow::h_hInstance;
std::map<UINT, pMsgHandler> hTempWindow::h_msgHandler;
std::map<UINT64, pMsgGroupHandler> hTempWindow::h_msgGroupHandler;
LRESULT WINAPI hTempWindow::WndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
for (std::map<UINT, pMsgHandler>::iterator i = hTempWindow::h_msgHandler.begin (); i != hTempWindow::h_msgHandler.end (); i++) {
if (uMsg == i->first) {
if (i->second (wParam, lParam)) return 0;
return DefWindowProc (hWnd, uMsg, wParam, lParam);
}
}
for (std::map<UINT64, pMsgGroupHandler>::iterator i = hTempWindow::h_msgGroupHandler.begin (); i != hTempWindow::h_msgGroupHandler.end (); i++) {
if (uMsg >= i->first >> 32 && uMsg <= (i->first & 0xFFFFFFFF)) {
if (i->second (uMsg, wParam, lParam)) return 0;
return DefWindowProc (hWnd, uMsg, wParam, lParam);
}
}
return DefWindowProc (hWnd, uMsg, wParam, lParam);
}
bool hTempWindow::Create (HINSTANCE hInstance, HWND parent) {
hTempWindow::h_hInstance = hInstance;
WNDCLASSEX wcex = { sizeof (WNDCLASSEX), 0, hTempWindow::WndProc, 0, 0, hTempWindow::h_hInstance, NULL, NULL, NULL, NULL, hTempWindow::h_name, NULL };
if (!RegisterClassEx (&wcex)) return false;
hTempWindow::h_hWnd = CreateWindowEx (0, hTempWindow::h_name, hTempWindow::h_name, 0, 0, 0, 0, 0, parent, NULL, hTempWindow::h_hInstance, NULL);
if (!IsWindow (hTempWindow::h_hWnd)) {
UnregisterClass (hTempWindow::h_name, hTempWindow::h_hInstance);
return false;
}
return true;
}
void hTempWindow::AddMsgHandler (UINT uMsg, pMsgHandler MsgHandler) {
hTempWindow::h_msgHandler.insert (std::pair<UINT, pMsgHandler> (uMsg, MsgHandler));
}
void hTempWindow::DelMsgHandler (UINT uMsg) {
hTempWindow::h_msgHandler.erase (uMsg);
}
void hTempWindow::AddMsgGroupHandler (UINT uMsgLow, UINT uMsgHigh, pMsgGroupHandler MsgGroupHandler) {
hTempWindow::h_msgGroupHandler.insert (std::pair<UINT64, pMsgGroupHandler> ((uMsgLow << 32)&uMsgHigh, MsgGroupHandler));
}
void hTempWindow::DelMsgGroupHandler (UINT uMsgLow, UINT uMsgHigh) {
hTempWindow::h_msgGroupHandler.erase ((uMsgLow << 32)&uMsgHigh);
}
至于使用方法嘛。。。等主窗口创建完毕后调用Create,然后就是AddMsgHandler和AddMsgGroupHandler。需要说明的是AddMsgGroupHandler为接收一个范围内的消息,当消息值>=一个数并且消息值<=又一个数时,可以调用这个方法,避免不停的AddMsgHandler带来的麻烦。
同学们对于这个代码如果有更好的建议就评论下吧,嘿嘿