我觉得应该花点时间熟悉一下windows编程了,不然项目的代码没法看啊。今天在家,实现了一个简单的接收消息的windows窗口,可以接收其他进程发送过来的消息。
《windows程序设计》开头就讲了一个windows程序的基本框架,该例程创建了一个可视的窗口,步骤还挺多的。如果创建的窗口仅用于接收消息,那就简单得多,不需要我们注册一个自定义的WNDCLASS,也不需要将界面显示出来。
先看一下CreateWindow的帮助文档:
http://msdn.microsoft.com/en-us/library/ms632679.aspx
lpClassName可以自己注册,也可以用系统预定义的,我在程序中用的是STATIC,如果这个参数填一个不存在的classname,那么CreateWindow会返回NULL。用户可以自定义消息,需要从WM_USER开始定义,而且处理消息和发送消息的进程都需要知道这份定义。WndProc是窗口处理函数,是通过SetWindowLong向窗口注册的。我写的WndProc只处理了WM_USER + 100和WM_USER + 200消息,其他的消息委托给DefWindowProc处理。
#include <tchar.h> #include <windows.h> #include <iostream> using namespace std; LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { TCHAR szText[MAX_PATH] = {0}; _stprintf(szText, _T("wParam=%d lParam=%d"), wParam, lParam); switch(message) { case WM_USER + 100: OutputDebugString(_T("WM_USER + 100")); OutputDebugString(szText); return 0; case WM_USER + 200: OutputDebugString(_T("WM_USER + 200")); OutputDebugString(szText); PostQuitMessage(0); return 0; default: OutputDebugString(_T("default")); OutputDebugString(szText); break; } return DefWindowProc (hwnd, message, wParam, lParam); } int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { HWND hWnd = CreateWindow( _T("static"), _T("MsgRecv"), WS_OVERLAPPEDWINDOW,, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL); if(hWnd != NULL && IsWindow(hWnd)) { SetWindowLong(hWnd, GWL_WNDPROC, (LONG) WndProc); } MSG msg; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } return msg.wParam; }
发送消息的进程实现比较简单,先FindWindow找到窗口句柄,然后在SendMessage即可。在如下代码中,我每隔10ms发送一个WM_USER + 100消息,发送100次后,我发送一个WM_USER + 200让接收消息的窗口退出。
#include<windows.h> #include<tchar.h> #include<iostream> using namespace std; int main() { HWND hWnd = ::FindWindow(_T("static"), _T("MsgRecv")); if (hWnd) { for (int i = 1; i <= 100; i++) { ::SendMessage(hWnd, WM_USER + 100, WPARAM(i), NULL); Sleep(10); } ::SendMessage(hWnd, WM_USER + 200, NULL, NULL); cout << "finish send" << endl; } else { cout << "hwnd is null" << endl; } return 0; }
这样一个接收消息的窗口程序就完成了。先运行创建窗口的进程,再运行发送消息的进程,在DebugView中就能够看到效果啦。
这个例子有很多应用场景,比如在客户端UI中,需要显示一个扫描线程的进度,其中,扫描进程用SendMessage上报进度,UI线程创建一个窗口接收进度信息,并在WndProc中做UI相关的显示。