Windows窗口(DirectX3D11学习笔记)

本文档是DirectX3D11学习的起点,从创建Windows窗口开始,介绍了创建窗口前的Visual Studio设置,讲解了Windows窗口的基本概念、创建窗口的步骤,包括Windows程序入口函数、注册窗体、实例化窗体和显示,以及窗口消息处理。通过自定义窗口类和消息处理机制,实现窗口关闭时退出程序的功能。此外,还涵盖了键盘输入的处理和自定义异常处理类的设计。
摘要由CSDN通过智能技术生成

前言

今天开个新坑,开始学习D3D,教程为https://www.youtube.com/channel/UCsyHonfwHi4fLb2lkq0DEAA,先从做一个Windows窗口开始。


创建窗口前的VS设置

为了适应接下来的工程,我们要对VS进行一些设置,首先将字符集设置为多字节字符集。
在这里插入图片描述

将VS的多处理器编译打开。
在这里插入图片描述

设置代码速度优先。
在这里插入图片描述
给Release下配置预处理器定义:NDEBUG,NDEBUG宏将调试时使用到的assert代码定义为空的,提高Release版本的程序运行效率。
在这里插入图片描述
运行时库选择静态库就可以。
在这里插入图片描述
浮点模型设置为快速模型。
在这里插入图片描述
C++标准使用最新的。
在这里插入图片描述
最后,将子系统设置为窗口。
在这里插入图片描述

Windows窗口简介

在这里插入图片描述
窗口分为两个部分,一个是窗口本身,一个是消息处理。

创建Windows窗口

Windows程序入口函数

每个程序都有一个入口,WinMain函数是Windows应用程序的入口程序,代码如下。

#include < Windows.h>

int CALLBACK WinMain(
	HINSTANCE hInstance,
	HINSTANCE hPrevInstance,
	LPSTR     lpCmdLine,
	int       nCmdShow)
{
   
	return 0;
}

要编写Windows窗口程序,需要引用Windows.h。关于WinMain的几个参数(被chill形容为junk),我现在能做出的解释如下:

  • HInstance是一个用来指向应用程序实例信息的指针
  • 第一个HInstance参数hInstance指向当前应用程序实例的信息。
  • 第二个HInstance参数hPrevInstance指向先前应用程序实例的信息,值得注意的是这个参数总是为NULL,也许是属于Windows那么多年以来的历史遗留。
  • 第三个LPSTR参数用来接收程序开始运行时,用户通过控制台端输入的额外参数。LPSTR只是char *的类型别名。C/C++的main函数也有类似的参数。
  • 第四个int参数用来决定我们这个程序的窗体用何种方法展示出来。比如说传入0(预处理宏为:SW_HIDE)的意思为:隐藏当前窗体并打开另一个窗体。具体有那些方式可以参考微软的MSDN。
  • 在函数名WinMain前方还有一个CALLBACKCALLBACK是函数修饰符,他的作用是告诉C++这个函数要用一个叫stdcall的调用约定。这个调用约定使得函数在栈上传递参数的方法与标准C的调用约定(cdecl)略有不同。WindowsAPI使用的应该都是stdcall调用约定。

注册窗体

当然,如果你直接将上面的代码复制到你的文件中编译,你不会得到一个窗口,因为要实现一个窗口,还有很多事情要做。即使是写个控制台程序,为了把控制台窗口拿给你看,系统在幕后也做了很多工作。要创建一个窗口,我们需要将使用一个叫Register的函数向系统注册我们将要创建的窗空的信息(样式啥的),然后我们才可以用另一个函数实例化一个窗口出来。这个过程有点像假如说Windows是一个C++类(但是实际上窗口不是C++类),我们去实例化它了以后才有。

为了创建窗体,我们将使用RegisterClassEx()函数,Ex表示他是标准的创建函数,其需要一个叫WNDCLASSEX结构的指针,WNDCLASSEX结构里包含了窗体的信息参数(MSDN)。WindowAPI很多都需要某个结构的指针,这也算是它们的特点,相比于直接将结构拷贝过去,传指针显然效率更好。

ATOM RegisterClassExA(
  const WNDCLASSEXA *unnamedParam1
);
typedef struct tagWNDCLASSEXA {
   
  UINT      cbSize;
  UINT      style;
  WNDPROC   lpfnWndProc;
  int       cbClsExtra;
  int       cbWndExtra;
  HINSTANCE hInstance;
  HICON     hIcon;
  HCURSOR   hCursor;
  HBRUSH    hbrBackground;
  LPCSTR    lpszMenuName;
  LPCSTR    lpszClassName;
  HICON     hIconSm;
} WNDCLASSEXA, *PWNDCLASSEXA, *NPWNDCLASSEXA, *LPWNDCLASSEXA;

首先我们定义一个WNDCLASSEX结构的变量wc。

	const auto className = "CurtainXT's";
	// 注册窗体类型
	WNDCLASSEX wc = {
    0 };
	wc.cbSize = sizeof(wc);
	wc.style = CS_OWNDC;
	wc.lpfnWndProc = DefWindowProc;
	wc.cbClsExtra = 0;
	wc.cbWndExtra = 0;
	wc.hInstance = hInstance;
	wc.hIcon = nullptr;
	wc.hCursor = nullptr;
	wc.hbrBackground = nullptr;
	wc.lpszMenuName = nullptr;
	wc.lpszClassName = className;
	wc.hIconSm = nullptr;
	RegisterClassEx(&wc);

这些信息里面值得一提的是:wc.cbSize = sizeof(wc)存储了这个结构体的大小,wc.style = CS_OWNDC代表我们会为这个Class的每一个窗口都有一个设备上下文,使得可以窗口中显示窗口,wc.lpfnWndProc = DefWindowProc是一个Windows Procedure指针,代表你想要这个窗口使用何种消息处理机制,这里我们先使用默认消息处理机制,wc.hbrBackground = nullptr设置为null是因为我们将使用DX来渲染窗口,所以不需要系统再帮我们提前渲染一次。

实例化并显示窗体

为了将窗口实例化,我们使用CreateWindowEx()函数(MSDN链接),该函数参数会定义窗口创造时的样式和行为,比如长宽,创建的位置,是否允许拖拽、透明等等等。

HWND CreateWindowExA(
  DWORD     dwExStyle,
  LPCSTR    lpClassName,
  LPCSTR    lpWindowName,
  DWORD     dwStyle,
  int       X,
  int       Y,
  int       nWidth,
  int       nHeight,
  HWND      hWndParent,
  HMENU     hMenu,
  HINSTANCE hInstance,
  LPVOID    lpParam
);

CreateWindowEx()会返回一个HWND类型的值,这是创建的窗口的handle,我们用这个handle在代码中操作这个窗口。

	// 创建窗体实例
	HWND hWnd = CreateWindowEx(
		0, className, "Hello World",
		WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,
		200, 200, 640, 480,
		nullptr, nullptr,
		hInstance, nullptr
	);

这里面的参数查看MSDN了解详情。如果你代码写到这里,点击运行会发现依旧啥都没有,这是因为为了让我们看到窗口,我们还需要将窗口显示出来,我们使用ShowWindow()实现这一点(MSDN链接)。

BOOL ShowWindow(
  HWND hWnd,
  int  nCmdShow
);
	// 将窗体显示出来
	ShowWindow(hWnd, SW_SHOW);

现在我们的窗口终于出来了,可是这个窗体啥都干不了,连关闭都要靠停止调试,所以接下来我们将学习窗口的消息处理。
在这里插入图片描述

窗口消息处理

事件驱动编程简介

在学习窗口消息之前,先学习一下什么是事件驱动编程(Event Driven Programming),简单来说,事件驱动编程写出来的程序只要在用户操作产生事件时它们才会进行相应的处理,如果什么事件都没有࿰

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值