呵呵,最近在研究SendMessage函數,其中需要用到m_hWnd,之后延伸着又嘗試獲得窗口的句柄,於是遇到了FindWindow函數,原型如下:
HWND FindWindow
(
LPCSTR lpClassName, //輸入窗口的類名,其實需要是注冊過的類名才行,否則是要報錯或者查找失敗的。
LPCSTR lpWindowName, //輸入窗口的名稱,就是窗口上面藍色的那行玩意兒寫的字。
);
對於這個函數,如果按照窗口的名稱查找,相信大家都非常簡單,因為名稱在rc文件里,是已經注冊過的了(具體的待會給大家貼代碼就能看明白了)。但如果大家使用我們自己定義的窗口名稱查詢,則往往會失敗,甚至是報錯!尤其是在使用SendMessage告知另一個窗口退出時,會導致內存泄露!
對於這樣的情況,編譯器不一定能告訴各位,所以,如果沒有親自注冊窗口類的經驗的話,建議大家如果要使用FindWindow函數獲得窗口句柄的話,盡量通過 窗口的名稱查詢。
言歸正傳,出現之前的那種嚴重情況的原因,是在於MFC並沒有一個一個幫大家將我們派生的窗口類進行注冊,而是使用的默認窗口類的方式,具體淵源似乎俺也說不大清楚(嘿嘿,見笑了。。。),咱只能引用這一段話:
“ 在早期的MFC中 (MFC 4.0之前的版本)提供了大量的預定以的窗口類,但這些窗口類在默認下已經不再被提供了,因為涉及到多版本的技術問題(多個版本的MFC加載在同一個地址空間),如涉及到的一個實際的問題就是MFC應用程序和OLE控件都會用到MFC的DLLs。 ”
而默認的窗口類,一般類名都是“#32770(Dialog)”,這個大家通過Spy++檢測窗口的時候就可以看到。
拿我這邊的一個小程序為例:
默認的類名是 #32770(Dialog)
而紅線之前的,就是“注冊”過的窗口的名稱,這個是MFC自動做了的。那么,我們能使用這個默認類名進行操作么?嘿嘿~大家試試嘛···所有的未注冊窗口似乎都是這個類名哦。。。。
OK,返回話題,既然默認是這樣的,那么如何修改呢?這個咱參閱了這位大大的文章:http://hi.baidu.com/iwangkun/blog/item/97fc18d5ef59dfc251da4b21.html
由於是英文的,可能有的朋友會望而生畏,所以,咱把自己的心得以及經驗總結一下,翻譯出來吧:
首先,請用記事本或寫字本的模式,打開需要注冊窗口的工程目錄下的rc資源文件(各個朋友,建議大家先將工程備份一份,因為錯誤的修改,很容易導致整個工程出錯哦!)。這個時候,請找到我們要注冊的窗口的數據位置,這個很好找的:
因為每一個窗口的數據開始位置,都是以窗口的句柄開頭的,
比如我要注冊的窗口類的對應句柄是IDD_CARHIRESYSTEM_DIALOG,
那么打開文件后,稍微需找一下就會發現這個數據段:
IDD_CARHIRESYSTEM_DIALOG DIALOGEX 0, 0, 400, 280 STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW CAPTION "車輛出租系統 CarHireSystem" FONT 9, "宋體", 0, 0, 0x1 BEGIN COMBOBOX IDC_COMBO_CHANCE,23,35,83,95,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP EDITTEXT IDC_EDIT_SEARCH,125,33,83,15,ES_AUTOHSCROLL DEFPUSHBUTTON "查詢",IDC_BUTTON_SEARCH,219,29,50,25 ........等等 END
如上所示,那么,我們接下來所要做事情,便是添加我們對窗口類的注冊信息,
即:
IDD_CARHIRESYSTEM_DIALOG DIALOGEX 0, 0, 400, 280 STYLE DS_MODALFRAME | WS_MINIMIZEBOX | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_APPWINDOW CAPTION "車輛出租系統 CarHireSystem" CLASS "CCarHireSystemDlg" //""雙引號內的類名,可以隨意,但注意一定要寫對哦,后面還要用到的。 FONT 9, "宋體", 0, 0, 0x1 BEGIN COMBOBOX IDC_COMBO_CHANCE,23,35,83,95,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP EDITTEXT IDC_EDIT_SEARCH,125,33,83,15,ES_AUTOHSCROLL DEFPUSHBUTTON "查詢",IDC_BUTTON_SEARCH,219,29,50,25 ........等等 END
然后保存文件,如此,基本上任務已經完成了,就差進行注冊了。MFC中的注冊函數是 :AfxRegisterClass,格式如下:
BOOL AFXAPI AfxRegisterClass(WNDCLASS *lpWndClass);
那么,我們要做的事情是什么呢? ----- 在窗口完成初始化之前,對窗口類進行注冊。於是,我們找到工程的App類,加入如下代碼:
///////////////////////////////////////////////////////// WNDCLASS wc;
// Get the info for this class. // #32770 is the default class name for dialogs boxes. ::GetClassInfo(AfxGetInstanceHandle(), "#32770", &wc);
// Change the name of the class. wc.lpszClassName = "CCarHireSystemDlg"; //這里請再次注意,一定要保證和rc資源文件里保存的類名相同! // Register this class so that MFC can use it. AfxRegisterClass(&wc);
/////////////////////////////////////////////////////////
如上,只要AfxRegisterClass(&wc); 不返回FALSE,那么我們的類名注冊就成功了!
演示截圖:
這個時候,大家再使用FindWindow("CCarHireSystemDlg",NULL)函數,就可以正常使用了!
最后再次重申兩點:
1.修改rc資源文件前,建議大家備份工程。當修改了rc文件后,如果沒有加入上面的注冊代碼,或者加入位置出錯,都會導致程序編譯無問題,但執行報錯!這一點,如果在rc資源文件里保存的類名稱,與注冊代碼里的類名稱不相同,也會導致執行報錯。
2.使用FindWindow函數時,如果窗口類還並未注冊,那么,建議直接將第一個參數設為NULL,同時在第二個參數上傳入窗口的名稱,進行查詢。注意,是窗口的名稱,即窗口類生成的對象的窗口標題!如此,也不會導致錯誤。
轉自
http://blog.csdn.net/atmcash4423/article/details/6606285
http://hi.baidu.com/%D5%B8%CC%EC/blog/item/d4a01fa0232126a0cbefd098.html