这几天做windows上进程通信发现,windows消息只能在窗口之间传递,不能在控制台之间传递,因为控制台程序没有消息循环,无法接收消息. 普通控制台程序不能提供消息循环,但是QT是提供(app.exec())消息循环的,也就是说是可以接收windows消息的.
先看一下windows新建窗口代码,经典的windows图形程序:
#include <windows.h> #include <stdio.h> int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int); BOOL InitApplication(HINSTANCE); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM); HINSTANCE hinst; // 窗口句柄 // windows GUI入口 int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { if (!InitApplication(hinstance)) return FALSE; if (!InitInstance(hinstance, nCmdShow)) return FALSE; // 循环派发消息 MSG msg; while (GetMessage(&msg, (HWND) NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } // 注册窗口 BOOL InitApplication(HINSTANCE hinstance) { WNDCLASSEX wcx; wcx.cbSize = sizeof(wcx); wcx.style = CS_HREDRAW|CS_VREDRAW; wcx.lpfnWndProc = MainWndProc; wcx.cbClsExtra = 0; wcx.cbWndExtra = 0; wcx.hInstance = hinstance; wcx.hIcon = LoadIcon(NULL,IDI_APPLICATION); wcx.hCursor = LoadCursor(NULL,IDC_ARROW); wcx.hbrBackground = (HBRUSH)(COLOR_BACKGROUND); wcx.lpszMenuName = NULL; wcx.lpszClassName = "MainWClass"; wcx.hIconSm = NULL; return RegisterClassEx(&wcx); } // 新建窗口 BOOL InitInstance(HINSTANCE hinstance, int nCmdShow) { HWND hwnd; hinst = hinstance; hwnd = CreateWindow( "MainWClass", // name of window class "Sample", // title-bar string WS_OVERLAPPEDWINDOW, // top-level window CW_USEDEFAULT, // default horizontal position CW_USEDEFAULT, // default vertical position 200, // default width 200, // default height (HWND) NULL, // no owner window (HMENU) NULL, // use class menu hinstance, // handle to application instance (LPVOID) NULL); // no window-creation data if (!hwnd) return FALSE; ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); return TRUE; } // 消息处理中心 LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; switch (message) { case WM_CREATE: case WM_SHOWWINDOW: case WM_KEYDOWN: case WM_COMMAND: return ::DefWindowProc(hWnd, message, wParam, lParam); case WM_LBUTTONDOWN: // 按下鼠标左键 { MessageBox(GetFocus(), "Hello", "Hello", MB_OK|MB_ICONASTERISK); break; } case WM_NOTIFYFORMAT: // 用户登录通知事件 { MessageBox(GetFocus(), "Notify", "Hello", MB_OK|MB_ICONASTERISK); break; } case WM_SETTEXT: { MessageBox(GetFocus(), "SET TEXT", "Hello", MB_OK|MB_ICONASTERISK); break; } case WM_COPYDATA: // 传递数据 { COPYDATASTRUCT *cp=(COPYDATASTRUCT*)lParam; MessageBox(GetFocus(), (char*)cp->lpData, "data", MB_OK|MB_ICONASTERISK); return ::DefWindowProc(hWnd, message, wParam, lParam); } case WM_USER+10: // 自定义事件 { MessageBox(GetFocus(), "User info Msg", "Hello", MB_OK|MB_ICONASTERISK); break; } case WM_DESTROY: PostQuitMessage(0); break; default: return ::DefWindowProc(hWnd, message, wParam, lParam); } return 0; }
可以看出,windows UI需要WinMain提供当前程序句柄, 需要一循环去派发消息. QT也提供事件循环,通过GetModuleHandle(NULL)即可获取当前实例句柄,这样就可以在QT调用windows api 新建窗口
int main(int argc,char **argv) { QApplication app(argc,argv); // 返回当前实例句柄 HINSTANCE hinstance = (HINSTANCE)GetModuleHandle(NULL); if (!InitApplication(hinstance)) return FALSE; if (!InitInstance(hinstance, SW_SHOW)) return FALSE; return app.exec(); }
运行结果: