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+1117: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: }