〇.前言————————————————————
+
学Windows窗体已经有一段时日了,奈何没有什么浅显易懂(&便宜!!)的书籍 , 就想来 , 算是记笔记吧 , 顺便还能给你们总结一些经验
注:有许多内容源于我看过的一些视频 , 比如Chili和Cherno的 , 大家也可以去搜一搜
一.准备————————————————————
我为什么要写这一栏,又不是OpenGL,算了,我喜欢~
1.Windows 10
2. VisualStudio2022 (没错,我可勇了)
3.笔记本
4.你的注意力(好吧,我承认,这是不可能的)
二.开始————————————————————
今天,我们的目标是,制作一个空白窗口
1.创建——————————
step1:新建项目 -> 选择空项目
不要选WindowsXXXXXX的,它有附带文件,一上来你可能看不懂
step2:填入解决方案名称
选择文件路径
点击创建
step3:右键"源文件" -> 选择"添加" -> 选择"新建项"
step4:选择C++文件
文件名取"WinMain.cpp"
点击添加
step5:右键"解决方案"下面的"WinMain" -> 选择"属性"
step6:选择"所有配置"
找到配置属性 -> 链接器 -> 系统
step7:将"子系统"改为"窗口"
2.代码——————————
首先,让我们来认识一下,你所见过的最简单的窗体程序,当然是Visu记事本啦
一个极简的窗体,实际上只有窗体内部,但记事本还加上了菜单和滑动条,默认地,窗体会自带最小化、全屏和关闭,你可以在WM_中设置
你看,当你在记事本中按一些按键的时候,他居然也能显示相同的字母!!
别觉得我很奇怪,这并不是理所当然的,这是由消息处理函数决定的,这在以后的事件中会讲解
最后,和控制台程序类似,窗体程序需要一个进入点main,在窗体程序中,它叫做WinMain
————————————————————
0.头文件——Windows.h
既然是Windows窗体程序,那肯定要Windows.h头文件啦~
#include <Windows.h>
————————————————————
1.WinMain——窗体程序的进入点
WinMain有个固定的格式:
int __stdcall WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPWSTR lpCmdLine,
int nCmdShow
)
解析
这些内容由系统指定:
__stdcall:这是一个扩展,我们平常看到的CALLBAK等宏都是指它
__stdcall指定了参数传递的方式,及堆栈的管理者
hInstance = handle(句柄) + Instance(实例)
指当前程序的句柄(类比指针)用于之后的创建
hPrevInstance = handle + Previous(上一个) + Instance
指上一级程序的句柄,Win16使用,现今基本不用
LPWSTR = Long + Pointer(指针) + Wide + STRing(字符串)
在定义中,我们可以发现它是WCHAR(宽字符串)的指针
lpCmdLine = LPWSTR + Command(命令) + Line
用于传递命令(类型为WCHAR)
nCmdShow:no + Command + Show
用于设置默认窗口样式,不是特别有用
——————————————————————
好的,既然已经把进入点准备好了,那么点击“编译”,你就会得到……什么都没有
当然啦,你都没有“召唤”出你的窗口界面,所以我们需要定制它的样式,它的属性,这些,我们需要在窗口类中注册
————————————————————
2.注册窗口类
首先,我们需要定义一个类:WNDCLASS(WindowClass),放在WinMain()中
此处我们使用加强(EX)版和Ansi(多字节字符串)版本,即WNDCLASSEXA
那这个对象我们不妨取作WC咳咳,Winc
WNDCLASSEXA Winc;
Winc = { 0 };
ZeroMemory( &Winc, sizeof( Winc ) );
接下来,我们需要把它清空,可以直接让他 = { 0 },也可以用ZeroMemory
创建好对象后,我们来看看它的其中一部分属性
Winc.cbSize =
Winc.style =
Winc.lpfnWndProc =
Winc.cbClsExtra =
Winc.cbWndExtra =
Winc.hInstance =
Winc.hIcon =
Winc.hCursor =
Winc.hbrBackground =
Winc.lpszMenuName =
Winc.lpszClassName =
别被吓到啦,来看看这些属性分别是什么意思:
cbSize —— 类的大小,填 sizeof( Winc ) 即可
style —— Class样式,具体参考Microsoft —— ClassStyle
要同时选用多种,用 | 隔开eg. CS_A | CS_B
lpfnWndProc —— 消息处理函数,后面会讲
cbClsExtra —— 类额外字节数,一般置0
cbWndExtra —— 窗体额外字节数,一般置0
hInstance —— 输入WinMain中的hInstance即可
hIcon、hCursor、hbrBackground之后再讲解
lpszMenuName —— 菜单栏样式,在resource.h与资源文件夹中定义
lpszClassName —— 类名,输入一个字符串即可
在注册完之后,我们把它丢到RegisterClass中就可以啦(EXA解释同上)
//这边是示例
WNDCLASSEXA Winc = { 0 };
Winc.cbSize = sizeof( Winc );
Winc.style = CS_OWNDC;
Winc.lpfnWndProc = MessageSetup;
Winc.cbClsExtra = 0;
Winc.cbWndExtra = 0;
Winc.hInstance = hInstance;
Winc.hIcon = nullptr;
Winc.hCursor = nullptr;
Winc.hbrBackground = nullptr;
Winc.lpszMenuName = nullptr;
Winc.lpszClassName = "wind2067 is handsome";
RegisterClassExA( &Winc );
————————————————————
3.CreateWindow——创建窗口组件
这边需要声明的是,我们先前认识的窗口,其实很狭义,事实上按钮、文本框、复选框以及它本身,都叫做Window
为了简化格式,我们使用Ansi版本的函数,即CrateWindowA(实际上是EXA)
CreateWindowA的定义如下:
HWND WINAPI CreateWindowExA(
_In_ DWORD dwExStyle,
_In_opt_ LPCSTR lpClassName,
_In_opt_ LPCSTR lpWindowName,
_In_ DWORD dwStyle,
_In_ int X,
_In_ int Y,
_In_ int nWidth,
_In_ int nHeight,
_In_opt_ HWND hWndParent,
_In_opt_ HMENU hMenu,
_In_opt_ HINSTANCE hInstance,
_In_opt_ LPVOID lpParam);
emm,先不管"_In_opt"这些,先来赏析一下这些形参:
DOWRD —— 就是int
dwExStyle —— 增强版窗口样式,参考Microsoft —— Extended WindowStyle
lpClassName —— 我们刚刚定义的类名
lpWindowName —— 窗口标题
dwStyle —— 窗口样式,参考Microsoft —— WindowStyle
X、Y —— 窗口出现时的位置(相对坐标)
nWidth、nHeight —— 窗口出现时的宽高
hWndParent —— 父窗口,需要WS_CHILD
lpParam —— 由于涉及到消息处理,之后再谈
创建完之后,我们得到了一个HWND(Handle Window),需要用HWND接收:
HWND hWnd = CreateWindow( … );
最后,我们将它用ShowWindow显示出来:
ShowWindow( hWnd, SW_SHOWDEFAULT );
注:SW = Show + Window
//这边是示例
hWnd = CreateWindowA(
"wind2067 is handsome",
"Subscribe!!!",
WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT, //CW = CreateWindow
0, 0,
nullptr, nullptr,
hInstance,
nullptr;
);
ShowWindow( hWnd, SW_SHOWDEFAULT );
就这样,点击编译,你就可以看到一个白白嫩嫩的窗口啦~~~
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)