創(chuàng)建時(shí)間:2019.07.06
修改時(shí)間:ONE 2019.07.07
官方標(biāo)準(zhǔn)教程中使用GLFW來(lái)創(chuàng)建OpenGL的窗體,處理輸入相關(guān)消息耗式。本文瞎寫如何在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;
}
運(yùn)行結(jié)果
主要分為三步:注冊(cè)窗口--->創(chuàng)建窗口--->顯示窗口
1.注冊(cè)窗口
1.1代碼詳解
//窗口應(yīng)用程序需包含的頭文件
#include <Windows.h>
//窗口應(yīng)用程序中,入口函數(shù) WinMain();
//返回值類型 函數(shù)修飾符(調(diào)用方式) WinMain函數(shù)名
INT WINAPI WinMain(HINSTANCE hInstance/*當(dāng)前應(yīng)用程序?qū)嵗?/, HINSTANCE hPrevInstance/*上一次應(yīng)用程序啟動(dòng)的實(shí)例*/, LPSTR lpCmdLine/*用cmd打開刊咳,命令行參數(shù)*/, int nShowCmd/*如何顯示窗口*/)
{
return 0;
}
運(yùn)行結(jié)果
1.2準(zhǔn)備工作
//定義WNDCLASSEX結(jié)構(gòu)體彪见,一個(gè)怎樣的窗口
WNDCLASSEX wndclass;
//窗口類型的額外控件
wndclass.cbClsExtra = 0;
//實(shí)際占用的多大內(nèi)存
wndclass.cbSize = sizeof(WNDCLASSEX);
//額外內(nèi)存
wndclass.cbWndExtra = 0;
//窗口部分,沒(méi)有包含旁邊的邊框
wndclass.hbrBackground = NULL;
//光標(biāo)
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
//應(yīng)用程序放在磁盤上的圖標(biāo)
wndclass.hIcon = NULL;
//程序運(yùn)行后娱挨,顯示在左上角的圖標(biāo)
wndclass.hIconSm = NULL;
//
wndclass.hInstance = hInstance;
//處理用戶操作函數(shù)
wndclass.lpfnWndProc = NULL;
//窗口名稱
wndclass.lpszClassName = L"GLWindow";
//菜單的名字
wndclass.lpszMenuName = NULL;
//窗口更新時(shí)余指,采用哪種重繪方式 水平|垂直
wndclass.style = CS_VREDRAW | CS_HREDRAW;
1.3注冊(cè)窗口
//注冊(cè)窗口
ATOM atom = RegisterClassEx(&wndclass);
if (!atom)
{
MessageBox(NULL, L"Notice", L"Error", MB_OK);
return 0;
}
運(yùn)行結(jié)果
2.創(chuàng)建窗口
2.1準(zhǔn)備工作
在創(chuàng)建窗口之前需要新增用戶操作函數(shù),更改第一步注冊(cè)窗口中的準(zhǔn)備工作相關(guān)代碼跷坝。
//處理用戶操作函數(shù)
//wndclass.lpfnWndProc = NULL;
wndclass.lpfnWndProc = GLWindowProc;
定義消息處理函數(shù)酵镜,監(jiān)聽(tīng)并處理用戶對(duì)窗口的操作
LRESULT CALLBACK GLWindowProc(HWND hwnd/*窗口句柄*/, UINT msg/*消息ID*/, WPARAM wParam/*附帶參數(shù)*/, LPARAM IParam/*附帶參數(shù)*/)
{
switch (msg)
{
//關(guān)閉按鈕,退出消息
case WM_CLOSE:
PostQuitMessage(0);
return 0;
}
//默認(rèn)消息處理函數(shù)去處理
return DefWindowProc(hwnd, msg, wParam, IParam);
}
2.2創(chuàng)建窗口
HWND hwnd = CreateWindowEx(NULL/*窗口額外的風(fēng)格*/, L"GLWindow"/*注冊(cè)時(shí)窗口的名稱*/, L"OpenGL Window"/*顯示在窗口標(biāo)題欄上的字符串*/, WS_OVERLAPPEDWINDOW/*窗口風(fēng)格*/,
100, 100, 800, 600/*包含窗口邊框部分的寬和高*/,
NULL/*父窗口句柄*/, NULL/*菜單句柄*/, hInstance/*應(yīng)用程序?qū)嵗?/, NULL/*額外的參數(shù)*/);
運(yùn)行結(jié)果
3.顯示窗口
3.1顯示窗口
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
運(yùn)行結(jié)果
窗口一閃而過(guò)
3.2程序不退出
//使應(yīng)用程序不退出————死循壞
MSG msg;
while (true)
{
//從系統(tǒng)的消息隊(duì)列里獲取消息
if (PeekMessage(&msg/*存取消息的變量*/, NULL/*獲取哪個(gè)消息的變量柴钻,所有*/, NULL/*消息IDmin */, NULL/*消息IDmax淮韭,不對(duì)消息過(guò)濾*/, PM_REMOVE/*如何處理消息,從消息隊(duì)列中移除掉*/))
{
if (msg.message == WM_QUIT)
{
break;
}
//轉(zhuǎn)換成應(yīng)用程序可以識(shí)別的消息
TranslateMessage(&msg);
//將消息派發(fā)出去
DispatchMessage(&msg);
}
}
運(yùn)行結(jié)果
參考博客
https://blog.csdn.net/qq_22822335/article/details/50911858