關於Windows隱藏窗口的封裝

隱藏窗口在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帶來的麻煩。
同學們對於這個代碼如果有更好的建議就評論下吧,嘿嘿
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章