C++系列 --- Windows消息驱动原理分析

一、消息驱动

创建窗口后,要对窗口的行为负责。操作系统不断的向应用程序发送消息,通知它发生了什么事情。

当Widnows向程序发送消息时,它调用程序中的一个函数,这个函数的参数精确地描述了Windows发送的消息。

在程序中称其为窗口函数或消息处理函数。它是一个自定义的回调函数。原型如下:

LRESULT CALLBACK WindowProc(HWND hwnd,UINT hMsg,WPARAM wParam,LPARAM lParam);

 

二、显示一个窗口的具体步骤

1、注册窗口类RegisterClassEx

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow) 
{
    char szClassName[] = "MainWClass";
    WNDCLASSEX wndclass;

    wndclass.cbSize = sizeof(wndclass);
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = MainWndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = ::LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szClassName;
    wndclass.hIconSm = NULL;

    ::RegisterClassEx(&wndclass);
    
    ......
}

2、创建窗口CreateWindowEx

//创建主窗口
HWND hWnd = ::CreateWindowEx(0,
	szClassName,//类名
	"我的第一个GUI程序",
	WS_OVERLAPPEDWINDOW,
	CW_USEDEFAULT,
	CW_USEDEFAULT,
	CW_USEDEFAULT,
	CW_USEDEFAULT,
	NULL,
	NULL,
	hInstance,
	NULL
);
if (NULL == hWnd) {
	::MessageBox(NULL, "创建窗口失败", "错误", MB_OK);
	return -1;
}

3、在桌面显示窗口ShowWindow

//显示窗口
::ShowWindow(hWnd, nCmdShow);

4、更新窗口客户区UpdateWindow

::UpdateWindow(hWnd);

5、进入消息获取和处理的循环。

首先是获取消息GetMessage,如果有消息到达,则将消息分派到回调函数处理DispatchMessage,如果是WM_QUIT,则GetMessage返回FALSE,则整个消息循环结束。消息的具体处理过程在MainWndProc函数中进行。

//从操作系统的消息队列中不断的捡取消息
MSG msg;
while (::GetMessage(&msg, NULL, 0, 0)) 
{
        //转化键盘消息 
	::TranslateMessage(&msg);

        // 将消息发送到相应的窗口函数
	::DispatchMessage(&msg);
}

// 当GetMessage返回0时,程序结束
return msg.wParam;

6、回调函数

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam)
{
	switch (message) 
        {
	case WM_DESTROY: // 正在销毁窗口

        // 向消息队列投递一个WM_QUIT消息,促使GetMessage函数返回0,结束消息循环
		::PostQuitMessage(0);
		return 0;
	}

    // 将我们不处理的消息交给操作系统默认处理。
	return ::DefWindowProc(hWnd, message, wparam, lparam);

}

 三、实例

1、实例

#include 
#include 
LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
	LPSTR lpCmdLine, int nCmdShow) {
	char szClassName[] = "MainWClass";
	WNDCLASSEX wndclass;

	wndclass.cbSize = sizeof(wndclass);
	wndclass.style = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc = MainWndProc;
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hInstance = hInstance;
	wndclass.hIcon = ::LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor = ::LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = szClassName;
	wndclass.hIconSm = NULL;

	::RegisterClassEx(&wndclass);

	//创建主窗口
	HWND hWnd = ::CreateWindowEx(0,
		szClassName,//类名
		"我的第一个GUI程序",
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL
	);
	if (NULL == hWnd) {
		::MessageBox(NULL, "创建窗口失败", "错误", MB_OK);
		return -1;
	}

	//显示窗口
	::ShowWindow(hWnd, nCmdShow);
	::UpdateWindow(hWnd);

	//从操作系统的消息队列中不断的捡取消息
	MSG msg;
	while (::GetMessage(&msg, NULL, 0, 0)) {
		::TranslateMessage(&msg);
		::DispatchMessage(&msg);
	}
	return msg.wParam;
}

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam) {
	switch (message) {
	case WM_DESTROY:
		::PostQuitMessage(0);
		return 0;
	}
	return ::DefWindowProc(hWnd, message, wparam, lparam);

}

2、运行结果

C++系列 --- Windows消息驱动原理分析_第1张图片 

 

你可能感兴趣的:(C++MFC)