以前這些消息用得比較少,但是今天碰到了個事兒,我看非用消息不可。
事情是這樣的,我在線程中需要刷新對話框上面的內容,但是每每執行到UpdateData時就出現了斷言錯誤。
查了相關資料,發現這個可能是多個模塊調用同一個方法出現的問題。反正照我之前的邏輯走不通。
我現在將更新對話框信息的函數,通過線程中發窗口消息,讓對話框的消息處理函數來負責處理我自定義的消息,為我刷新對話框數據。
// http://blog.csdn.net/a8082649/article/details/7733527
1.自定義消息ID。
#define WM_MY_MESSAGE (WM_USER+100) WM_USER為windows系統為非系統消息保留的ID,這里至少要用100,因為其它控件的消息會占用一部分。
2. 定義消息處理函數。
消息處理函數為消息目標類的成員函數。首先應該在.h 文件中聲明。這里以主窗口類為例,主窗口類名 CMainDialog,則首先在CMainDialog.h聲明消息處理函數。
protected:
afx_msg LRESULT OnMyMessage(WPARAM wParam, LPARAM lParam);
3.在CMainDialog.cpp中實現消息處理函數
LPESULT CMainDialog::OnMyMessage(WPARAM wParam, LPARAM lParam) { // TODO: 處理用戶自定義消息 ... return 0; }
4.在CMainDialog.cpp中映射消息ID和消息處理函數
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()
在創建線程的時候將主窗口句柄作為參數傳入線程,就可以用 PostMessage傳遞消息了。
消息預處理函數
添加消息處理函數PreTranslateMessage,此函數可以通過MFC ClassWizard添加
- BOOL CPreTranslateMessageDlg::PreTranslateMessage(MSG* pMsg)
- {
- if (pMsg->message==WM_LBUTTONDOWN)
- {
- MessageBox("三三四四");
- }
- return CDialog::PreTranslateMessage(pMsg);
- }
此函數為手動添加的消息函數,可通過pMsg->message來判斷是什么消息,比如WM_LBUTTONDOWN是左鍵單擊消息,那當單擊左鍵時就會執行此函數,同樣當敲擊一下鍵盤也會執行PreTranslateMessage函數
// ===================================================================================================================
SendMessage函數功能:該函數將指定的消息發送到一個或多個窗口。此函數為指定的窗口調用窗口程序,直到窗口程序處理完消息再返回。而函數PostMessage不同,將一個消息寄送到一個線程的消息隊列后立即返回。
函數原型 :
LRESULT SendMessage(HWND hWnd,UINT wMsg,WPARAM wParam,LPARAM IParam);
參數:
hWnd:其窗口程序將接收消息的窗口的句柄。如果此參數為HWND_BROADCAST,則消息將被發送到系統中所有頂層窗口,包括無效或不可見的非自身擁有的窗口、被覆蓋的窗口和彈出式窗口,但消息不被發送到子窗口。
wMsg用於區別其他消息的常量值,這些常量可以是Windows單元中預定義的常量,也可以是自定義的常量.
wParam通常是一個與消息有關的常量值,也可能是窗口或控件的句柄
lParam通常是一個指向內存中數據的指針。由於WParm、lParam和Pointer都是32位的,因此,它們之間可以相互轉換
返回值:返回值指定消息處理的結果,依賴於所發送的消息。
SendMessage用例
1. 系統消息(WM_)
::SendMessage(this->m_hWnd,WM_CLOSE,0,0);
SendMessage(hWnd,WM_KEYDOWN,VK_TAB,0x000f0001);
SendMessage(hWnd,WM_CHAR,VK_TAB,0x000f0001);
SendMessage(hWnd,WM_KEYUP,VK_TAB,0xc00f0001);
SendMessage(hWnd,WM_KEYDOWN,VK_TAB,0x000f0001);
SendMessage(hWnd,WM_CHAR,VK_TAB,0x000f0001);
SendMessage(hWnd,WM_KEYUP,VK_TAB,0xc00f0001);
SendMessage(hWnd,WM_KEYDOWN,VK_TAB,0x000f0001);
SendMessage(hWnd,WM_CHAR,VK_TAB,0x000f0001);
SendMessage(hWnd,WM_KEYUP,VK_TAB,0xc00f0001);
SendMessage(hWnd,WM_KEYDOWN,VK_RETURN,0x001c0001);
SendMessage(hWnd,WM_CHAR,VK_RETURN,0x001c0001);
SendMessage HWND, WM_SHOWWINDOW, SW_HIDE, vbNull '隱藏窗體
SendMessage HWND, WM_SHOWWINDOW, SW_NORMAL, vbNull '顯示窗體
SendMessage(HWND, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&) '關閉
SendMessage(HWND, WM_SYSCOMMAND, SC_MINIMIZE, ByVal 0&) '最小化
SendMessage(HWND, WM_PASTE, 0, 0) '粘貼
SendMessage(HWND, WM_COPY, 0, 0) '復制
SendMessage(HWND, WM_UNDO, 0, 0) '撤消
2. 通告消息
比如:給資源ID為IDC_BUTTON2的按鈕,發送點擊消息:
SendMessage(WM_COMMAND,
MAKELONG(IDC_BUTTON2,BN_CLICKED),
(LPARAM)(GetDlgItem(IDC_BUTTON2)-> GetSafeHwnd()));
或:
::SendMessage(m_hWnd,
WM_COMMAND,
MAKELONG(IDC_BUTTON2,BN_CLICKED),
(LPARAM)(GetDlgItem(IDC_BUTTON2)-> GetSafeHwnd()));
例:給菜單ID為ID_GET的菜單項,發送消息
::SendMessage(AfxGetMainWnd()->m_hWnd,WM_COMMAND,ID_GET,NULL);
3. 用戶自定義消息
SendMessge(WM_MYMSG,0,0);
或:
::SendMessge(::AfxGetMainWnd()->m_hWnd,WM_MYMSG,0,0);
4. 向其他應用程序發送消息
也可以為其他應用程序發送消息,前提是找到窗體的句柄,如:與FindWindow()函數一起使用;
如:
CString str="360w.txt -記事本";//向窗口為str的記事本窗口發送WM_CLOSE消息
CWnd *pWnd=CWnd::FindWindow(NULL,str);//獲取目的窗口對象
::SendMessage(*pWnd,WM_CLOSE,0,0);
窗口標題的獲取方法:
1. 使用VC++自帶工具SPY++
2. 編程實現,可用EnumWindows函數實現;詳見“枚舉所有窗體,並向打開的窗體發送關閉消息”http://download.csdn.net/detail/nuptboyzhb/4162747
舉例:
HWND gameh=NULL; gameh=::FindWindow(NULL,"窗口標題");//參看游戲的標題.可以用vc6.0自帶的Spy++工具查看
CWnd* pWnd = CWnd::FromHandle(gameh);
//在坐標為(x,y)的點,發送鼠標按下消息//注意,x,y是客戶區的坐標
::SendMessage(*pWnd,WM_LBUTTONDOWN,0,(y<<16)+x);
//發送鼠標移動消息,鼠標移動到點(x,y)
::SendMessage(*pWnd,WM_MOUSEMOVE,0,MAKELONG(x,y));
//發送粘貼消息
::SendMessage(dlg_hwnd,WM_PASTE,0,0);
5. 發送自己注冊的消息 5.1 發送端:
本示例先通過RegisterWindowMessage函數來注冊一條消息,然后用Win32 API函數SendMessage()發送。 主程序端: 建立MFC對話框,添加一個按鈕 在對話框CPP文件預處理下加入下面代碼: static UINT NEAR WM_RGSMSG=RegisterWindowMessage("MESSAGE");//注冊一條發送MESSAGE的自己注冊的消息 在按鈕單擊事件函數中添加后: void CMyDlg::OnButton1() { // TODO: Add your control notification handler code here HWND hwnd=::FindWindow(NULL,"接受窗口");//找到我們要發送消息的窗口句柄 if(hwnd==NULL) { AfxMessageBox("沒有找到接受窗口"); return; } else ::SendMessage(hwnd,WM_RGSMSG,1,0);//發送消息 }
5.2 接收端:
本示例接受方,仍然是先通過RegisterWindowMessage函數來注冊一條相同的消息,然后定義消息宏,綁定處理函數 接收窗口: 建立MFC對話框工程 在對話框CPP文件預處理下加入下面代碼: static UINT NEAR WM_RGSMSG=RegisterWindowMessage("MESSAGE");//注冊一條發送MESSAGE的自己注冊的消息 在消息宏聲明處 將消息聲明為: afx_msg LRESULT OnRgsmsg(WPARAM wParam,LPARAM lparam); //聲明消息映射函數 在建立消息映射表的地方添加如下代碼: ON_REGISTERED_MESSAGE(WM_RGSMSG,OnRgsmsg)//注冊的消息宏應放在這個位置 在CPP文件中,添加函數定義,代碼如下: LRESULT CMyDlg::OnRgsmsg(WPARAM wParam,LPARAM lParam) { AfxMessageBox("接收到消息"); return TRUE; }
// http://blog.csdn.net/nupt123456789/article/details/7370463