在對話方塊中,如果按鈕的屬性指定了bs_defpushbutton風格,那麼在對話方塊中按下enter鍵,就會呼叫設定了bs_defpushbutton風格的按鈕的響應函式。
但如果我們在普通cwnd派生類中,建立了bs_defpushbutton風格的按鈕,按下enter鍵,卻不會執行些按鈕的響應函式。下面講解如何為cwnd加上這一特性。
零、在講解前,先介紹一下,執行按鈕的響應函式是通過wm_command訊息來完成的,訊息id為0x0111。
一、建議乙個標準的mfc對話方塊程式,刪除ok和cannel按鈕,再建立兩個按鈕,id為idc_button1和idc_button2(id為1002,十六進製制為3ea),並為兩個按鈕加上響應函式onbutton1和onbutton2。把idc_button2設定為預設按鈕。
二、在onbutton2中加個斷點。
三、按下enter鍵,在onbutton2中斷,檢視呼叫棧如下:
czzzzdlg::onbutton2() line 107
_afxdispatchcmdmsg(ccmdtarget * 0x0012fe74 , unsigned int 0x000003ea, int 0x00000000, void (void)* 0x0040105f czzzzdlg::onbutton2(void), void * 0x00000000, unsigned int 0x0000000c, afx_cmdhandlerinfo * 0x00000000) line 88
ccmdtarget::oncmdmsg(unsigned int 0x000003ea, int 0x00000000, void * 0x00000000, afx_cmdhandlerinfo * 0x00000000) line 302 + 39 bytes
cdialog::oncmdmsg(unsigned int 0x000003ea, int 0x00000000, void * 0x00000000, afx_cmdhandlerinfo * 0x00000000) line 97 + 24 bytes
cwnd::oncommand(unsigned int 0x000003ea, long 0x002f051e) line 2088
cwnd::onwndmsg(unsigned int 0x00000111, unsigned int 0x000003ea, long 0x002f051e, long * 0x0012fa0c) line 1597 + 28 bytes
cwnd::windowproc(unsigned int 0x00000111, unsigned int 0x000003ea, long 0x002f051e) line 1585 + 30 bytes
afxcallwndproc(cwnd * 0x0012fe74 , hwnd__ * 0x00260302, unsigned int 0x00000111, unsigned int 0x000003ea, long 0x002f051e) line 215 + 26 bytes
afxwndproc(hwnd__ * 0x00260302, unsigned int 0x00000111, unsigned int 0x000003ea, long 0x002f051e) line 368
afxwndprocbase(hwnd__ * 0x00260302, unsigned int 0x00000111, unsigned int 0x000003ea, long 0x002f051e) line 220 + 21 bytes
user32! 7e418734()
user32! 7e418816()
user32! 7e428ea0()
user32! 7e428eec()
ntdll! 7c90e473()
user32! 7e4292e3()
user32! 7e431cde()
user32! 7e43c6d3()
cwnd::isdialogmessagea(tagmsg * 0x004167c8 ) line 182
我們看到,在afxwndprocbase呼叫時,第一次看到0x00000111(wm_command)訊息及按鈕id 0x000003ea。所以,發生訊息轉換,是在下面呼叫之間:
afxwndprocbase(hwnd__ * 0x00260302, unsigned int 0x00000111, unsigned int 0x000003ea, long 0x002f051e) line 220 + 21 bytes
user32! 7e418734()
user32! 7e418816()
user32! 7e428ea0()
user32! 7e428eec()
ntdll! 7c90e473()
user32! 7e4292e3()
user32! 7e431cde()
user32! 7e43c6d3()
cwnd::isdialogmessagea(tagmsg * 0x004167c8 ) line 182
cwnd::isdialogmessagea內部,把訊息0x00000100(#define wm_keydown 0x0100)轉成0x00000111(wm_command)。然後通過afxwndprocbase來完成後續呼叫。通過以上分析,就縮小了研究範圍。
四、按f5繼續執行程式,並啟動spy++,通過spy++監視對話方塊的訊息。
五、cwnd::isdialogmessage**如下:
bool cwnd::isdialogmessage(lpmsg lpmsg)
在return ::isdialogmessage(m_hwnd, lpmsg);上加斷點。
六,按enter鍵,在return ::isdialogmessage(m_hwnd, lpmsg);上中斷,記錄spy++中,當前訊息前面的索引號。這個索引號之後的訊息,正是從isdialogmessage到afxwndprocbase呼叫過程中,對話方塊收到的訊息,對我們是有用的。
七、按f5執行,在onbutton2處中斷。記錄下spy++中當前訊息索引。上一步到這一步間,spy++中顯示對話方塊收到的訊息如下:
<00031> 00260302 s dm_getdefid
<00031> 00260302 r dm_getdefid whasdef:dc_hasdefid wdefid:03ea
<00032> 00260302 s wm_command wnotifycode:bn_clicked wid:1002 hwndctl:002f051e
可以看到,在訊息轉換時,對話方塊收到了dm_getdefid訊息,從字面上理解,dm表示dialog message,getdefid表示get default id,應該就是我們要找的訊息。
通過查詢msdn中dm_getdefid和isdialogmessage,確認,dm_getdefid正是得到預設按鈕id的訊息,只要我們在自己的cwnd中處理這個訊息,並且把預設按鈕的id返回,就可以通過按鈕enter鍵,執行我們自己預設按鈕的訊息響應函式了。
八、與dm_getdefid對應的還有乙個dm_setdefid,表示設定預設按鈕的id,視窗預設的預設按鈕id為1,即idok。所以,我們把自己的預設按鈕的id修改為1,也是可以的。
九、需要注意的是:cwnd派生類,預設不處理dm_setdefid和dm_getdefid,需要我們自己去處理。
設定預設按鈕:
// cwnd through dm_getdefid to handle default button
if ((dwstyle & bs_defpushbutton) == bs_defpushbutton)
}bool bret = pparent->sendmessage(dm_setdefid, nid, 0);
}父視窗cwnd派生類中的處理:
lresult cuiwnd::windowproc(uint message, wparam wparam, lparam lparam)
else if (message == dm_getdefid)
return cwnd::windowproc(message, wparam, lparam);}
LibUIDK介面庫系列文章 對話方塊座標單位
在 rc中,對話方塊中及其中的控制項的座標單位叫 對話方塊座標單位 英文縮寫為dlu。它們實際上依據一種特殊的座標系統,該系統只用於對話方塊模板。數字依據對話方塊使用字型的大小而定 x座標和寬度的單位是字元平均寬度的1 4 y座標和高度的單位是字元高度的1 8。公式如下 pixelx dialogu...
資料庫使用系列文章
資料庫在網際網路應用中佔據著不可或缺的作用,本系列文章旨在針對資料庫從背景 基本應用到高效使用作出一定總結。資料庫從字面上的理解就是資料的倉庫,其實我們平時說的資料庫是指資料庫管理系統 database management system 它是一種操縱和管理資料庫的大型軟體,用於建立 使用和維護資料...
微軟企業庫5 0 學習之路系列文章索引
第一步 基本入門 第二步 使用vs2010 data access模組建立多資料庫專案 第三步 為專案加上異常處理 採用自定義擴充套件方式記錄到資料庫中 第四步 使用快取提高 的效能 entlib caching 第五步 介紹entlib.validation模組資訊 驗證器的實現層級及內建的各種驗...