關於Windows隱藏視窗的封裝
阿新 • • 發佈:2019-02-01
隱藏視窗在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帶來的麻煩。
同學們對於這個程式碼如果有更好的建議就評論下吧,嘿嘿