隱藏窗口在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帶來的麻煩。
同學們對於這個代碼如果有更好的建議就評論下吧,嘿嘿