原文網址:http://zhoumf1214.blog.163.com/blog/static/5241940200910265532959/
最近在用VC2008做開發,后來由於要用到消息的發送,而且需要自定義消息,在網上查找了很多例子,根據他們所說的,雖然大致都差不多,但是基本上沒有一個能完全做出來的。要知道VC編程有一個小地方出錯,都可能是個讓你頭暈腦脹的事情。經過我后來不但探索,經過改進之后,一點錯誤都沒有,現在貼出來供大家參考。
1. 先來個基本知識介紹
SendMessage的基本結構如下:
SendMessage(
HWND hWnd, //消息傳遞的目標窗口或線程的句柄。
UINT Msg, //消息類別(這里可以是一些系統消息,也可以是自己定義,下文具體介紹,)
WPARAM wParam, //參數1 (WPARAM 其實是與UINT是同種類型的,
//在vc編譯器中右鍵有個“轉到WPARAM的定義”的選項可以查看。
LPARAM lParam); //參數2
其中一些參數的由來如下:
//typedef unsigned int UINT;
//typedef UINT WPARAM;
//typedef LONG LPARAM;
//typedef LONG LRESULT;
2. SendMessage用法實例
例如可以用以下語句:
void CTScrollWinView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息處理程序代碼和/或調用默認值
::SendMessage(AfxGetMainWnd()->m_hWnd,WM_CHILDFRAMEDBCLK ,0,0);
CScrollView::OnLButtonDblClk(nFlags, point);
}
這是我用VC2008下建立的一個多文檔選項卡式工程里面的一段代碼,是為了實現在子窗口雙擊后發送一個不帶參數的消息(其ID為WM_USER+1)給主窗口, 如上為部分代碼, 其中WM_CHILDFRAMEDBCLK是自定義的消息ID, AfxGetMainWnd()->m_hWnd是獲得主窗口(這里不能使用GetParent()->m_hWnd或者GetParentFrame()->m_hWnd, 因為這是獲得父窗口,但父窗口不一定是主窗口,一定要注意,不然消息就會發錯導致接收不到,我這里卡了半天,后來在QQ群里一位大俠告訴我的,在此再感謝一下那位大俠);
3. 在接收消息的窗體以及線程所在的頭文件里定義:
#define WM_CHILDFRAMEDBCLK WM_USER+1 // do something
4. 然后接下來定義一個消息需要映射的函數,如下:
afx_msg LRESULT OnChlidFrameDBClick(WPARAM wParam, LPARAM lParam);
注意格式必須是:兩個參數必不可少,返回類型一定為LRESULT,網上很多文章都忽略了這兩點,這也是網上文章普遍錯誤的地方。
5. 添加消息函數映射
ON_MESSAGE(WM_CHILDFRAMEDBCLK,OnChlidFrameDBClick)
注意這里必須是ON_MESSAGE, 不能使用ON_COMMAND, 前者主要針對用戶自定義消息,后者針對
WM_COMMAND命令,比如菜單、工具欄等.
6. 實現消息函數:
我們在接收窗體里定義一個這樣的事情(過程),
LRESULT CMainFrame::OnChlidFrameDBClick(WPARAM wParam, LPARAM lParam)
{
CancelFullScreenWin(); // 這里調用了一個使子窗口全屏的自寫函數,我就不貼出來了,以后專題將的時候會提到
return 0;
}
7. 下面是部分代碼,要想搞清楚自定義消息發送只看這部分代碼就足夠了
在MainFrm.h頭文件里定義了消息如下:
#define WM_CHILDFRAMEDBCLK WM_USER+1
然后在MainFrm.cpp中聲明需要映射的消息函數如下:
afx_msg LRESULT OnChlidFrameDBClick(WPARAM wParam, LPARAM lParam);
再在MainFrm.cpp中添加映射如下:
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx)
ON_WM_CREATE()
ON_COMMAND(ID_FullScreen, OnViewFullscreen)
ON_MESSAGE(WM_CHILDFRAMEDBCLK,OnChlidFrameDBClick) // 映射添加到這里
END_MESSAGE_MAP()
然后在MainFrm.cpp中實現OnChlidFrameDBClick()方法,如下:
LRESULT CMainFrame::OnChlidFrameDBClick(WPARAM wParam, LPARAM lParam)
{
CancelFullScreenWin();//自己定義的函數,你們可以在這里完成自己需要的業務
return true;
}
最后就可以發送消息給主窗口了,如下:
void CTScrollWinView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息處理程序代碼和/或調用默認值
::SendMessage(AfxGetMainWnd()->m_hWnd,WM_USER+1,0,0);
CScrollView::OnLButtonDblClk(nFlags, point);
}
總結一下:①注意定義消息的ID不能重復,要用WM_USER+n;
②注意定義的消息函數的返回值一定是LRESULT, 並且有兩個參數分別必須為WPARAM和LPARAM ;
③注意映射用ON_MESSAGE, 而不是ON_COMMAND;
④注意傳給主窗口的消息在CXXXXView類中要用AfxGetMainWnd()->m_hWnd獲得主窗口。
至此就講完了,希望對大家找不對資源的有所幫助
MFC退出程序
原文網址:http://blog.csdn.net/one___thousand/article/details/40212369
PostQuitMessage(0);
PostMessage(WM_QUIT,0,0);
::SendMessage(AfxGetMainWnd()->m_hWnd,WM_CLOSE,0,0);
::PostMessage(AfxGetMainWnd()->m_hWnd,WM_CLOSE,0,0);
ExitProcess(0);//注意使用時先釋放分配的內存,以免造成內存泄露
exit(0) ;//正常終止程序; exit(非0)非正常終止程序
SendMessage(WM_CLOSE); //向主窗口發送WM_CLOSE消息
AfxGetMainWnd->SendMessage(WM_CLOSE); //在其它類關閉應用程序
MFC獲取句柄的方法
句柄獲取方法(獲取該窗口的句柄后,即可向該窗口類類發送消息、處理程序):
例如:::PostMessage("句柄", WM_USER_DRAWVIEWPIC_EDS, 0, 0);
0。獲取所在類窗口的句柄:
this->m_hwnd
1。主窗口的句柄:
無論在主窗口類內,還是子窗口類內,獲取主窗口句柄的方法:
AfxGetMainWnd()->m_hWnd,
如:::SendMessage(AfxGetMainWnd()->m_hWnd , WM_MY_DOSOME , 0 ,(LPARAM)i);
在窗口類中
this->m_hWnd
或者this->GetSafeHwnd()
2。子窗口句柄:用FindWindow,(只要知道子窗口的名字即可)如:
::FindWindow(NULL,WindowsName)
返回找到的窗口的句柄
尋找當前窗口是否在運行windowname的程序,該名字為窗口名字,如:
CWnd* pWnd=FindWindow(NULL,_T("清芝--支票機"));//
GetSafeHwnd
函數功能:獲取某個窗口對象(CWnd的派生對象)指針的句柄(HWND)時,最安全的方法是使用
GetSafeHwnd()函數。
通過下面的例子來看其理由:
CWnd *pwnd = FindWindow(“ExploreWClass”,NULL); //希望找到資源管理器
HWND hwnd = pwnd->m_hwnd; //得到它的HWND
這樣的代碼當開始得到的pwnd為空的時候就會出現一個“General protection error”,並關閉應用
程序,因為一般不能對一個NULL指針訪問其成員,如果用下面的代碼:
CWnd *pwnd = FindWindow(“ExploreWClass”,NULL); //希望找到資源管理器
HWND hwnd = pwnd->GetSafeHwnd(); //得到它的HWND
就不會出現問題,因為盡管當pwnd是NULL時,GetSafeHwnd仍然可以用,只是返回NULL
源文檔 <http://blog.csdn.net/luheng2006/article/details/5897643>
3。獲取窗口中 控件的句柄,用 GetDlgItem
語法為:GetDlgItem(IDC_COMBO3)->m_hWnd :參數為 該控件的ID,返回值為:CWnd* 類型,但它是CWnd類
內的函數,因此要先獲取控件所在窗口的指針,如:
CString str(_T("dd"));
::SendMessage(AfxGetMainWnd()->GetDlgItem(IDC_COMBO3)->m_hWnd, WM_SETTEXT , 0 , (LPARAM)
str.GetBuffer(0));
從句柄獲得指針,用 FromHandle
語法:CWnd* pWnd = CWnd::FromHandle(hWnd);
獲取窗口句柄(全集) vc&MFC
獲得窗口句柄:
this->m_hwnd
HWND GetForegroundWindow(VOID);
GetSafehWnd 取你程序所在窗口類的句柄
GetActiveWindow 取當前活動窗口句柄
AfxGetMainWnd 取主窗口句柄
GetForegroundWindow 取前台窗口句柄
FindWindow
EnumWindow
