1. 程式人生 > >關於Windows隱藏視窗的封裝

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