窗口句柄浅析和获取窗口句柄的方法
句柄(HANDLE)是Windows程序中一個重要的概念,使用也非常頻繁。在Windows程序中,有各種各樣的資源(窗口、圖標、光標等),系統在創建這些資源時會為它們分配內存,并返回標識這些資源的標識號,即句柄。
窗口句柄是windows句柄的一種,且是重要的一種句柄。在Windows應用程序中,窗口是通過窗口句柄(HWND)來標識的。我們要對某個窗口進行操作,首先就要得到這個窗口的句柄。
窗口句柄的概念比較抽象,簡單說窗口句柄就是一個窗口(window)的代表。我們通過幾個例子來認識它。
1.LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
windows窗口處理函數,windows消息機制說的是,每當某個窗口發生變化(比如改變大小,移動),windows系統都會發相應的消息(wm_size,wm_move)給這個窗口。即調用函數 SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);注意這里WndProc和SendMessage的第一個參數都是HWND,窗口句柄代表這個窗口。
2. hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
????? CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
這里說的是窗口句柄的產生,可以把hWnd想象成指針,CreateWindow想象成c++里的new,創建一個window,系統要為這個window對象分配一些資源,可以想象,window是由一個大的結構構成的。同時窗口句柄用來標識這個窗口。
3.有個窗口的句柄,則你就可以操控這個窗口的一切。
大量管理window的win32 api都是以hwnd做為參數。下面列舉一些:
BringWindowToTop
FindWindowEx
GetParent
SetWindowPos
GetWindowRect
等等。
4.不僅窗口,窗口上的控件,象按鈕,編輯框等也有窗口句柄,因為它們也是一種特殊的窗口,上面操作窗口的api大部分對這些控件窗口也適用。
獲取句柄的方法:
這篇文章是關于如何獲取窗口句柄,以及有哪些函數可供使用的簡單討論!可適用于vc、bcb(其他的我沒有試,估計可以),本人在bcb環境下試驗。
首先我會羅列出一些獲取句柄的win32 api 函數,然后簡單說說他們的用途!最后說說我是怎么理解和應用的。見笑了!
可用的win32 api函數:
1.HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName)
?? HWND FindWindowEx(HWND hwndParent, HWND hwndChildAfter,LPCTSTR lpClassName, LPCTSTR lpWindowName)
2.HWND WindowFromPoint(POINT& Point)
3.BOOL CALLBACK EnumChildProc(HWND hwnd,LPARAM lParam)
?? BOOL CALLBACK EnumChildWindows(HWND hWndParent, WNDENUMPROC lpEnumFunc,LPARAM lParam)
?? BOOL CALLBACK EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam)
?? BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
一般用途:
?????? 對于第一種,大家都很熟悉,是捕捉句柄的常規武器,FindWindow這兩兄弟,可以接受捕捉對象的類名或者窗口標題之一,作為參數,返回一個HWND。可是對于一般群眾,不一定知道所有的窗口(包括標題欄、按鈕等等)的類名啊!--可以簡單舉例,請問你知道桌面圖標的窗口的類名嗎?而對于窗口標題,有可能會出現相同的標題,有兩個窗口--指一個程序的兩個進程,這又是個麻煩吧!好了,這個問題先放放,繼續下一組。
?????? 第二組,通過win32定義的POINT結構(typedef struct tagPOINT {?? LONG x;
? LONG y;} POINT),來獲得當前鼠標光標位置的窗口HWND,這是最直觀的武器!常規操作如下:先得到Cursor的POINT(BOOL GetCursorPos(LPPOINT)函數),再用WindowFromPoint。這樣,我們幾乎可以獲得任何打開的有窗口的函數的HWND了!然后通過獲取類名的win32 api函數(int GetClassName(? HWND hWnd,?? LPTSTR lpClassName,?? int nMaxCount ))得到類名--這里的lpClassName最好用字符數組地址,nMaxCount就是數組的size了,同時,這種方法解決了第一個問題的麻煩!--我可以把鼠標放在任何地方!*^_^*
?????? 第三組,這些是用來列舉和處理任何窗口的超級武器!通過組合運用EnumWindows和EnumWindowsProc,EnumChildWindows與EnumChildProc,可以掃描桌面所有窗口并對之處理!
我的理解:(這部分用任務驅動式教學方法--誰讓小弟是老師呢!xi xi)
任務:得到所有的窗口的類名。
解決辦法1:我們會先想到第三組,可以自桌面窗口開始(它是所有窗口的祖先),依次掃描,獲取類名并存之。有點兒像Visual Stdio的Spy++,或者Borland 的WinSight32,具體辦法如下:(bcb中)
在主程序中,調用EnumWindows,傳入YouEnumProc的函數地址作第一個參數,別忘了轉換成WNDENUMPROC類型。第二參可NULL。::EnumWindows(reinterpret_cast<WNDENUMPROC> YouEnumProc,NULL);
在YouEnumProc函數中,如果第一參HWND = = NULL,就跳離(return FALSE;),可以結束啦!
然后,把類名數組準備好,得到類名,存之。
返回真值,繼續下一次掃描。
看起來并不復雜,是一種函數遞歸。但是我可會解釋!面啊!: p
第二種解決方法:簡單、直觀--自己想出來的,頗得意
首先準備一個時鐘,一種存類名方法(我用TMemo)
在定時器處理函數中:
1、得到當前cursor的點位置
2、再用WindowFromPoint,
3、然后得到類名,放到TMemo里
這樣可以用鼠標獲得你想要的窗口(包括按鈕等),只要鼠標在窗口放一會兒。。。哈哈
第三種方法:其實利用FindWindow和循環結構也應該可以
總結:其實得到HWND的方法很多,比如知道了窗口層次,依次向下掃。。。在說第三種呢!但我覺得,我的方法最直接有效,你說呢?
歡迎大家與我聯系,并討論這個問題!有關這個問題我還有許多疑問,比如HWND與ID的轉換,在如IE頁面中的表單控件的HWND或ID,還是其他的東東,總之是能識別他的東西。。。這個我很困惑,沒辦法!
不清楚地方,大家要參照MSDN啊
其它獲取句柄的方法:
1.根據id獲取窗口句柄
??Hwnd hwnd = GetDlgItem(hwndParent,id).
2.根據窗口句柄,獲取id
????id = GetWindowLong(hwndChild,GWL_ID)
??? id = GetDlgCtrlID(hwndchild).
3.獲取實例句柄的若干方法
????hInst = GetWindowLong(hwnd,GWL_HINSTANCE)
????把HINSTANCE 作為全局變量保存.
????當建立窗口時,參數lparam指向了一個建立結構的地址.
????可以這樣獲取實例句柄
????hInst = ((LPCREATESTRUCT)lParam)->hInstance.
總結
以上是生活随笔為你收集整理的窗口句柄浅析和获取窗口句柄的方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux的桌面分辨率设置,linux
- 下一篇: 微粒群算法(PSO)