LibUIDK介面庫系列文章 響應預設按鈕

2021-08-08 23:07:16 字數 4023 閱讀 6708

在對話方塊中,如果按鈕的屬性指定了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模組資訊 驗證器的實現層級及內建的各種驗...