在MFC中註冊自己的窗口類名

之所以產生這個想法,或者說關注這個問題,是因爲想通過FindWindow找到(自己設計的程序中的)窗口的句柄。

一、關於MFC窗口類的一般知識:

一般情況下,MFC使用了默認的窗口屬性來幫助我們建立窗口。這裏單獨說一下基於Dialog建立起來的程序,窗口有些是通過有些是Dialog(有名字/標題,但窗口類型名與其他基於Dialog的程序的窗口的窗口類型名相同;只能通過名字來查找),有些是DialogBar(既沒有名字/標題,也沒有可分辨的窗口類型名),因爲MFC在幫助我們省去一些工作的同時,也使用了這些默認的窗口屬性。

在這種情況下,如果使用FindWindow來找到DialogBar窗口的句柄,是比較難的。因此,我想可以通過修改DialogBar窗口的WNDCLASS類型名來達到這一點。

按照MSDN上的說法:

MFC應用程序產生的對話框和控件,這兩者的窗口類類名由Windows提供。我們可以替換這些由Windows動態提供的名字,方法是在PreCreateWindow中註冊我們自己的類並使用這個類。一般情況下,MFC提供的窗口類型名有下面兩種方式:①Afx::%x:%x;②Afx::%x:%x:%x:%x。   這些%x所表示的16進制字符是用WNDCLASS結構的數據來填充的。MFC使用此技術,可以使得需要相同WNDCLASS結構的C++類可以共享同一個註冊的窗口類。需要注意的是,與大多數簡單的Win32應用程序不同,MFC應用程序只有一個WNDPROC。各個不同的窗口之所以表現出不同的特性,是因爲重載了函數。

MFC提供的窗口類型名中,%x字符的可替換值如下:

WNDCLASS.hInstance, WNDCLASS.style, WNDCLASS.hCursor, WNDCLASS.hbrBackground, WNDCLASS.hIcon

①Afx::%x:%x中,hCursor、hbrBackground、hIcon是NULL。

二、修改窗口類的類名

通過對網絡資料的搜索,找到了一種修改Dialog的WNDCLASS.lpszClassName的方法。參考文獻①中有詳細的描述,經實際驗證可行。

該方法主要有兩步:

①在rc資源文件中,找到要待修改的Dialog的資源描述信息,添加CLASS “窗口類型名”

②在APP類中的InitInstance進行窗口類型註冊。


三、使用FindWindow或FindWindowEx查找窗口

函數聲明:

HWND WINAPI FindWindow(  _In_opt_  LPCTSTR lpClassName,  _In_opt_  LPCTSTR lpWindowName);

HWND WINAPI FindWindowEx(  _In_opt_  HWND hwndParent,  _In_opt_  HWND hwndChildAfter,
  _In_opt_  LPCTSTR lpszClass,  _In_opt_  LPCTSTR lpszWindow);


關於FindWindow和FindWindowEx的使用注意事項:

在網上瀏覽的過程中,發現了很多人說這兩個函數返回的句柄是0,怎麼弄也找不到原因。實際上,可能是沒有注意到這兩個函數的使用說明。PS:我也犯了這樣的錯,花了大概半天的時間才找到原因。

在讀MSDN關於這兩個函數的說明時,有些地方不能漏掉。

FindWindow:

Retrieves a handle to the top-level window whose class name and window name match the specified strings. This function does not search child windows. This function does not perform a case-sensitive search.

這句話的意思是說,FindWindow是從頂層窗口中找到並返回匹配lpClassName和lpWindowName的窗口的句柄。這裏的窗口必須是頂層的,即是Desktop的子窗口,不能使孫窗口或任何非子代的後代窗口。也就是說,如果匹配這兩個字符串的窗口是某個頂層窗口的子窗口,則FindWindow返回0。

FindWindowEx

Retrieves a handle to a window whose class name and window name match the specified strings. The function searches child windows, beginning with the one following the specified child window. This function does not perform a case-sensitive search.

這句話的意思是,FindWindowEx從hwndParent的子窗口中查找並返回匹配參數的窗口句柄。返回的句柄所對應的窗口必須是hwndParent的子窗口;如果與參數匹配的窗口是hwndParent的非直接子代窗口(如:孫窗口什麼的)或者是後代窗口中的某個控件中的窗口,則FindWindowEx返回0。

建議:使用FindWindow或者FindWindowEx,要明白待查找的窗口位於哪一個層級,是誰的子窗口。


參考文獻:

① 如何改變MFC應用程序主窗口的類名http://www.cnblogs.com/menggucaoyuan/archive/2011/06/10/2077217.html

MFC窗口類名稱http://msdn.microsoft.com/zh-cn/library/btbxa0ad.aspx

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章