day02 创建第一个Windows窗口及Windows的消息处理

第一个Windows窗口程序

1. 入口函数

Windows编程的入口函数:
建议直接F1查询官方文档,Ctrl C+V

int WINAPI WinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR     lpCmdLine,
	int       nShowCmd
)
{

	return 0;
}

2. 创建窗口类

我们准备创建一个窗口类,使用WNDCLASSW创建一个支持宽字符的窗口类:
这个类比较复杂,但是我们实际用到的属性不多:
WNDCLASSW函数原型官方文档

WNDCLASSW myClassWindow{ 0 };		
myClassWindow.lpszClassName = L"我的第一个窗口";	//显式指定窗口类名
myClassWindow.lpfnWndProc = nullptr;			//指定回调函数,我们之后会用到,暂时给他赋一个空值

我们创建一个最简单的窗口类,可以只声明这个两个参数的值,但是在我们以后的学习中,你就会慢慢丰富这个类,比如,我们可以指定窗口的图标,鼠标样式等等。。。我们以后再说。

3. 注册窗口

根据我们创建的窗口类,注册一个窗口实例:

RegisterClassW(&myClassWindow);

注册成功后,我们便可以使用这个窗口类创建一个实例对象了。

4. 创建窗口实例

CreatClass创建一个窗口类:

HWND window=CreateWindowW(
	myClassWindow.lpszClassName,//窗口的类名
	L"无标题",	//窗口的标题
	WS_OVERLAPPEDWINDOW,	//窗口样式
	CW_USEDEFAULT,	//窗口的x坐标(左上角)
	0,	//窗口的y坐标
	CW_USEDEFAULT,	//窗口的width宽度
	0,	//窗口的height高度
	NULL,	//窗口的父窗口句柄(一般为空)
	NULL,	//菜单
	hInstance,	//与此窗口相关联的窗口句柄
	NULL	//一般为空
);
//显示窗口
ShowWindow(window, SW_SHOWNORMAL);

我们返回一个HWND的句柄,这样我们就得到我们的主窗口的句柄了。
然后再显示此窗口。

5. 处理消息事件

Windows系统是基于消息的操作系统。
每一个窗口都在不停的处理消息,所有的操作都是接收到消息之后,进行处理的结果。
围绕着消息的处理,产生了获取消息的消息泵机制也叫消息循环,以及处理消息的窗口回调函数机制。

消息的产生
Windows下产生消息的时机共有以下四种:
1、用户主动产生的消息
2、Windows系统本身产生的消息。
3、应用程序本身产生的消息。
4、其他应用程序产生的消息。
那么应用程序是如何接受消息的呢?

Windows操作系统有一个系统消息队列,每个GUI程序,都有自己的消息队列,系统消息队列负责将消息发送给不同GUI程序的消息队列。
API函数:
GetMessage 从消息队列中取出消息
TranslateMessage 翻译消息为字符消息
DispatchMessage 将消息发送给消息处理函数。

MSG msg{ 0 };
while (GetMessageW(&msg, 0, 0, 0))
{
	TranslateMessage(&msg);
	DispatchMessageW(&msg);
}

6. 回调函数

Wndproc: 在应用程序中定义的回调函数,用于处理发送到窗口的消息。

windows就是一个不断处理消息的系统,我们要对其处理消息,并且返回给主函数。

LRESULT CALLBACK Wndproc(
	HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
)
{
	switch (uMsg)
	{
	case WM_CREATE:
	{
		MessageBoxW(hwnd, L"窗口创建成功!", L"提示", MB_OK);
		break;
	}
	case WM_CLOSE:
	{
		DestroyWindow(hwnd);
		PostQuitMessage(NULL);
		break;
	}
	}

	return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}

记得在我们最开始创建的窗口类中指明我们的回调函数:

myClassWindow.lpfnWndProc = Wndproc;

完整测试

#include <Windows.h>

LRESULT CALLBACK Wndproc(
	HWND hwnd,
	UINT uMsg,
	WPARAM wParam,
	LPARAM lParam
)
{
	switch (uMsg)
	{
	case WM_CREATE:
	{
		MessageBoxW(hwnd, L"窗口创建成功!", L"提示", MB_OK);
		break;
	}
	case WM_CLOSE:
	{
		DestroyWindow(hwnd);
		PostQuitMessage(NULL);
		break;
	}
	}

	return DefWindowProcW(hwnd, uMsg, wParam, lParam);
}

int WINAPI WinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR     lpCmdLine,
	int       nShowCmd
)
{
	WNDCLASSW myClassWindow{ 0 };
	myClassWindow.lpszClassName = L"我的第一个窗口";
	myClassWindow.lpfnWndProc = Wndproc;

	RegisterClassW(&myClassWindow);

	HWND window=CreateWindowW(
		myClassWindow.lpszClassName,//窗口的类名
		L"无标题",	//窗口的标题
		WS_OVERLAPPEDWINDOW,	//窗口样式
		CW_USEDEFAULT,	//窗口的x坐标(左上角)
		0,	//窗口的y坐标
		CW_USEDEFAULT,	//窗口的width宽度
		0,	//窗口的height高度
		NULL,	//窗口的父窗口句柄(一般为空)
		NULL,	//菜单
		hInstance,	//与此窗口相关联的窗口句柄
		NULL	//一般为空
	);
	//显示窗口
	ShowWindow(window, SW_SHOWNORMAL);

	MSG msg{ 0 };
	while (GetMessageW(&msg, 0, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessageW(&msg);
	}

	return 0;
}

在这里插入图片描述
在这里插入图片描述


Windows消息处理

Windows通用消息:
Windows通用消息标志都定义在WINUSER.H中,以WM_开头,大体分为三类。

  1. 窗口消息
    例如:WM_CREATEWM_CLOSE

  2. 命令消息
    特指WM_COMMAND消息,与处理用户请求有关,如点击菜单项,工具栏,控件等就会产生命令消息。

  3. 通知消息
    特指WM_NOTIFY消息,只使用用windows的公共控件,如列表,视图等。

  • Windos控件消息
    控件消息是用于控制控件的一些行为的,不同的控件有不同的控制消息,命名规则如下:
    BM_按钮控制消息
    EM_编辑框控制消息
    STM_静态文本控制消息
    CM_组合框控制消息
    LBM_列表框控制消息

  • 用户自定义消息
    除了windows消息外,我们也可以定义自己的消息。系统的消息马在0-WM_USER之间,故而我们定义的消息大于WM_USER即可

  • 消息的发送
    PostMessageSendMessage
    PostMessage会将消息发送到消息队列,应用程序的消息循环会最终得到消息,并分发给回调函数。
    SendMessage相当于直接调用窗口的回调函数,等待窗口过程处理结束并返回结果。
    根据发送消息的方式不同,消息分为两类:
    队列消息、非队列消息

posted @ 2022-10-05 20:08  hugeYlh  阅读(11)  评论(0编辑  收藏  举报  来源