1、前言
本文提供广大读者一个最基本的窗口模板,提高编写代码的效率,同时给初学者一个参考。
2、注意事项
① 相比于之前黑乎乎的控制台窗口,我们所做的是windows下一般意义上的窗口。
② 在使用VS创建时,需要选择 项目->属性->链接器->系统->子系统 将子系统从控制台变为窗口。
3、代码
本人提供在此一份“洁癖”版本的模板代码,消除了所有警告信息。
在WinMain函数参数中添加_In_是为了消除VS2019下标注不匹配的警告
在返回值msg.wParam前使用强制类型转换是为了消除返回值不匹配的警告
以上两点删除也不会影响程序运行结果,执行
3.1 带注释版的模板程序(可直接copy运行)
//需要包含Windows.h头文件,我们的所有API都在这个头文件里
#include<Windows.h>
//处理消息循环的回调函数
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//WinMain函数,窗口的主入口函数,相当于控制台下的main函数
int WINAPI WinMain(_In_ HINSTANCE hInstance,//应用程序当前实例的句柄
_In_opt_ HINSTANCE hPrevInstance, //应用程序的先前实例的句柄。对于一个32位程序,该参数总为NULL。属于历史遗留产物,一般不做使用。
_In_ LPSTR lpCmdLine,//指向应用程序命令行的字符串的指针
_In_ int iCmdShow) {//指明窗口如何显示,一般不做使用
//第一步,初始化窗口类
//填充WNDCLASS这一结构体下的所有参数
WNDCLASS wndclass;
wndclass.cbClsExtra = 0;//窗口类无扩展
wndclass.cbWndExtra = 0;//窗口实例无扩展
wndclass.hInstance = hInstance; //当前实例句柄
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);//窗口的最小化图标为缺省图标
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); // 窗口采用箭头光标
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //窗口背景为白色
wndclass.lpszMenuName = NULL; //窗口无菜单
wndclass.lpszClassName = L"模板";//窗口类名为“模板”
wndclass.style = CS_HREDRAW | CS_VREDRAW;// 窗口类的风格,CS_HREDRAW表示窗口在水平方向改变或移动时重绘窗口,CS_VREDRAW表示垂直方向
wndclass.lpfnWndProc = WndProc;定义窗口处理函数
//第二步,注册窗口
if (!RegisterClass(&wndclass)) {//注册窗口,如果成功返回非零
MessageBox(NULL, L"注册窗口失败", L"提示", MB_OK);
return 0;
}
//第三步,创建窗口
//借助CreateWindow完成操作
//如果函数成功,返回值为新窗口的句柄
//如果函数失败,返回值为NULL。若想获得错误信息,可调用GetLastError函数。
HWND hwndModel;
hwndModel = CreateWindow(L"模板",//创建窗口的类名,可以是系统自带的控件风格,也可以是任意注册窗口时使用的类名。
L"模板",//窗口名
WS_OVERLAPPEDWINDOW,//窗口风格
CW_USEDEFAULT,//窗口的起始位置(x坐标)CW_USEDEFAULT表示使用默认位置
CW_USEDEFAULT,//窗口的起始位置(y坐标)
CW_USEDEFAULT,//窗口的长
CW_USEDEFAULT,//窗口的宽
NULL,//创建窗口的父窗口或所有者窗口的句柄。
NULL,//菜单句柄,或者依据窗口风格指明一个子窗口标识
hInstance,//与窗口相关联的模块实例的句柄。
NULL);//指向一个值的指针,该值传递给窗口WM_CREATE消息。
//第四步,显示窗口
ShowWindow(hwndModel, SW_SHOW);
//第五步,更新窗口
UpdateWindow(hwndModel);
//第六步,创建消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {//获取消息
TranslateMessage(&msg);//将虚拟键消息转换为字符消息
DispatchMessage(&msg);//将消息分窗口处理函数处理
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CLOSE://点击关闭按钮时,windows会向窗口发送一个WM_CLOSE
case WM_DESTROY: {//紧接着,发送WM_DESTROY消息,完成窗口的清理工作
PostQuitMessage(0);//终止消息循环
return 0;
}
}
//DefWindowProc函数为应用程序没有处理的任何窗口消息提供缺省的处理,确保每一个消息得到处理。
//我们所使用到的消息是整个窗口创建到毁灭过程中的很少的一部分
//如果想知道所有的消息过程,可以打印lParam中的所有信息
return DefWindowProc(hWnd, msg, wParam, lParam);
}
3.2 无注释版 (可直接copy运行,适合实际开发作为模板使用)
#include<Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int iCmdShow) {
WNDCLASS wndclass;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = L"模板";
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
RegisterClass(&wndclass);
HWND hwndModel;
hwndModel = CreateWindow(L"模板", L"模板", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwndModel, SW_SHOW);
UpdateWindow(hwndModel);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CLOSE:
case WM_DESTROY: {
PostQuitMessage(0);
return 0;
}
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}