这几天做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();
}
运行结果: