VC++ 自定义消息学习总结
生活随笔
收集整理的這篇文章主要介紹了
VC++ 自定义消息学习总结
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
VC添加自定義消息
http://blog.csdn.net/jinnee_cumtb/article/details/4524375?
? VC的ClassWizard不允許增加用戶自定義消息,所以你必須手工進(jìn)行添加。當(dāng)你添加了自定義的消息以后,ClassWizard就可以像處理其它消息一樣處理你定義的消息了。
一、VC6添加自定義消息
? ? 1、定義消息。在Windows中,所有的消息都用一個特定的整數(shù)值來表示,為了避免自定義消息與已存在的其他消息發(fā)生沖突,應(yīng)該利用Windows提供 的一個常量:WM_USER,小于這個常量的是系統(tǒng)保留的。即用戶自定義的消息至少為WM_USER+1,注意最后表示的消息的數(shù)值不要超過 0x7FFF。在開發(fā)Windows95應(yīng)用程序時,Microsoft推薦用戶自定義消息至少是WM_USER+100,因?yàn)楹芏嘈驴丶惨褂?WM_USER消息。
? ? #define UM_PROGRESS WM_USER + 100
? ? 2、在類頭文件的AFX_MSG塊中聲明消息處理函數(shù):
? ? class CMainFrame:public CFrameWnd{
? ? protected:
? ? //{{AFX_MSG(CMainFrame)
? ? afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
? ? afx_msg void OnTimer(UINT nIDEvent);
? ? afx_msg LRESULT OnProgress(WPARAM wParam, LPARAM lParam);
? ? //}}AFX_MSG
? ? DECLARE_MESSAGE_MAP()
? ? 3、在類的實(shí)現(xiàn)文件中,使用ON_MESSAGE宏指令將消息映射到消息處理表中。
? ? BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
? ? //{{AFX_MSG_MAP(CMainFrame)
? ? ? ? ON_WM_CREATE()
? ? ? ? ON_WM_TIMER()
? ? ? ? ON_MESSAGE(UM_PROGRESS, OnProgress)//注意這條語句的后面沒有分號
? ? //}}AFX_MSG_MAP
? ? END_MESSAGE_MAP()?
? ? 4、實(shí)現(xiàn)消息處理函數(shù)。該函數(shù)使用WPRAM和LPARAM參數(shù)并返回LPESULT。
? ? LPESULT CMainFrame::OnProgress(WPARAM wParam,LPARAM lParam){
? ? ? ?CRect rect;
? ? ? ?m_wndStatusBar.GetItemRect(2,&rect); //獲得窗格區(qū)域
? ? ? ?//創(chuàng)建進(jìn)度欄,注意第三個參數(shù)為CWnd* pParentWnd,根據(jù)情況選擇父窗體
? ? ? ?m_progress.Create(WS_CHILD|WS_VISIBLE|PBS_VERTICAL,rect,this,123);
? ? ? ?m_progress.SetPos(50);
? ? ? ?return 0;
? ? }
? ? 5、在適當(dāng)?shù)臅r候發(fā)送自定義消息,進(jìn)行消息處理。需要注意使用SendMessage還是PostMessage進(jìn)行處理:SendMessage是消息處理完畢后再返回;而PostMessage則是把消息放到消息隊(duì)列后立即返回。
? ? SendMessage(UM_PROGRESS);?
? ? PostMessage(UM_PROGRESS); ? ?
? ? 如果用戶需要整個系統(tǒng)唯一的消息,可以調(diào)用SDK函數(shù)RegisterWindowMessage并使用ON_REGISTER_MESSAGE宏指令取代ON_MESSAGE宏指令,其余步驟同上。
二、VC2003添加自定義消息
? ? 在VC2003中添加自定義消息和VC6基本一致。需要注意的是VC6處理的消息可以沒有參數(shù),但VC2003消息處理的函數(shù)必須帶有兩個參數(shù) wParam和lParam,并且其返回值類型為LRESULT。這里,還有另一種方法可以實(shí)現(xiàn)地定義消息的處理(VC6和VC2003均適用):
? ? 1、定義消息:#define UM_PROGRESS WM_USER + 100
? ? 2、重載CMainFrame的DefWindowProc函數(shù),然后添加對用戶自定義消息處理:
? ? LRESULT CMainFrame::DefWindowProc(UINT message, WPARAM wParam,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? LPARAM lParam){
? ? ? ? switch(message){
? ? ? ?case UM_PROGRESS:{
? ? ? ? ? ? //通過指定資源ID獲得相應(yīng)的索引
? ? ? ? ? ? int index = m_wndStatusBar.CommandToIndex(IDS_PROGRESS);?
? ? ? ? ? ?CRect rect;
? ? ? ? ? m_wndStatusBar.GetItemRect(index,&rect);
? ? ? ? ? ?m_progress.Create(WS_CHILD|WS_VISIBLE,rect, &m_wndStatusBar
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ,123);
? ? ? ? ? ?m_progress.SetPos(50);
? ? ? ? ? ?break;
? ? ? ? }
? ? ? ? default:
? ? ? ? ? ? break;
? ? ?}
? ? ?return CFrameWnd::DefWindowProc(message, wParam, lParam);
? ? }
========
自定義消息
http://www.cnblogs.com/xydblog/archive/2014/02/25/3566266.html一、實(shí)現(xiàn)過程
1. 使用宏定義消息ID,例如:
#define ? WM_OCRRESULT (WM_USER+101)
其中WM_USER為系統(tǒng)消息和用戶自定義消息的分界線,小于WM_USER的消息被系統(tǒng)所占用,如:WM_LBUTTONDOWN消息,大于WM_USER的消息為用戶自定義消息;
2. 在類聲明AFX_MSG塊中聲明消息響應(yīng)函數(shù)的原型,例如:
afx_msg void OnOcrResult(WPARAM wParam, LPARAM lParam); ? 函數(shù)可以有返回值,也可以無返回值; 函數(shù)原型可以有參數(shù),也可以無參數(shù),如果無參數(shù),經(jīng)常導(dǎo)致在debug下正常運(yùn)行,release下程序就奔潰了。
復(fù)制代碼
class CDlgOCRMain : public CDialog
{
protected:?
? ? // Generated message map functions
? ? //{{AFX_MSG(CDlgOCRMain)
? ? virtual BOOL OnInitDialog();
? ? afx_msg void OnDestroy();
? ? afx_msg void OnSize(UINT nType, int cx, int cy);
? ? afx_msg BOOL OnEraseBkgnd(CDC *pDC);
? ? afx_msg void OnPaint();
? ? afx_msg void OnOcrResult(WPARAM wParam, LPARAM lParam);
? ? //}}AFX_MSG?
? ? DECLARE_MESSAGE_MAP()
}
3. 在用戶類的消息塊中,使用ON_MESSAGE宏指令將消息映射到消?
息處理函數(shù)中,格式為:ON_MESSAGE(MsgID,MsgFun)
注意:ON_MESSAGE一定要放到AFX_MSG_MAP之后,END_MESSAGE_MAP()之前
BEGIN_MESSAGE_MAP(CDlgOCRMain, CDialog)
? ? //{{AFX_MSG_MAP(CDlgOCRMain)
? ? ON_WM_DESTROY()
? ? ON_WM_SIZE()
? ? ON_WM_ERASEBKGND()
? ? ON_WM_PAINT()
? ? //}}AFX_MSG_MAP?
? ? ON_MESSAGE(WM_OCRRESULT, OnOcrResult)?
END_MESSAGE_MAP()
? 4. 實(shí)現(xiàn)消息處理函數(shù)
void CDlgOCRMain::OnOcrResult(WPARAM wParam, LPARAM lParam)
{
? //........................ ? ? ? ? ? ? ??
}
?二、自定義消息出錯
如果我們消息響應(yīng)函數(shù)原型為: afx_msg void OnXXXX(); 則在經(jīng)常導(dǎo)致在debug下正常運(yùn)行,release下程序就奔潰了。
解決方法:
將afx_msg void OnXXXX()改為afx_msg void OnXXXX(WPARAM wParam, LPARAM lParam);
原因:
當(dāng)有自定義的消息產(chǎn)生時,系統(tǒng)會調(diào)用自定義消息處理函數(shù),系統(tǒng)想當(dāng)然的認(rèn)為這個函數(shù)有兩個參數(shù),分別是WPARAM wParam和LPARAM lParam。系統(tǒng)在調(diào)用函數(shù)時,會把這兩個參數(shù)壓棧。 然而函數(shù)自身并沒有參數(shù)。在release優(yōu)化的情況下,在返回上一級函數(shù)時,依據(jù)的是這個函數(shù)的自動變量,參數(shù)等信息,于是這兩個參數(shù)被系統(tǒng)留了下來,也就是說參數(shù)仍然保存在棧中,這樣就產(chǎn)生了沖突,所以程序就崩潰了。
在debug下,每調(diào)用一個函數(shù)時,系統(tǒng)會把當(dāng)前函數(shù)在堆棧中的位置保存在一個寄存器中(SP),當(dāng)函數(shù)執(zhí)行完畢后返回上一級函數(shù)時,SP指針返回到函數(shù)調(diào)用前SP指針指向的位置。也就是說保證了入棧和出棧的一致性。
========
VC/MFC中如何自定義消息
定義一個自定義消息號:const UINT WM_MYMESSAGE = WM_USER + n; // 自定義消息一般大于WM_USER,然后就可以為該消息添加映射了。
afx_msg LRESULT OnMyMessage ( WPARAM wParam, LPARAM lParam );
ON_MESSAGE ( WM_MYMESSAGE, OnMyMessage )
LRESULT cxx::OnMyMessage ( WPARAM wParma, LPARAM lParam )
{
...
}
如果該消息不需要返回值,也不需要參數(shù),那么可以使用宏ON_MESSAGE_VOID來映射
afx_msg void OnMyMessage ();
ON_MESSAGE_VOID ( WM_MYMESSAGE, OnMyMessage )
void cxx::OnMyMessage ()
{
...
}
復(fù)雜全面版本:
消息映射、循環(huán)機(jī)制是Windows程序運(yùn)行的基本方式。VC++ MFC 中有許多現(xiàn)成的消息句柄,可當(dāng)我們需要完成其它的任務(wù),需要自定義消息,就遇到了一些困難。在MFC ClassWizard中不允許添加用戶自定義消息,所以我們必須在程序中添加相應(yīng)代碼,以便可以象處理其它消息一樣處理自定義消息。通常的做法是采取以下步驟:
第一步:定義消息。
推薦用戶自定義消息至少是WM_USER+100,因?yàn)楹芏嘈驴丶惨褂肳M_USER消息。
#define WM_MY_MESSAGE (WM_USER+100)
第二步:實(shí)現(xiàn)消息處理函數(shù)。該函數(shù)使用WPRAM和LPARAM參數(shù)并返回LPESULT。
LPESULT CMainFrame::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
// TODO: 處理用戶自定義消息
...
return 0;
}
第三步:在類頭文件的AFX_MSG塊中說明消息處理函數(shù):
class CMainFrame:public CMDIFrameWnd
{
...
// 一般消息映射函數(shù)
protected:
// {{AFX_MSG(CMainFrame)
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT nIDEvent);
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
}
第四步:在用戶類的消息塊中,使用ON_MESSAGE宏指令將消息映射到消息處理函數(shù)中。
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
//{{AFX_MSG_MAP(CMainFrame)
ON_WM_CREATE()
ON_WM_TIMER()
ON_MESSAGE(WM_MY_MESSAGE, OnMyMessage)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
如果用戶需要一個定義整個系統(tǒng)唯一的消息,可以調(diào)用SDK函數(shù)RegisterWindowMessage定義消息:
static UINT WM_MY_MESSAGE=RegisterWindowMessage(User);
并使用ON_REGISTERED_MESSAGE宏指令取代ON_MESSAGE宏指令,其余步驟同上。
當(dāng)需要使用自定義消息時,可以在相應(yīng)類中的函數(shù)中調(diào)用函數(shù)PostMessage或SendMessage發(fā)送消息PoseMessage(WM_MY_MESSAGE,O,O); 如果向其他進(jìn)程發(fā)送消息可通過如下方法發(fā)送消息:
DWORD result;
SendMessageTimeout(wnd->m_hWnd, // 目標(biāo)窗口
WM_MY_MESSAGE, // 消息
0, // WPARAM
0, // LPARAM
SMTO_ABORTIFHUNG |
SMTO_NORMAL,
TIMEOUT_INTERVAL,
&result);
以避免其它進(jìn)程如果被阻塞而造成系統(tǒng)死等狀態(tài)。
可是如果需要向其它類(如主框架、子窗口、視類、對話框、狀態(tài)條、工具條或其他控件等)發(fā)送消息時,上述方法顯得無能為力,而在編程過程中往往需要獲取其它類中的某個識別信號,MFC框架給我們造成了種種限制,但是可以通過獲取某個類的指針而向這個類發(fā)送消息,而自定義消息的各種動作則在這個類中定義,這樣就可以自由自在的向其它類發(fā)送消息了。
下面舉的例子敘述了向視類和框架類發(fā)送消息的方法:
在主框架類中向視類發(fā)送消息:
視類中定義消息:
ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage) //定義消息映射
視類定義消息處理函數(shù):
// 消息處理函數(shù)
LRESULT CMessageView::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
// TODO: 處理用戶自定義消息
...
return 0;
}
//發(fā)送消息的測試函數(shù)
void CMainFrame::OnTest()
{
CView * active = GetActiveView();//獲取當(dāng)前視類指針
if(active != NULL)
active->PostMessage(WM_MY_MESSAGE,0,0);
}
在其它類中向視類發(fā)送消息:
//發(fā)送消息的測試函數(shù)
void CMainFrame::OnTest()
{
CMDIFrameWnd *pFrame;
CMDIChildWnd *pChild;
CView *pView;
//獲取主窗口指針
pFrame =(CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;
// 獲取子窗口指針
pChild = (CMDIChildWnd *) pFrame->GetActiveFrame();
//獲取視類指針
pView = pChild->GetActiveView();
if(pView != NULL)
pView->PostMessage(WM_MY_MESSAGE,0,0);//發(fā)送消息
}
其余步驟同上。
在視類中向主框架發(fā)送消息:
首先在主框架中定義相關(guān)的消息,方法同上,然后在發(fā)送消息的函數(shù)中添加代碼如下
//發(fā)送消息的測試函數(shù)
void CMessageView::OnTest()
{
CFrameWnd * active = GetActiveFrame();//獲取當(dāng)前主窗口框架指針
if(active != this)
active->PostMessage(WM_MY_MESSAGE,0,0);
return 0;
}
在其它類中向不同的類發(fā)送消息可依次方法類推,這樣我們的程序就可以的不受限制向其它類和進(jìn)程發(fā)送消息,而避免了種種意想不到的風(fēng)險。
下面一個例子程序?yàn)槎辔臋n程序里在一對話框中向視類發(fā)送消息,詳述了發(fā)送自定義消息的具體過程。
實(shí)現(xiàn)步驟:
第一步:在VC++中新建工程Message,所有ClassWizard步驟選項(xiàng)均為缺省,完成。
第二步:在主菜單中添加測試菜單為調(diào)出對話框,在框架類中建立相應(yīng)函數(shù)OnTest()
第三步:在資源中建立對話框,通過ClassWizard添加新類TestDialog,添加測試按鈕,
在對話框類中建立相應(yīng)函數(shù)OnDialogTest()
//通過對話框按鈕發(fā)送消息的函數(shù)
void TestDialog::OnDialogTest()
{
CMDIFrameWnd *pFrame;
CMDIChildWnd *pChild;
CView *pView;
//獲取主窗口指針
pFrame =(CMDIFrameWnd*)AfxGetApp()->m_pMainWnd;
// 獲取子窗口指針
pChild = (CMDIChildWnd *) pFrame->GetActiveFrame();
//獲取視類指針
pView = pChild->GetActiveView();
if(active != NULL)
active->PostMessage(WM_MY_MESSAGE,0,0);//發(fā)送消息
}
在Message.h頭文件中添加如下語句:
static UINT WM_MY_MESSAGE=RegisterWindowMessage(Message);
第四步:在視類中添加自定義消息:
在頭文件MessageView.h中添加消息映射
protected:
//{{AFX_MSG(CMessageView)
//}}AFX_MSG
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam); //此行為添加代碼
DECLARE_MESSAGE_MAP()
在視類文件MessageView.cpp中的消息映射中添加自定義消息映射
BEGIN_MESSAGE_MAP(CMessageView, CView)
//{{AFX_MSG_MAP(CMessageView)
//}}AFX_MSG_MAP
// Standard printing commands
ON_REGISTERED_MESSAGE(WM_MY_MESSAGE,OnMyMessage) //此行添加代碼定義唯一消息
END_MESSAGE_MAP()
添加相應(yīng)的0消息處理函數(shù)
LRESULT CMessageView::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
CRect rect;
GetClientRect(&rect);
InvalidateRect(&rect);
test=!test;
return 0;
}
在MessageView.h中添加布爾變量 public:BOOL test;
在視類構(gòu)造函數(shù)中初始化 test變量:test=FALSE;
修改CMessageView::OnDraw()函數(shù)
void CMessageView::OnDraw(CDC* pDC)
{
CMessageDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// 以下程序顯示消息響應(yīng)效果
if(test)
pDC->TextOut(0,0,消息響應(yīng)!);
}
第五步:顯示測試對話框
在MainFrame類中包含對話框頭文件:
#include TestDialog.h;
OnTest()函數(shù)中添加代碼
void CMainFrame::OnTest()
{
TestDialog dialog;
dialog.DoModal();
}
運(yùn)行程序,在測試菜單打開對話框,點(diǎn)擊測試按鈕即可看到結(jié)果。
========
MFC中自定義消息
http://blog.csdn.net/qihailong123456/article/details/6777112這篇技術(shù)文章不是討論經(jīng)典的MFC中的消息工作機(jī)理的,討論消息工作原理、方式和路徑的文章在網(wǎng)上和書本中
隨處可見。網(wǎng)上眾多的討論都是關(guān)于如何響應(yīng)并進(jìn)行用戶自定義消息映射的;網(wǎng)上還有一些文章介紹如何在自定
義類中響應(yīng)Windows消息,在本文中都簡略敘述。但是,網(wǎng)上大部分的文章沒用透徹闡述如何在用戶自定義類中
響應(yīng)自定義消息這一通用方法。?
問題定義如下:用戶自定義一個類,這個類不一定要有界面(完全可以是不可視的),要求自定義的類可以響應(yīng)
某個自定義消息。
首先能夠響應(yīng)消息的類必須都從CCmdTarget類中派生,因?yàn)橹挥幸赃@個類中提供了消息的框架和處理機(jī)制,而
CWnd類也派生與此類。CWinApp類、CDocument類、CDocTemplate類等都是CCmdTarget的派生類,即子類;而
CFrameWnd類、CView類、CDialog類等都是從CWnd中派生的,其實(shí)也是CCmdTarget的子孫,所以都能夠響應(yīng)消息
,但是響應(yīng)消息的種類不太相同。
那么,如果自己定義的類要求響應(yīng)命令消息(就是WM_COMMAND,也就是一些菜單、工具欄中的消息,包括快捷鍵
,這類消息處理的機(jī)制與其他以WM_開頭的消息處理機(jī)制不同,它具有一條層次明確的消息流動路徑),那么自
定義的類可以從CCmdTarget中派生。由于CWnd窗體類派生于CCmdTarget父類,那么從CWnd中派生的類也可以理所
應(yīng)當(dāng)?shù)捻憫?yīng)命令消息。這種命令消息無論是往已有的一些諸如CWinApp類中還是自定義的類中添加都是一件非常
容易的事情,只需用向?qū)Ъ纯?#xff0c;在此不再敘述。
如果用戶自定義的類要求響應(yīng)普通的Windows消息(也就是以WM_開頭,除了WM_COMMAND以外的消息,這類消息在
WM_USER以下的是系統(tǒng)消息,WM_USER以上的可以由用戶自己定義),那就要求自定義的類必須從CWnd中派生。這
是由于此類消息的處理機(jī)制決定的,這類消息沒有命令消息那條繁瑣的流動路徑,而是消息發(fā)出者直接發(fā)給對應(yīng)
CWnd的窗體句柄,由CWnd負(fù)責(zé)消息的響應(yīng)。所以這類消息必須同一個CWnd類對應(yīng),更精確的說必須與一個HWND類
型的窗體句柄相對應(yīng)。這樣得出一個重要的結(jié)論,就是從CCmdTarget中派生而沒有從CWnd派生的類沒有處理此類
消息的能力。
綜上所述,就是為什么命令消息可以放到大部分類中處理,包括CWinThread、CWinApp、CDocument、CView、
CFrameWnd或是自定義的類中,而普通Windows消息和用戶自定義的消息只能放到CFrameWnd和CView等派生與CWnd
中的類中處理。
由此可見,我們自定義的類要想響應(yīng)自定義消息就只能從CWnd中派生(當(dāng)然不響應(yīng)任何消息的類可以從CObject
中派生)。先來看看如何自定義消息:
在.h中做的工作:
第一步要聲明消息:
#define WM_MYMSG WM_USER+8
第二步要在類聲明中聲明消息映射:
DECLARE_MESSAGE_MAP()
第三步要在類聲明中定義消息處理函數(shù):
afx_msg LRESULT MyMsgHandler(WPARAM,LPARAM);
在.cpp中做的工作:
第四步要實(shí)現(xiàn)消息映射:
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
ON_MESSAGE(WM_MYMSG,OnMyMsgHandler)
END_MESSAGE_MAP()
第五步要實(shí)現(xiàn)消息處理函數(shù)(當(dāng)然可以不實(shí)現(xiàn)):
LRESULT CMainFrame::OnMyMsgHandler(WPARAM w,LPARAM l)
{
AfxMessageBox("Hello,World!");
return 0;?
}
在引發(fā)或發(fā)出消息的地方只用寫上:
::SendMessge(::AfxGetMainWnd()->m_hWnd,WM_MYMSG,0,0);
到此,自定義消息完畢,這是好多網(wǎng)上文章都寫的東西。大家會發(fā)現(xiàn)上面代碼是在CMainFrame類中實(shí)現(xiàn)的,但是
如果要用自定義類,就沒有那么簡單了。顯然把第四步與第五步的CMainFrame換成自定義的類名(這里我用
CMyTestObject來代表自定義類)是不能正常工作的。原因在于在發(fā)送消息的SendMessage函數(shù)中的第一個參數(shù)是
要響應(yīng)消息對應(yīng)的HWND類型的窗體句柄,而CMyTestObject類中的m_hWnd中在沒有調(diào)用CWnd::Create之前是沒有
任何意義的,也就是沒有調(diào)用CWnd::Create或CWnd::CreateEx函數(shù)時,CWnd不對應(yīng)任何窗體,消息處理不能正常
運(yùn)作。
所以,又一個重要的結(jié)論,在自定義類能夠處理任何消息之前一定要確保m_hWnd關(guān)聯(lián)到一個窗體,即便這個窗體
是不可見的。那么有人說,在自定義類的構(gòu)造函數(shù)中調(diào)用Create函數(shù)就行了,不錯,當(dāng)然也可以在別處調(diào)用,只
要確保在消息發(fā)送之前。但是,Create的調(diào)用很有說法,要注意兩個地方,第一個參數(shù)是類的名稱,我建議最好
設(shè)為NULL;第五個參數(shù)是父窗體對象的指針,這個函數(shù)指定的對象一定要存在,我建議最好為整個程序的主窗體
。還有很多人問第六個參數(shù)的意義,這個參數(shù)關(guān)系不大,是子窗體ID,用于傳給父窗體記錄以便識別。如下是我
的自定義類的構(gòu)造函數(shù):
CMyTestObject::CMyTestObject()
{
CWnd::Create(NULL,"MyTestObject",WS_CHILD,CRect(0,0,0,0),::AfxGetMainWnd(),1234);
} ? ?//一定要在生成主窗體后使用,在主窗體完成OnCreate消息的處理后
CMyTestObject::CMyTestObject(CWnd *pParent)
{
CWnd::Create(NULL,"MyTestObject",WS_CHILD,CRect(0,0,0,0),pParent,1234);
}
不能如下調(diào)用Create,因?yàn)榇藭rCMyTestObject不關(guān)聯(lián)任何窗體,所以this中的m_hWnd無效:
CWnd::Create(NULL,"MyTestObject",WS_CHILD,CRect(0,0,0,0),this,1234);
這時上面四、五兩步修改成:
BEGIN_MESSAGE_MAP(CMyTestObject, CWnd)
ON_MESSAGE(WM_MYMSG,OnMyMsgHandler)
END_MESSAGE_MAP()
LRESULT CMyTestObject::OnMyMsgHandler(WPARAM w,LPARAM l)
{
AfxMessageBox("My Messge Handler in My Self-Custom Class!");
return 0;?
}
在類外部發(fā)出消息:
CMyTestObject *test=new CMyTestObject();
::SendMessage(test->m_hWnd,WM_MYMSG,0,0);
在類內(nèi)部某個成員函數(shù)(方法)中發(fā)出消息:
::SendMessage(m_hWnd,WM_MYMSG,0,0);
最后一個問題便是容易產(chǎn)生警告錯誤的窗體回收,自定義的類要顯式調(diào)用窗體銷毀,析構(gòu)函數(shù)如下:
CMyTestObject::~CMyTestObject()
{
CWnd::DestroyWindow();
}
?
========
vc中SendMessage自定義消息函數(shù)用法實(shí)例
http://www.jb51.net/article/56565.htm這篇文章主要介紹了vc中SendMessage自定義消息函數(shù)用法,以實(shí)例實(shí)行詳細(xì)講述了SendMessage的定義、原理與用法,具有一定的實(shí)用價值,需要的朋友可以參考下
..本文實(shí)例講述了vc中SendMessage自定義消息函數(shù)用法,分享給大家供大家參考。具體如下:
SendMessage的基本結(jié)構(gòu)如下:
復(fù)制代碼 代碼如下:SendMessage(
? ? HWND hWnd, ?//消息傳遞的目標(biāo)窗口或線程的句柄。
? ? UINT Msg, //消息類別(這里可以是一些系統(tǒng)消息,也可以是自己定義,下文具體介紹,)
? ? WPARAM wParam, //參數(shù)1 (WPARAM 其實(shí)是與UINT是同種類型的,
? //在vc編譯器中右鍵有個“轉(zhuǎn)到WPARAM的定義”的選項(xiàng)可以查看。?
? ? LPARAM lParam); //參數(shù)2
其中一些參數(shù)的由來如下:
//typedef unsigned int UINT;
//typedef UINT WPARAM;
//typedef LONG LPARAM;
//typedef LONG LRESULT;
例如可以用以下語句:
復(fù)制代碼 代碼如下:::SendMessage(this->m_hWnd, WM_MY_DOSOME, (WPARAM) 0, (LPARAM) 0);
這里我發(fā)送的消息是本窗體接收的,所以句柄用:this->m_hWnd
這里的消息類別WM_MY_DOSOME就是我自定義的,
在接收消息的窗體或線程所在的頭文件里:
復(fù)制代碼 代碼如下:#define WM_MY_DOSOME WM_USER+1 // do something
當(dāng)然你還可以定義更多如:
復(fù)制代碼 代碼如下:#define WM_DOOTHER WM_USER+2 // do other
表示要做一些事情。
到這里,可能大家還是對消息類別有點(diǎn)模糊,不要擔(dān)心,下面很快就講到。
我們發(fā)了一個消息出去,那么接收方要能識別這個消息是干什么,就是通過消息類別來區(qū)分,并且開始去做這個消息對應(yīng)要處理的事情。如下:
一、編寫一個事情:
我們在接收窗體里定義一個這樣的事情(過程),
復(fù)制代碼 代碼如下:afx_msg LRESULT DoSomeThing(WPARAM iParam1,LPARAM iParam2)
{
?MessageBox("收到消息了,我要開始做一些事情了。","收到",MB_OK);
?//可以運(yùn)用iParam1,iParam2 來做一些事情。
?return 0;
}
這個事情有3點(diǎn)大家要注意,非常重要:
1. 使用了afx_msg,并且要將afx_msg LRESULT DoSomeThing(WPARAM iParam1,LPARAM iParam2)
改寫到頭文件的?
//{{AFX_MSG?
//。。。改寫到這里,顏色會變成灰的。這一點(diǎn)非常重要。
//}}AFX_MSG
2. 參數(shù)有2個,WPARAM iParam1,LPARAM iParam2,哪怕沒有東西傳進(jìn)來也要寫,不然會吃苦頭的,vc里不會提醒你少寫了一個,
但一些莫名奇妙的事情會發(fā)生。
3. 類型用 LRESULT,完了要return 0;
二、讓接收方知道什么時候做這個事情:
我們在
復(fù)制代碼 代碼如下://{{AFX_MSG_MAP
//。。。這里寫上
ON_MESSAGE(WM_MY_DOSOME,DoSomeThing)
//如果還有其他消息就再寫一個
ON_MESSAGE(WM_DOOTHER,DoOther)
//}}AFX_MSG_MAP
到這里,當(dāng)你用SendMessage,發(fā)了一個WM_MY_DOSOME類型的消息過來的時候,接收方就會去做DoSomeThing(WPARAM iParam1,LPARAM iParam2)
發(fā)了一個WM_DOOTHER類型的消息過來的時候,接收方就會去做DoOther(WPARAM iParam1,LPARAM iParam2)當(dāng)然,這里DoOther我還沒有定義。
這樣就是一個完整的消息發(fā)送與接受過程,這里沒有詳細(xì)講參數(shù),iParam1,因?yàn)檫€沒有用到很復(fù)雜的情況,
在頭文件里:
復(fù)制代碼 代碼如下:#define WM_MYMSG ?WM_USER+5 //自定義一個消息
afx_msg void OnMyMessage(WPARAM wParam, LPARAM lParam); //自定義消息的處理函數(shù)聲明
在.cpp文件里:
復(fù)制代碼 代碼如下:ON_MESSAGE(WM_MYMSG, OnMyMessage)
//利用ON_MESSAGE()宏在自定義消息與其處理函數(shù)間建立映射關(guān)系
void CModelessDlg::OnMyMessage(WPARAM wParam, LPARAM lParam)
//從lParam中取出CString對象的指針,并將字符串內(nèi)容在IDC_MSGEDIT中顯示出來
{
? ? CString *str;
? ? str=(CString *)lParam;
? ? SetDlgItemText(IDC_EDIT,*str);
}
按下按鈕發(fā)送消息
復(fù)制代碼 代碼如下:void CModelessDlg::OnMsgBTN()?
{
?CString str= "自定義消息被觸發(fā)了!";
?SendMessage(WM_MYMSG, 0, (LPARAM) &str);
?//給ModelessDlg自己發(fā)一個自定義的消息
}
希望本文所述對大家的VC程序設(shè)計(jì)有所幫助。
========
總結(jié)
以上是生活随笔為你收集整理的VC++ 自定义消息学习总结的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# 模板编程相关学习总结
- 下一篇: windbg !htrace 学习总结