创建时间:2019.07.06
修改时间:ONE 2019.07.07
官方标准教程中使用GLFW来创建OpenGL的窗体,处理输入相关消息。本文瞎写如何在win32下搭建OpenGL窗口。
完整代码
#include <Windows.h>
LRESULT CALLBACK GLWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM IParam)
{
switch (msg)
{
case WM_CLOSE:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, IParam);
}
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASSEX wndclass;
wndclass.cbClsExtra = 0;
wndclass.cbSize = sizeof(WNDCLASSEX);
wndclass.cbWndExtra = 0;
wndclass.hbrBackground = NULL;
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hIcon = NULL;
wndclass.hIconSm = NULL;
wndclass.hInstance = hInstance;
wndclass.lpfnWndProc = GLWindowProc;
wndclass.lpszClassName = L"GLWindow";
wndclass.lpszMenuName = NULL;
wndclass.style = CS_VREDRAW | CS_HREDRAW;
ATOM atom = RegisterClassEx(&wndclass);
if (!atom)
{
MessageBox(NULL, L"Notice", L"Error", MB_OK);
return 0;
}
HWND hwnd = CreateWindowEx(NULL, L"GLWindow", L"OpenGL Window", WS_OVERLAPPEDWINDOW,
100, 100, 800, 600,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
MSG msg;
while (true)
{
if (PeekMessage(&msg, NULL, NULL, PM_REMOVE)
{
if (msg.message == WM_QUIT)
{
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
运行结果
主要分为三步:注册窗口--->创建窗口--->显示窗口
1.注册窗口
1.1代码详解
//窗口应用程序需包含的头文件
#include <Windows.h>
//窗口应用程序中,入口函数 WinMain();
//返回值类型 函数修饰符(调用方式) WinMain函数名
INT WINAPI WinMain(HINSTANCE hInstance/*当前应用程序实例*/, HINSTANCE hPrevInstance/*上一次应用程序启动的实例*/, LPSTR lpCmdLine/*用cmd打开,命令行参数*/, int nShowCmd/*如何显示窗口*/)
{
return 0;
}
运行结果
1.2准备工作
//定义WNDCLASSEX结构体,一个怎样的窗口
WNDCLASSEX wndclass;
//窗口类型的额外控件
wndclass.cbClsExtra = 0;
//实际占用的多大内存
wndclass.cbSize = sizeof(WNDCLASSEX);
//额外内存
wndclass.cbWndExtra = 0;
//窗口部分,没有包含旁边的边框
wndclass.hbrBackground = NULL;
//光标
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
//应用程序放在磁盘上的图标
wndclass.hIcon = NULL;
//程序运行后,显示在左上角的图标
wndclass.hIconSm = NULL;
//
wndclass.hInstance = hInstance;
//处理用户操作函数
wndclass.lpfnWndProc = NULL;
//窗口名称
wndclass.lpszClassName = L"GLWindow";
//菜单的名字
wndclass.lpszMenuName = NULL;
//窗口更新时,采用哪种重绘方式 水平|垂直
wndclass.style = CS_VREDRAW | CS_HREDRAW;
1.3注册窗口
//注册窗口
ATOM atom = RegisterClassEx(&wndclass);
if (!atom)
{
MessageBox(NULL, L"Notice", L"Error", MB_OK);
return 0;
}
运行结果
2.创建窗口
2.1准备工作
在创建窗口之前需要新增用户操作函数,更改第一步注册窗口中的准备工作相关代码。
//处理用户操作函数
//wndclass.lpfnWndProc = NULL;
wndclass.lpfnWndProc = GLWindowProc;
定义消息处理函数,监听并处理用户对窗口的操作
LRESULT CALLBACK GLWindowProc(HWND hwnd/*窗口句柄*/, UINT msg/*消息ID*/, WPARAM wParam/*附带参数*/, LPARAM IParam/*附带参数*/)
{
switch (msg)
{
//关闭按钮,退出消息
case WM_CLOSE:
PostQuitMessage(0);
return 0;
}
//默认消息处理函数去处理
return DefWindowProc(hwnd, msg, wParam, IParam);
}
2.2创建窗口
HWND hwnd = CreateWindowEx(NULL/*窗口额外的风格*/, L"GLWindow"/*注册时窗口的名称*/, L"OpenGL Window"/*显示在窗口标题栏上的字符串*/, WS_OVERLAPPEDWINDOW/*窗口风格*/,
100, 100, 800, 600/*包含窗口边框部分的宽和高*/,
NULL/*父窗口句柄*/, NULL/*菜单句柄*/, hInstance/*应用程序实例*/, NULL/*额外的参数*/);
运行结果
3.显示窗口
3.1显示窗口
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
运行结果
窗口一闪而过
3.2程序不退出
//使应用程序不退出————死循坏
MSG msg;
while (true)
{
//从系统的消息队列里获取消息
if (PeekMessage(&msg/*存取消息的变量*/, NULL/*获取哪个消息的变量,所有*/, NULL/*消息IDmin */, NULL/*消息IDmax,不对消息过滤*/, PM_REMOVE/*如何处理消息,从消息队列中移除掉*/))
{
if (msg.message == WM_QUIT)
{
break;
}
//转换成应用程序可以识别的消息
TranslateMessage(&msg);
//将消息派发出去
DispatchMessage(&msg);
}
}
运行结果
参考博客
https://blog.csdn.net/qq_22822335/article/details/50911858