MFC窗口消息PostMessage和SendMessage

之前這些消息用得比較少,可是今天碰到了個事兒,我看非用消息不可。css

事情是這樣的,我在線程中須要刷新對話框上面的內容,可是往往執行到UpdateData時就出現了斷言錯誤。編程

查了相關資料,發現這個多是多個模塊調用同一個方法出現的問題。反正照我以前的邏輯走不通。windows

我如今將更新對話框信息的函數,經過線程中發窗口消息,讓對話框的消息處理函數來負責處理我自定義的消息,爲我刷新對話框數據。函數

 

// http://blog.csdn.net/a8082649/article/details/7733527工具

1.自定義消息ID。this

#define WM_MY_MESSAGE (WM_USER+100)         WM_USER爲windows系統爲非系統消息保留的ID,這裏至少要用100,由於其它控件的消息會佔用一部分。spa

2. 定義消息處理函數。.net

消息處理函數爲消息目標類的成員函數。首先應該在.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添加

  1. BOOL CPreTranslateMessageDlg::PreTranslateMessage(MSG* pMsg)
  2. {
  3.     if (pMsg->message==WM_LBUTTONDOWN)
  4.     {
  5.         MessageBox("三三四四");
  6.     }
  7.     
  8.     return CDialog::PreTranslateMessage(pMsg);
  9. }

此函數爲手動添加的消息函數,可經過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

相關文章
相關標籤/搜索