消息添加方式

Windows是基于消息的机制,在MFC程序中使用消息主要是下面几个步骤。

1,注册消息。

   1: #define WM_THREADPOOL WM_USER+102

WM_USER一下的消息由系统保留,这里最好是WM_USER+一个数字。

2,消息响应函数声明,和生命普通函数是一样的。

   1: protected:
   2:     afx_msg LRESULT OnThreadpool(WPARAM wParam, LPARAM lParam);

这里的声明是WIN规定的,因为后面的映射宏的参数指定了是这么一个格式。

3,将定义的消息映射到声明的响应函数。需要放在下面位置,一般里面还有系统已经自动生成的一些映射,比如下面就有鼠标点击的响应。

   1: BEGIN_MESSAGE_MAP(CThreadPoolProjDlg, CDialogEx)
   2:     ON_WM_SYSCOMMAND()
   3:     ON_WM_PAINT()
   4:     ON_WM_QUERYDRAGICON()
   5:     ON_BN_CLICKED(IDC_BUTTON2, &CThreadPoolProjDlg::OnBnClickedButton2)
   6:     ON_MESSAGE(WM_THREADPOOL, &CThreadPoolProjDlg::OnThreadpool)
   7: END_MESSAGE_MAP()

ONMESSAGE是一个宏,查看定义可看到下面的代码:

   1: #define ON_MESSAGE(message, memberFxn) \
   2:     { message, 0, 0, 0, AfxSig_lwl, \
   3:         (AFX_PMSG)(AFX_PMSGW) \
   4:         (static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > \
   5:         (memberFxn)) },
   6:  
   7: // for Registered Windows messages

4,完成映射以后就需要实现响应函数了,这个跟一般函数也一样,无非是实现一个.h文件里命名的函数罢了。

   1: afx_msg LRESULT CThreadPoolProjDlg::OnThreadpool(WPARAM wParam, LPARAM lParam)
   2: {
   3:     UpdateData(FALSE);
   4:     return 0;
   5: }

这里只是简单地更新数据。

5,发送消息。

发送消息可以用SendMessage和PostMessage,二者的区别可以参考MSDN,很好理解。

SendMessage :This function sends the specified message to a window or windows. SendMessage calls the window procedure for the specified window and does not return until the window procedure has processed the message. The PostMessage function, in contrast, posts a message to a thread's message queue and returns immediately.

简单来说就是,SendMessage发送消息,等到程序响应了以后才返回,PostMessage则把消息加入消息队列就不管了,直接返回。类似同步和异步的区别。

   1: SendMessage(((CThreadPoolProjDlg*)pT)->m_hWnd, WM_THREADPOOL, 0, 0);

这里使用SendMessage。

 

整个过程就是上面五个步骤,在VC6中,添加消息需要自己一步一步实现。更新的VS系列则简化了这个过程,直接在类向导里面就可以跟添加变量一样实现,我的VS2013有时候添加消息会出现没有定义的情况,这时候需要自己手动添加定义。

 

实际上在WIN32编程中,添加消息的方式很简单,只需要第一步和最后一步发送消息即可,而且直接看WIN32的消息运行过程,更好理解消息机制,下面是测试的简单代码,当时主要是测试了一些别的东西,所以有其他代码,这里只需要关注switch里面的代码即可。

  1: #include<Windows.h>
  2: #include<process.h>
  3: #include<windowsx.h>
  4: #include<atlstr.h>
  5: 
  6: #define WM_MYMESSAGE WM_USER+111
  7: 
  8: 
  9: unsigned int _stdcall ThreadProc(void*);
 10: LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
 11: HWND g_hWnd;
 12: 
 13: int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, PSTR szCmdline, int CmdShow)
 14: {
 15:     WNDCLASS wndclass;
 16:     wndclass.cbClsExtra = NULL;
 17:     wndclass.cbWndExtra = NULL;
 18:     wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
 19:     wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
 20:     wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
 21:     wndclass.hInstance = hInstance;
 22:     wndclass.lpfnWndProc = WndProc;
 23:     wndclass.lpszClassName = TEXT("TestWnd");
 24:     wndclass.lpszMenuName = NULL;
 25:     wndclass.style = CS_HREDRAW | CS_VREDRAW;
 26:     
 27:     if (!RegisterClass(&wndclass))
 28:     {
 29:         MessageBox(NULL, TEXT("Warnning!"), TEXT("Failed to Regist!"), MB_OK);
 30:         return -1;
 31:     }
 32: 
 33:     HWND hWnd = CreateWindow(TEXT("TestWnd"), TEXT("测试窗口!"), WS_OVERLAPPEDWINDOW,CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
 34: 
 35:     ShowWindow(hWnd, CmdShow);
 36:     UpdateWindow(hWnd);
 37: 
 38:     g_hWnd = hWnd;
 39: 
 40: 
 41:     MSG msg;
 42: 
 43: 
 44:     HANDLE hThread;
 45:     hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadProc, (void*)0x00, 0, NULL);
 46: 
 47:     _beginthreadex(NULL, 0, ThreadProc, (void*)0x01, 0, NULL);
 48: 
 49:     while (GetMessage(&msg, hWnd, 0, 0))
 50:     {
 51:         TranslateMessage(&msg);
 52:         DispatchMessage(&msg);
 53:     }
 54:     return msg.wParam;
 55: 
 56: }
 57: 
 58: unsigned int _stdcall ThreadProc(void* pT)
 59: {
 60:     if (!(int)pT)
 61:     {
 62:         MessageBox(NULL, TEXT("Thread is running!"), TEXT("ThreadProc"), MB_OK);
 63:         Sleep(4000);
 64:     }
 65:     else
 66:     {
 67:         Sleep(2000);
 68:         SendMessage(g_hWnd, WM_MYMESSAGE, 0, 0);
 69:     }
 70:     return 0;
 71: }
 72: 
 73: LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 74: {
 75:     CString Tsr;
 76:     switch (message)
 77:     {
 78:     case WM_CREATE:
 79:         return 0;
 80:     case WM_LBUTTONDOWN:
 81:         Tsr.Format(TEXT("Position<%d,%d>"), GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
 82:         MessageBox(NULL, Tsr, TEXT("PointInfo"), MB_OK);
 83:         
 84:         
 85: 
 86: 
 87:         return 0;
 88:     case WM_MYMESSAGE:
 89:         MessageBox(NULL, TEXT("WM_MYMESSAGE"), TEXT("TEST"), MB_OK);
 90:         return 0;
 91:     case WM_DESTROY:
 92:         PostQuitMessage(0);
 93:     return 0;
 94:     }
 95:     return DefWindowProc(hWnd, message, wParam, lParam);
 96: 
 97: }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MFC自定义控件消息响应方式一般有以下几种: 1. 消息映射法:在控件所在的窗口类中添加响应函数,然后在消息映射表中添加对应的消息映射。例如: ``` BEGIN_MESSAGE_MAP(CMyWnd, CWnd) ON_WM_PAINT() ON_WM_LBUTTONDOWN() END_MESSAGE_MAP() void CMyWnd::OnPaint() { // TODO: 在此处添加消息处理程序代码 } void CMyWnd::OnLButtonDown(UINT nFlags, CPoint point) { // TODO: 在此处添加消息处理程序代码 } ``` 2. 消息钩子法:在控件类中重载虚函数PreTranslateMessage,然后在函数中进行消息处理。例如: ``` class CMyControl : public CWnd { public: virtual BOOL PreTranslateMessage(MSG* pMsg); }; BOOL CMyControl::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_LBUTTONDOWN) { // TODO: 在此处添加消息处理程序代码 return TRUE; } return CWnd::PreTranslateMessage(pMsg); } ``` 3. 消息分发法:在控件类中重载虚函数WindowProc,然后在函数中进行消息处理。例如: ``` class CMyControl : public CWnd { public: virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); }; LRESULT CMyControl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_PAINT: // TODO: 在此处添加消息处理程序代码 break; case WM_LBUTTONDOWN: // TODO: 在此处添加消息处理程序代码 break; default: break; } return CWnd::WindowProc(message, wParam, lParam); } ``` 以上三种方法都可以用来响应自定义控件的消息,具体应该根据实际情况选择。其中,消息映射法是MFC中最常用的方式,也是最简单易懂的方式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值