前言:我们需要用windows 窗口来绘制3D图形,所以,第一篇文章就来说说如何创建一个窗口。
我们的主要目标是用DirectX 绘制3D图形,复杂的windows控件在这个系列中并不会涉及,所以大家不要有畏难心理。本篇开发的窗口应用在后续开发中仍然使用。
总架构图:
其中消息循环和回调函数与main函数 初始化函数类似于一种是并列的意思。
窗口初始化流程图
消息循环流程图
完整代码:
#include "stdafx.h"
#include<Windows.h>
//有句柄,就能操作对应窗口。
HWND MainWindowHandle = 0;
bool InitWindowsApp(HINSTANCE instanceHandle, int show);
int Run();
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
/*
WinMain 函数就是C/C++中的main函数。是程序运行的入口。
//应用程序的引用(也叫句柄)
//设为0即可
//PSTR 是char类型的指针(==char *)
*/
int WINAPI WinMain( HINSTANCE hWInstance,HINSTANCE hPrevInstance,PSTR pCmdLine,int nShowCmd) {
//按当前尺寸显示、最大化、最小化
if (!InitWindowsApp(hWInstance, nShowCmd)) {//进入winmain函数的内部
::MessageBox(0, L"Init - Failed", L"Error", MB_OK);
return 0;
}
return Run();
}
//一,本函数用于应用程序初始化
bool InitWindowsApp(HINSTANCE instanceHandle, int show)
{//设置应用程序句柄和窗口显示方式
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
//wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
//wc.lpfnWndProc = WndProc;//将过程函数和窗口关联起来
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = instanceHandle;//保存应用程序实例的句柄
wc.hIcon = ::LoadIcon(0, IDI_APPLICATION);
wc.hCursor = ::LoadCursor(0, IDC_ARROW);
wc.hbrBackground = static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH));//设置背景颜色
wc.lpszMenuName = 0;//没有使用菜单,所以设为0
wc.lpszClassName = L"Hello";
if (!::RegisterClass(&wc)) {
::MessageBox(0, L"Register-Failed", 0, 0);
return false;
}
//HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
// CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
MainWindowHandle = CreateWindow(//创建成功就会返回窗口句柄(HWND类型),创建失败,返回0.
L"Hello",
L"Hello",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,//该窗口的父窗口句柄。没有父窗口就设为0
0,//没菜单,设为0
instanceHandle,
nullptr
);
if (MainWindowHandle == 0) {
::MessageBox(0, L"CreateWindow-Failed", 0, 0);
return false;
}
::ShowWindow(MainWindowHandle, show);//传递一个窗口句柄,这样windows就知道要显示哪个窗口了。
::UpdateWindow(MainWindowHandle);
return true; //一切正常,将返回true
}
//二,消息循环
int Run()
{
MSG msg;
while (true) {//peekMesage检查是否有新消息,如果哟
if (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT)
break;
::TranslateMessage(&msg);
::DispatchMessage(&msg);//将消息发送到WndProc中进行处理
}
else {
//运行你的代码
}
}
return msg.wParam;
}
//三,消息处理
LRESULT CALLBACK WndProc(HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
//LRESULT==Long 类型的结果。
//CALLBACK表示会掉函数。
//windows帮我们调用这个函数
switch (msg) {
case WM_LBUTTONDOWN:
::MessageBox(0, L"Hello , World",L"Hello", MB_OK);
return 0;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE) {
::DestroyWindow(MainWindowHandle);
}
return 0;
case WM_DESTROY://告诉Run(),我要退出消息循环
::PostQuitMessage(0);
return 0;
}
return ::DefWindowProcW(MainWindowHandle,
msg,
wParam,
lParam);
}