標籤:style blog http color 使用 strong
呵呵,最近在研究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