2.2 窗口创建

窗口创建

首先了解一下创建窗口的API,CreateWindow以及CreateWindowEx。
CreateWindow函数是Windows API中一个非常重要的函数,用于创建一个新的窗口。

  • 原型
HWND CreateWindow(
  LPCTSTR lpClassName,//指定窗口类名。可以是预定义的窗口类(如"Button"、"Edit"等)或自定义的窗口类。
  LPCTSTR lpWindowName,//指定窗口标题栏文本,也就是窗口标题栏的名字
  DWORD dwStyle,//指定窗口样式,可以是多个样式的组合,如WS_OVERLAPPED、WS_CAPTION、WS_SYSMENU等。
  int x,//窗口左上角水平坐标位置
  int y,//窗口左上角垂直坐标位置
  int nWidth,//窗口的宽度
  int nHeight,//窗口的高度
  HWND hWndParent,//指定父窗口的句柄,如果窗口没有父窗口则传入NULL。
  HMENU hMenu,//指定窗口菜单的句柄,如果没有菜单则传入NULL。
  HINSTANCE hInstance,//指定创建窗口的应用程序实例句柄。
  LPVOID lpParam//窗口创建时附加参数,可以为NULL。
);
  • 返回值

该函数返回一个HWND类型的值,代表新创建窗口的句柄。如果创建失败,返回NULL。

CreateWindowEx与CreateWindow函数相比只是增加了更多的窗口样式选项。

HWND CreateWindowEx(
  DWORD dwExStyle,//指定额外的窗口样式。可以是多个样式的组合,如WS_EX_CLIENTEDGE、WS_EX_LAYERED等。
  LPCTSTR lpClassName,
  LPCTSTR lpWindowName,
  DWORD dwStyle,
  int x,
  int y,
  int nWidth,
  int nHeight,
  HWND hWndParent,
  HMENU hMenu,
  HINSTANCE hInstance,
  LPVOID lpParam
);

这里重点是第三个参数,窗口风格
微软官网详解: 窗口样式
在这里插入图片描述

窗口创建执行过程

也就是CreateWindow这个API是怎么实现的

  • 1.CreateWindow根据传入的窗口类名称,在应用程序局部窗口类中查找,如果找到执行2如果未找到执行3。
  • 2.比较局部窗口类与创建窗口时传入的HINSTANCE变量。如果发现相等,创建和注册的窗口类在同一模块,创建窗口返回。如果不相等,继续执行3。
  • 3.在应用程序全局窗口类,如果找到,执行4,如果未找到执行5
  • 4.使用找到的窗口类的信息,创建窗口返回
  • 5.在系统窗口类中查找,如果找到创建窗口返回,否则创建窗口失败

简单来说内部的实现过程可以概述为:
1.检查输入参数的合法性,如窗口类名、窗口样式、父窗口句柄等。如果参数不合法,函数返回NULL并设置相应的错误码。
2.查找已注册的窗口类,如果没有找到对应的窗口类,则返回错误。
3.分配内存空间来保存新窗口的数据结构,包括窗口句柄、窗口类信息、窗口样式、位置大小等。
4.初始化新窗口的数据结构,填充相关信息。
5.将新窗口添加到系统维护的窗口链表中。
6.调用低层次的窗口创建函数,如NtUserCreateWindowEx,来向操作系统发出创建窗口的请求。
7.如果窗口创建成功,返回新窗口的句柄;否则释放之前分配的内存空间,返回NULL并设置错误码。

关于1.3中程序关闭窗口后依然在后台运行如何退出的问题

在这里插入图片描述
可以看到,即使关闭了窗口,程序依旧在后台运行着
原因分析:
在这里插入图片描述
在这里插入图片描述
这里简单讲下这个API,后续会有详细的讲解
简单理解就是PostQuitMessage可以让GetMessage函数返回0

PostQuitMessage函数是Windows API中用于向应用程序的消息队列发送WM_QUIT消息的函数。
PostQuitMessage函数向应用程序的主线程消息队列发送WM_QUIT消息。
当应用程序的主消息循环收到WM_QUIT消息时,它会退出消息循环,应用程序也随之结束运行。
通常在应用程序的主窗口过程中,当用户关闭窗口时会调用PostQuitMessage函数,以结束应用程序的主消息循环。
除了在窗口过程中调用,您也可以在应用程序的其他地方调用PostQuitMessage函数,以结束应用程序的执行。

子窗口创建过程

  • 创建时要设置父窗口句柄
  • 创建风格要增加WS_CHILD | WS_VISIBLE 这两个风格
    在这里插入图片描述
    源码如下:
#include <windows.h>
//窗口处理函数(自定义,处理消息)
LRESULT CALLBACK WndProc(HWND hWnd, UINT msgID, WPARAM wParam, LPARAM lParam)
{
	switch (msgID)
	{
	case WM_DESTROY:
			PostQuitMessage(0);//向应用程序的消息队列发送WM_QUIT消息的函数
			break;
	}
	return DefWindowProc(hWnd, msgID, wParam, lParam);
}
//入口函数
int CALLBACK WinMain(_In_ HINSTANCE hIns, _In_opt_ HINSTANCE hPreIns, _In_ LPSTR lpCmdLine, _In_  int nCmdShow)
{
	//注册窗口类(向向操作系统写入一些数据)
	WNDCLASS wc = { 0 };
	wc.cbClsExtra = 0;	//申请缓冲区
	wc.cbWndExtra = 0; //申请缓冲区
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);	//窗口背景色
	wc.hCursor = NULL;	//光标,NULL表示默认由系统指定
	wc.hIcon = NULL;	//图标,NULL表示默认图标,即窗口左上角小图标
	wc.hInstance = hIns;		//当前程序实例句柄  ******
	wc.lpfnWndProc = WndProc;		//窗口处理函数名
	wc.lpszClassName = "Main";   //窗口类名字   ******
	wc.lpszMenuName = NULL;		//无菜单
	wc.style = CS_HREDRAW | CS_VREDRAW;	//当窗口宽度货高度发生改变时,重绘整个窗口
	RegisterClass(&wc);	//将以上所有赋值全部写入操作系统

	//在内存中创建窗口
	HWND hWnd = CreateWindowEx(0,"Main", "windows", WS_OVERLAPPEDWINDOW, 100, 100, 500, 500, NULL, NULL, hIns, NULL);

	wc.cbClsExtra = 0;	//申请缓冲区
	wc.cbWndExtra = 0; //申请缓冲区
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 3);	//窗口背景色
	wc.hCursor = NULL;	//光标,NULL表示默认由系统指定
	wc.hIcon = NULL;	//图标,NULL表示默认图标,即窗口左上角小图标
	wc.hInstance = hIns;		//当前程序实例句柄  ******
	wc.lpfnWndProc = DefWindowProc;		//窗口处理函数名
	wc.lpszClassName = "Child";   //窗口类名字   ******
	wc.lpszMenuName = NULL;		//无菜单
	wc.style = CS_HREDRAW | CS_VREDRAW;	//当窗口宽度货高度发生改变时,重绘整个窗口
	RegisterClass(&wc);	//将以上所有赋值全部写入操作系统
	//创建子窗口
	HWND hChild1 = CreateWindowEx(0, "child", "c1", WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, 0, 200, 200, hWnd, NULL, hIns, NULL);
	HWND hChild2 = CreateWindowEx(0, "child", "c2", WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW, 200, 0, 200, 200, hWnd, NULL, hIns, NULL);
	//显示窗口
	ShowWindow(hWnd, SW_SHOW);
	UpdateWindow(hWnd);	//刷新窗口
	//消息循环
	MSG nMsg = { 0 };
	while (GetMessage(&nMsg, NULL, 0, 0))
	{
		TranslateMessage(&nMsg);
		DispatchMessage(&nMsg);	//将消息交给窗口处理函数来处理
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦里捡到一只猫丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值