年轻人的第一个win32窗口程序

年轻人的第一个win32窗口程序

#include <cstdio>
#include <windows.h>

// 窗口处理函数
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
	switch (msgID)
	{
	case WM_DESTROY: // 点击关闭按钮
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hWnd, msgID, wParam, lParam);
}

// 入口函数
int CALLBACK WinMain(HINSTANCE hIns, HINSTANCE hPreIns, LPSTR lpCmdLine, int nCmdShow)
{
	// 新建窗口类
	WNDCLASS wc = { 0 };
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wc.hCursor = NULL;// 默认光标
	wc.hIcon = NULL;// 默认图标
	wc.hInstance = hIns;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = "Windows";
	wc.lpszMenuName = NULL; // 无菜单
	wc.style = CS_HREDRAW | CS_VREDRAW;
	// 注册窗口类
	RegisterClass(&wc);
	// 内存中创建窗口
	HWND hWind = CreateWindow("Windows", "windows", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, NULL, NULL);
	// 显示窗口
	ShowWindow(hWind, SW_SHOW);
	// 刷新窗口
	UpdateWindow(hWind);
	// 消息循环
	MSG nMsg = { 0 };
	while (GetMessage(&nMsg, NULL, 0, 0))
	{
		TranslateMessage(&nMsg); // 翻译消息
		DispatchMessage(&nMsg); // 派发给窗口处理函数处理
	}
	// 取消窗口类的注册
	UnregisterClass("Windows", hIns);
	return 0;
}

看到这么一长串代码你一定有很多问号,没事我们好好分析一下。

1 什么是CALLBACK?

当一个程序调用windows API时的过程称为Call

当windows API调用程序里面的函数时这称之为Callback

所以这里的两个函数都是用于windows API调用的。

2 主函数在哪?

WinMain函数就是主函数,或者说是入口函数。

WinMain函数的几个参数详见官方文档

3 消息处理函数

消息处理函数的参数一般由以下部分组成:

LRESULT CALLBACK WndProc(
    HWND hWnd, // 窗口句柄
    UINT msgID, // 消息ID
    WPARAM wParam, 
    LPARAM lParam //两个参数
    )

4 什么是消息

消息是系统或程序产生的一个信号,它以MSG结构体的形式被接收。

接受消息函数:GetMessage
MSG结构体: MSG structure

MSG中有两个成员:lParam 和 wParam。二者是宏定义,实际上是64位无符号整数:

// basetsd.h
typedef unsigned __int64 UINT_PTR, *PUINT_PTR;
// minwindef.h
typedef UINT_PTR            WPARAM;

一般在消息函数中带这两个类型的参数,通常用来存储窗口消息的参数。
有时64位的前后32位会存储两个不同的信息,可以用这两个宏提取:

UINT_PTR x;
WORD low = LOWORD(x); // 低32位
WORD high = HIWORD (x); // 高32位

5 DefWindowProc()函数是什么?

DefWindowProc calls the default window procedure to provide default processing for any window messages that an application does not process. This function ensures that every message is processed. DefWindowProc is called with the same parameters received by the window procedure.

DefWindowProc让程序使用微软提供的一套默认消息处理方式处理消息。

6 如何结束程序?

点击窗口右上关闭会在显示器上关闭窗口,但不会使GetMessage返回0,所以不会结束进程!

需要使用使用PostQuitMessage函数发出WM_QUIT消息才能使GetMessage返回0。

WM_QUIT:Indicates a request to terminate an application, and is generated when the application calls the PostQuitMessage function. This message causes the GetMessage function to return zero.

以上来自于Windows Docs

7 WNDCLASS是什么?

WNDCLASS是窗口的结构体,或者说是窗口类。

新建一个WNDCLASS结构体后,我们需要修改其成员变量,使之符合程序的功能:

// 新建窗口类
	WNDCLASS wc = { 0 };
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	wc.hCursor = NULL;// 默认光标
	wc.hIcon = NULL;// 默认图标
	wc.hInstance = hIns;
	wc.lpfnWndProc = WndProc;
	wc.lpszClassName = "Windows";
	wc.lpszMenuName = NULL; // 无菜单
	wc.style = CS_HREDRAW | CS_VREDRAW;

注意WinUser.h中:

typedef WNDCLASSA WNDCLASS;

所以要看WNDCLASSA结构体:Windows Docs

可以设置不同的style以添加功能,注意用或符号(|)添加多个,详见官方文档

新建完窗口类之后需要在注册窗口类,这样就可以拿着lpszClassName创建并使用它了。

8 创建窗口

调用CreateWindow函数会在窗口显示之前发出WM_CREATE消息,并直接调用窗口处理函数,不会进入消息队列被GetMessage接收

9 其他函数

其他的函数就看看注释和查查官方的文档吧,官方的文档非常详细。

10 最后:HWND,UINT_PTR...这些奇奇怪怪的数据类型是啥?

HWND之类是句柄类型,这些以后再说。

其他的都是普通的数据类型的宏或重定义,直接右键转定义。

posted @ 2022-08-14 17:13  DarkLights  阅读(7)  评论(0编辑  收藏  举报