欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

ON_COMMAND_RANGE多個(gè)按鈕響應(yīng)一個(gè)函數(shù)的解決方法

 更新時(shí)間:2014年07月18日 09:29:27   投稿:shichen2014  
這篇文章主要介紹了ON_COMMAND_RANGE多個(gè)按鈕響應(yīng)一個(gè)函數(shù)的解決方法,需要的朋友可以參考下

本文描述了ON_COMMAND_RANGE多個(gè)按鈕響應(yīng)一個(gè)函數(shù)的解決方法。

開發(fā)人員需要注意在自定義消息響應(yīng)函數(shù)的聲明過程中,一定要注意參數(shù)的形式,稍微一疏忽就會導(dǎo)致莫須有的錯(cuò)誤,具體以O(shè)N_COMMAND_RANGE為例說下。

1.聲明消息響應(yīng)函數(shù):在要添加的工程上添加函數(shù)afx_msg void OnButtonPort();

2.消息映射:

BEGIN_MESSAGE_MAP(CXXXDlg, CDialog)
//{{AFX_MSG_MAP(CXXXDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_TIMER()
//}}AFX_MSG_MAP

//這里的IDC_BUTTON_PORT_1和 IDC_BUTTON_START_ALL之間有很多個(gè)Button,并且ID連續(xù)
ON_COMMAND_RANGE(IDC_BUTTON_PORT_1, IDC_BUTTON_START_ALL, OnButtonPort)
ON_WM_DEVICECHANGE()
END_MESSAGE_MAP()

3.映射函數(shù)的實(shí)現(xiàn):實(shí)現(xiàn)你自己的響應(yīng)函數(shù) void CXXXDlg::OnButtonPort()

注:此代碼DEBUG OK,Relase異常,不可直接參考,且聽下面分解:

DEBUG通過,不料Release卻直接崩潰,寫了這么多年的CODE還真第一次遇到這種情況,為什么ON_COMMAND_RANGE Debug正常,Release不正常呢?

先MSDN:

Use this macro to map a contiguous range of command IDs to a single message handler function.
ON_COMMAND_RANGE(id1, id2, memberFxn )
Parameters
id1
Command ID at the beginning of a contiguous range of command IDs.
id2
Command ID at the end of a contiguous range of command IDs.
memberFxn
The name of the message-handler function to which the commands are mapped.
Remarks
The range of IDs starts with id1 and ends with id2.
Use ON_COMMAND_RANGE to map a range of command IDs to one member function. Use ON_COMMAND to map a single command to a member function. Only one message-map entry can match a given command ID. That is, you can't map a command to more than one handler. For more information on mapping message ranges, see Handlers for Message-Map Ranges.
There is no automatic support for message map ranges, so you must place the macro yourself.

MSDN也沒有特別說明要注意什么的,我覺得我用的也很正常,于是在網(wǎng)上又搜了一大會,有一個(gè)網(wǎng)友非常專業(yè)的解釋的原因,具體網(wǎng)址是:http://yiyunscu.blog.163.com/blog/static/3626332020099802057982/

以下是轉(zhuǎn)載內(nèi)容:

該網(wǎng)友定義如下:

afx_msg void OnCommandMy(WPARAM wParam, LPARAM lParam );

申明只適用于ON_COMMAND消息的函數(shù)申明, 而ON_COMMAND_RANGE的函數(shù)申明在MSDN中建議寫成這樣:
OnCommandMy(UINT nID);
通過switch(nID) case **:進(jìn)行針對不同菜單進(jìn)行消息響應(yīng).
nID就是菜單傳入消息的ID號, 奇怪的是, 在Debug版本下, 先前的申明方式運(yùn)行完全正常, 查閱了MSDN, 找出了可能的原因:

 Handler functions for single commands normally take no parameters. With the exception of update handler functions, handler functions for message-map ranges require an extra parameter, nID, of type UINT. This parameter is the first parameter. The extra parameter accommodates the extra command ID needed to specify which command the user actually chose.

針對單個(gè)Command消息響應(yīng)函數(shù)可以不帶參數(shù), 但是對于多個(gè)Command消息如ON_COMMAND_RANGE申明的消息響應(yīng)需要將函數(shù)參數(shù)列表中的第一個(gè)參數(shù)定義為UINT nID, 指明command 的ID號, 按照MSDN的理解, ON_COMMAND_RANGE也可以像ON_COMMAND那樣在消息響應(yīng)函數(shù)中定義兩個(gè)參數(shù), 如afx_msg void OnCommandMy(WPARAM wParam, LPARAM lParam );在Debug和Release下, 編譯不會出現(xiàn)問題, 在Debug下運(yùn)行也不會出現(xiàn)問題, 但是在Release下面卻出現(xiàn)內(nèi)存錯(cuò)誤, 所以可以帶多個(gè)參數(shù)感覺只能在Debug下可以行的能, 在Release下就沒失效了.
查閱相關(guān)的資料并利用VC查看相應(yīng)的匯編代碼發(fā)現(xiàn), 應(yīng)該是函數(shù)調(diào)用和返回時(shí)棧操作不平衡導(dǎo)致Release版本下出現(xiàn)了內(nèi)存錯(cuò)誤的問題, ON_COMMAND_RANGE在MFC默認(rèn)的消息響應(yīng)函數(shù)中, 參數(shù)只有一個(gè), 如:

#define ON_COMMAND_RANGE(id, idLast, memberFxn) \
 { WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)idLast, AfxSig_vw, \
 (AFX_PMSG)(void (AFX_MSG_CALL CCmdTarget::*)(UINT))&memberFxn },
 // ON_COMMAND_RANGE(id, idLast, OnFoo) is the same as
 //  ON_CONTROL_RANGE(0, id, idLast, OnFoo)

函數(shù)調(diào)用過程中, 會將傳入的參數(shù)進(jìn)行壓棧操作, 因?yàn)镸FC默認(rèn)的傳入?yún)?shù)只有一個(gè), 因此調(diào)用OnCommandMy時(shí)會有系統(tǒng)傳入的一個(gè)消息參數(shù)進(jìn)行壓棧操作. 在函數(shù)返回時(shí), 應(yīng)該進(jìn)行出棧操作, 并且保證調(diào)用完成后棧維持平衡, 否則會出現(xiàn)可能的內(nèi)存錯(cuò)誤.在DEBUG上沒有出現(xiàn)內(nèi)存錯(cuò)誤在于在調(diào)用OnCommandMy函數(shù)返回時(shí)編譯器在返回代碼處添加了如下的匯編代碼:

pop edi
pop esi
pop ebx
add esp, 48h
cmp ebp, esp
call __chkesp (0041e680)
mov esp, ebp
pop ebp
ret 8(兩個(gè)參數(shù)出棧)

此匯編代碼的作用就是在函數(shù)返回時(shí)檢查調(diào)用中和調(diào)用返回時(shí)的棧是否一致, 如果不一致, 就強(qiáng)制平棧操作, 因?yàn)樵谶@個(gè)調(diào)用過程中, 傳入OnCommandMy的消息參數(shù)只有一個(gè)(只是申明成兩個(gè), 實(shí)際只有一個(gè)參數(shù)傳入), 所以存在棧不一致的情況, 但是強(qiáng)制平??梢员苊庥纱艘鸬腻e(cuò)誤.
在Release版本下, 就沒有了檢測棧的操作,
只是簡單的下面幾句匯編代碼完成出棧操作:

mov esp, ebp
pop ebp
ret 8兩個(gè)參數(shù)出棧)

可以明顯看到, Release下出現(xiàn)了棧操作不平衡的情況, 即入棧數(shù)小于出棧數(shù), 從而導(dǎo)致棧區(qū)地址錯(cuò)誤, 當(dāng)其它函數(shù)兩次對棧區(qū)進(jìn)行地址訪問時(shí)就極有可能出現(xiàn)內(nèi)存錯(cuò)誤的現(xiàn)象了.
所以, 平時(shí)寫程序時(shí)在Debug下高度完成之后, 最好還在Release下看一下, 因?yàn)橛行r(shí)候, Debug下對函數(shù)參數(shù)的檢查不是那么嚴(yán)格, 并且在棧的操作上, Debug可以幫助我們解決很多隱藏的問題, 但是Release下就不會了. 另外在自定義的消息響應(yīng)函數(shù)中, Debug和Release都不會對響應(yīng)函數(shù)的參數(shù)列表與MFC默認(rèn)參數(shù)列表進(jìn)行一致性檢測, 從而可能隱藏重大的內(nèi)存出錯(cuò)的可能性, 導(dǎo)致最終軟件在Release下運(yùn)行可能發(fā)生崩潰.

終于明白了,原來是ON_COMMAND_RANGE只能帶一個(gè)參數(shù),帶兩個(gè)或不帶都會異常所以重新定義:

afx_msg void OnButtonPort(UINT nID);

而且此nID就是你點(diǎn)擊的按鈕ID值,再也不用之前的麻煩代碼了

CWnd *pWnd = GetFocus();
int nPortID = pWnd->GetDlgCtrlID() ;

問題解決!

附加:

1、ON_COMMAND(ID_VIEW_CUSTOMIZE, OnViewCustomize)==>void CMainFrame::OnViewCustomize();或void CMainFrame::OnViewCustomize(WPARAM wParam, LPARAM lParam);

2、ON_REGISTERED_MESSAGE(AFX_WM_RESETTOOLBAR, OnToolbarReset)==>afx_msg LRESULT CMainFrame::OnToolbarReset(WPARAM /*wp*/,LPARAM);

3、ON_COMMAND_RANGE(ID_SHORTCUT_1, ID_SHORTCUT_5, OnOutlookBarShortcut)==>void CMainFrame::OnOutlookBarShortcut(UINT id);

4、ON_UPDATE_COMMAND_UI(ID_VIEW_CAPTIONBAR, OnUpdateViewCaptionBar)==>void CMainFrame::OnUpdateViewCaptionBar(CCmdUI* pCmdUI);

相關(guān)文章

  • C語言之實(shí)現(xiàn)控制臺光標(biāo)隨意移動的實(shí)例代碼

    C語言之實(shí)現(xiàn)控制臺光標(biāo)隨意移動的實(shí)例代碼

    下面小編就為大家?guī)硪黄狢語言之實(shí)現(xiàn)控制臺光標(biāo)隨意移動的實(shí)例代碼。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-07-07
  • C語言全面梳理文件操作方法

    C語言全面梳理文件操作方法

    這篇文章主要為大家詳細(xì)介紹了C語言的文件操作,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-05-05
  • C++實(shí)現(xiàn)二維圖形的傅里葉變換

    C++實(shí)現(xiàn)二維圖形的傅里葉變換

    這篇文章主要介紹了C++實(shí)現(xiàn)二維圖形的傅里葉變換的方法,是C++程序設(shè)計(jì)里一個(gè)重要的應(yīng)用,需要的朋友可以參考下
    2014-08-08
  • C語言動態(tài)分配二維字符串?dāng)?shù)組的方法

    C語言動態(tài)分配二維字符串?dāng)?shù)組的方法

    小編最近忙里偷閑,給大家整理一份教程關(guān)于C語言動態(tài)分配二維字符串?dāng)?shù)組的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2021-10-10
  • C++小游戲教程之猜數(shù)游戲的實(shí)現(xiàn)

    C++小游戲教程之猜數(shù)游戲的實(shí)現(xiàn)

    這篇文章主要和大家詳細(xì)介紹如何利用C++做一個(gè)簡易的猜數(shù)游戲,分為用戶猜數(shù)和系統(tǒng)猜數(shù)。文中的示例代碼講解詳細(xì) ,感興趣的小伙伴可以嘗試一下
    2022-11-11
  • C++詳細(xì)分析講解函數(shù)參數(shù)的擴(kuò)展

    C++詳細(xì)分析講解函數(shù)參數(shù)的擴(kuò)展

    在C++中,定義函數(shù)時(shí)可以給形參指定一個(gè)默認(rèn)的值,這樣調(diào)用函數(shù)時(shí)如果沒有給這個(gè)形參賦值(沒有對應(yīng)的實(shí)參),那么就使用這個(gè)默認(rèn)的值。也就是說,調(diào)用函數(shù)時(shí)可以省略有默認(rèn)值的參數(shù)
    2022-04-04
  • C++實(shí)現(xiàn)簡單的圖書管理系統(tǒng)

    C++實(shí)現(xiàn)簡單的圖書管理系統(tǒng)

    本文給大家分享的是使用C++實(shí)現(xiàn)簡單的圖書管理系統(tǒng)的代碼,本系統(tǒng)采用了面向?qū)ο蟮某绦蛟O(shè)計(jì)方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2015-08-08
  • 詳解C語言結(jié)構(gòu)體的定義和使用

    詳解C語言結(jié)構(gòu)體的定義和使用

    這篇文章主要為大家介紹了C語言結(jié)構(gòu)體的定義和使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • C++實(shí)現(xiàn)LeetCode(152.求最大子數(shù)組乘積)

    C++實(shí)現(xiàn)LeetCode(152.求最大子數(shù)組乘積)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(152.求最大子數(shù)組乘積),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C語言結(jié)構(gòu)體詳細(xì)圖解分析

    C語言結(jié)構(gòu)體詳細(xì)圖解分析

    C 數(shù)組允許定義可存儲相同類型數(shù)據(jù)項(xiàng)的變量,結(jié)構(gòu)是 C 編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許你存儲不同類型的數(shù)據(jù)項(xiàng),本篇讓我們來了解C 的結(jié)構(gòu)體
    2022-03-03

最新評論