1.填充窗口类
2.创建窗口
3.显示窗口
4.更新窗口
5.建立消息循环
6.实现窗口过程函数
#include
const WCHAR *wszClassName = L"rkvir"; 定义一个窗口类名
const WCHAR *wszTitle = L"GrkDemo"; 定义一个标题名
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 声明主窗口过程 CALLBACK为回调函数 参数依次是 窗口句柄 消息 参数 参数
{
switch (message) 根据接收到的消息进行不同的分发
{
case WM_COMMAND: 处理应用的程序菜单,如点击程序帮助,接收的消息都会发送到此处
{
break;
}
case WM_PAINT: 绘制主窗口
{
PAINTSTRUCT ps; PAINTSTRUCT为一个结构,包含窗口的信息
HDC hDC = BeginPaint(hWnd, &ps); 绘制窗口 参数依次 窗口句柄 窗口结构
EndPaint(hWnd, &ps);
break;
}
case WM_DESTROY: 退出程序,必须有,否则点击窗口关闭,窗口消失但线程无法结束
{
PostQuitMessage(0); 向操作系统发送已经终止/退出的请求
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam); 默认窗口过程,处理接不住的消息
break;
}
return 0;
}
ATOM MyRegisterClass(HINSTANCE hInstance) ATOM实际是WORD别名
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX); 填充结构尺寸
wcex.style = CS_HREDRAW | CS_VREDRAW; 填充窗口的风格
wcex.lpfnWndProc = WndProc; Windows窗口的主过程(消息的处理函数)
wcex.cbClsExtra = 0; 跟在窗口类结构后面的附加字节数,给类预留的空间
wcex.cbWndExtra = 0; 跟在窗口实例后面的附加字节数,给实例预留的空间
wcex.hInstance = hInstance; 实例句柄
wcex.hIcon = 0; 图标 如果没有则值为0,若有调用oadIcon接口,图标的格式是ico
wcex.hCursor = 0; 光标 如果没有则值为0,若有调用LoadCursor接口加载
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); 类背景画笔的句柄
wcex.lpszMenuName = 0; 菜单的句柄,没有时值为0
wcex.lpszClassName = wszClassName; 指向类名称的句柄,一般说类名称必须有
wcex.hIconSm = 0; 任务栏图标,如果没有则值为0,若有调用oadIcon接口
return RegisterClassExW(&wcex); 注册窗口类
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow); 初始化即创建窗口 参数为实例句柄和显示模式
{
HWND hWnd = CreateWindow(wszClassName , wszTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 500, 500, nullptr, nullptr, hInstance, nullptr);
参数依次 窗口类名称 标题名 风格 x坐标,如上参数是一个绝对坐标 y坐标 宽度 高度 副窗口句柄,没有写nullptr 菜单句柄,没有写nullptr 实例句柄 参数,没有填nullptr,其返回值是一个窗口句柄
此时窗口在内存中被创建,但并没有被显示
if (!hWnd) 判断窗口是否被创建
{
return FALSE; 窗口创建失败,直接返回
}
ShowWindow(hWnd, nCmdShow); 显示窗口:参数依次窗口句柄 命令行用于填充显示模式
UpdateWindow(hWnd); 更新窗口 参数为句柄
return TRUE;
}
当主程序代码块为空时,程序运行时有控制台一闪而过,利用system(“pause”)可以观察到,但是
Windows程序内会有一个消息循环(死循环)所以可以不用利用该函数
Windows是以消息驱动的操作系统,需要不停获取消息并分发,也叫消息循环
进程中存在消息队列,用于存储消息。
Windows系统会对消息进行填充并发放到消息队列中,此时进程类的窗口的消息循环会从队列中取
回并派发到窗口过程函数中进行处理,处理完毕后返回到消息循环,再次访问消息队列,重复以上
操作,叫做消息循环
消息结构包含:
HWND hwnd; 窗口句柄
UINT message; 消息
WPARAM wParam; 消息的附加信息
LPARAM lParam; 消息的附加信息
DWORD time; 消息的创建发布时间
POINT pt; 消息发送时,光标所在的位置
MSG msg; MSG结构:消息结构 GetMessage在消息队列中获取消息
while (GetMessage(&msg,nullptr,0,0)) 窗口主循环,它是个死循环,GetMessage()参数依次是 消息地址 其余默认填nullptr 0 0
{
TranslateMessage(&msg); 翻译传入的消息,如键盘打字传入的消息是虚拟键码,此处转换成字符消息
DispatchMessage(&msg); 派发消息
}
程序入口 参数依次实例句柄 被启用的实例句柄 命令行 LPWSTR实际是对WCHAR的封装,与之类
似还有LPSTR和char 显示模式,int类型
int APIENTRY wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPWSTR
lpCmdLine,int nCmdShow)
{
MyRegisterClass(hInstance); 填充窗口类
if (!InitInstance(hInstance, nCmdShow)) 判断该窗口是否创建成功
{
return FALSE;
}
MSG msg;
while (GetMessage(&msg,nullptr,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
此时一个窗口构建完毕,运行程序结果是