02. Win32 API简介
我将复制DirectX 9中的创建窗口课程,因为它们是相同的。这里有很多代码可以入门,但是一旦完成,我们就可以开始实际使用DirectX。
我们的应用程序首先包含windows.h头文件。当创建一个窗口时,需要为该窗口创建一个Windows类,这就是下一行的用途。在下面,这只是我们窗口的句柄
#include <windows.h>
LPCTSTR WndClassName = “firstwindow”;
HWND hwnd = NULL;
我们将使用这些常量定义窗口的宽度和高度
const int Width = 800;
const int Height = 600;
bool InitializeWindow(HINSTANCE hInstance,
int ShowWnd,
int width, int height,
bool windowed);
int messageloop();
我们初始化Windows回调过程。Windows API是“事件驱动”的编程模型,因此在此功能中,我们可以“捕获” Windows消息,例如按键(也称为事件)并操纵程序的流程。
LRESULT CALLBACK WndProc(HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, //Main windows function
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
if(!InitializeWindow(hInstance, nShowCmd, Width, Height, true))
{
MessageBox(0, "Window Initialization - Failed",
"Error", MB_OK);
return 0;
}
messageloop();
return 0;
}
int ShowWnd - How the window should be displayed. Some common commands are SW_SHOWMAXIMIZED, SW_SHOW, SW_SHOWMINIMIZED.
int width - Width of the window in pixels
int height - Height of the window in pixels
bool windowed - False if the window is fullscreen and true if the window is windowed
bool InitializeWindow(HINSTANCE hInstance,
int ShowWnd,
int width, int height,
bool windowed)
{
我们创建一个名为wc的扩展样式的Windows类,然后填写所有属性。该WNDCLASSESEX结构如下所示:
typedef struct _WNDCLASS {
UINT cbSize;
UINT style;
WNDPROC lpfnWndProc;
int cbClsExtra;
int cbWndExtra;
HANDLE hInstance;
HICON hIcon;
HCURSOR hCursor;
HBRUSH hbrBackground;
LPCTSTR lpszMenuName;
LPCTSTR lpszClassName;
} WNDCLASS;
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = NULL;
wc.cbWndExtra = NULL;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2);
wc.lpszMenuName = NULL;
wc.lpszClassName = WndClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, "Error registering class",
"Error", MB_OK | MB_ICONERROR);
return false;
}
hwnd = CreateWindowEx(
NULL,
WndClassName,
"Window Title",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
width, height,
NULL,
NULL,
hInstance,
NULL
);
if (!hwnd)
{
MessageBox(NULL, "Error creating window",
"Error", MB_OK | MB_ICONERROR);
return false;
}
BOOL ShowWindow( HWND hWnd, int nCmdShow );
BOOL UpdateWindow( HWND hWnd );
ShowWindow(hwnd, ShowWnd);
UpdateWindow(hwnd);
return true;
}
完成初始化窗口后,我们可以继续执行程序的主要部分,即消息循环。这是使程序继续运行的原因。
int messageloop(){
MSG msg;
ZeroMemory(&msg, sizeof(MSG));
while(true)
{
BOOL PeekMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg
);
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else{
// run game code
}
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
switch( msg ) {</span><span class="kwd">case</span><span class="pln"> WM_KEYDOWN</span><span class="pun">:</span><span class="pln"> </span><span class="kwd">if</span><span class="pun">(</span><span class="pln"> wParam </span><span class="pun">==</span><span class="pln"> VK_ESCAPE </span><span class="pun">){</span><span class="pln"> </span><span class="kwd">if</span><span class="pun">(</span><span class="typ">MessageBox</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Are you sure you want to exit?"</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Really?"</span><span class="pun">,</span><span class="pln"> MB_YESNO </span><span class="pun">|</span><span class="pln"> MB_ICONQUESTION</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> IDYES</span><span class="pun">)</span><span class="pln"> </span><span class="typ">DestroyWindow</span><span class="pun">(</span><span class="pln">hwnd</span><span class="pun">);</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln"> </span><span class="kwd">case</span><span class="pln"> WM_DESTROY</span><span class="pun">:</span><span class="pln"> </span><span class="typ">PostQuitMessage</span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span><span class="pln"> </span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
}
最后,我们调用DefWindowProc函数。这是默认的Windows过程功能。最后,我们称其为照顾我们收到的所有消息,但不照顾自己。
return DefWindowProc(hwnd,
msg,
wParam,
lParam);
}
//Include necessary Headers//
#include <windows.h>
//Define variables/constants//
LPCTSTR WndClassName = “firstwindow”; //Define our window class name
HWND hwnd = NULL; //Sets our windows handle to NULL
const int Width = 800; //window width
const int Height = 600; //window height
//Functions//
bool InitializeWindow(HINSTANCE hInstance, //Initialize our window
int ShowWnd,
int width, int height,
bool windowed);
int messageloop(); //Main part of the program
LRESULT CALLBACK WndProc(HWND hWnd, //Windows callback procedure
UINT msg,
WPARAM wParam,
LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, //Main windows function
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
//Initialize Window//
if(!InitializeWindow(hInstance, nShowCmd, Width, Height, true))
{
//If initialization failed, display an error message
MessageBox(0, “Window Initialization - Failed”,
“Error”, MB_OK);
return 0;
}
messageloop</span><span class="pun">();</span><span class="pln"> </span><span class="com">//Jump into the heart of our program</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
}
bool InitializeWindow(HINSTANCE hInstance, //Initialize our window
int ShowWnd,
int width, int height,
bool windowed)
{
//Start creating the window//
WNDCLASSEX wc</span><span class="pun">;</span><span class="pln"> </span><span class="com">//Create a new extended windows class</span><span class="pln">
wc</span><span class="pun">.</span><span class="pln">cbSize </span><span class="pun">=</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">WNDCLASSEX</span><span class="pun">);</span><span class="pln"> </span><span class="com">//Size of our windows class</span><span class="pln">
wc</span><span class="pun">.</span><span class="pln">style </span><span class="pun">=</span><span class="pln"> CS_HREDRAW </span><span class="pun">|</span><span class="pln"> CS_VREDRAW</span><span class="pun">;</span><span class="pln"> </span><span class="com">//class styles</span><span class="pln">
wc</span><span class="pun">.</span><span class="pln">lpfnWndProc </span><span class="pun">=</span><span class="pln"> </span><span class="typ">WndProc</span><span class="pun">;</span><span class="pln"> </span><span class="com">//Default windows procedure function</span><span class="pln">
wc</span><span class="pun">.</span><span class="pln">cbClsExtra </span><span class="pun">=</span><span class="pln"> NULL</span><span class="pun">;</span><span class="pln"> </span><span class="com">//Extra bytes after our wc structure</span><span class="pln">
wc</span><span class="pun">.</span><span class="pln">cbWndExtra </span><span class="pun">=</span><span class="pln"> NULL</span><span class="pun">;</span><span class="pln"> </span><span class="com">//Extra bytes after our windows instance</span><span class="pln">
wc</span><span class="pun">.</span><span class="pln">hInstance </span><span class="pun">=</span><span class="pln"> hInstance</span><span class="pun">;</span><span class="pln"> </span><span class="com">//Instance to current application</span><span class="pln">
wc</span><span class="pun">.</span><span class="pln">hIcon </span><span class="pun">=</span><span class="pln"> </span><span class="typ">LoadIcon</span><span class="pun">(</span><span class="pln">NULL</span><span class="pun">,</span><span class="pln"> IDI_WINLOGO</span><span class="pun">);</span><span class="pln"> </span><span class="com">//Title bar Icon</span><span class="pln">
wc</span><span class="pun">.</span><span class="pln">hCursor </span><span class="pun">=</span><span class="pln"> </span><span class="typ">LoadCursor</span><span class="pun">(</span><span class="pln">NULL</span><span class="pun">,</span><span class="pln"> IDC_ARROW</span><span class="pun">);</span><span class="pln"> </span><span class="com">//Default mouse Icon</span><span class="pln">
wc</span><span class="pun">.</span><span class="pln">hbrBackground </span><span class="pun">=</span><span class="pln"> </span><span class="pun">(</span><span class="pln">HBRUSH</span><span class="pun">)(</span><span class="pln">COLOR_WINDOW </span><span class="pun">+</span><span class="pln"> </span><span class="lit">2</span><span class="pun">);</span><span class="pln"> </span><span class="com">//Window bg color</span><span class="pln">
wc</span><span class="pun">.</span><span class="pln">lpszMenuName </span><span class="pun">=</span><span class="pln"> NULL</span><span class="pun">;</span><span class="pln"> </span><span class="com">//Name of the menu attached to our window</span><span class="pln">
wc</span><span class="pun">.</span><span class="pln">lpszClassName </span><span class="pun">=</span><span class="pln"> </span><span class="typ">WndClassName</span><span class="pun">;</span><span class="pln"> </span><span class="com">//Name of our windows class</span><span class="pln">
wc</span><span class="pun">.</span><span class="pln">hIconSm </span><span class="pun">=</span><span class="pln"> </span><span class="typ">LoadIcon</span><span class="pun">(</span><span class="pln">NULL</span><span class="pun">,</span><span class="pln"> IDI_WINLOGO</span><span class="pun">);</span><span class="pln"> </span><span class="com">//Icon in your taskbar</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="typ">RegisterClassEx</span><span class="pun">(&</span><span class="pln">wc</span><span class="pun">))</span><span class="pln"> </span><span class="com">//Register our windows class</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="com">//if registration failed, display error</span><span class="pln">
</span><span class="typ">MessageBox</span><span class="pun">(</span><span class="pln">NULL</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Error registering class"</span><span class="pun">,</span><span class="pln">
</span><span class="str">"Error"</span><span class="pun">,</span><span class="pln"> MB_OK </span><span class="pun">|</span><span class="pln"> MB_ICONERROR</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
hwnd </span><span class="pun">=</span><span class="pln"> </span><span class="typ">CreateWindowEx</span><span class="pun">(</span><span class="pln"> </span><span class="com">//Create our Extended Window</span><span class="pln">
NULL</span><span class="pun">,</span><span class="pln"> </span><span class="com">//Extended style</span><span class="pln">
</span><span class="typ">WndClassName</span><span class="pun">,</span><span class="pln"> </span><span class="com">//Name of our windows class</span><span class="pln">
</span><span class="str">"Window Title"</span><span class="pun">,</span><span class="pln"> </span><span class="com">//Name in the title bar of our window</span><span class="pln">
WS_OVERLAPPEDWINDOW</span><span class="pun">,</span><span class="pln"> </span><span class="com">//style of our window</span><span class="pln">
CW_USEDEFAULT</span><span class="pun">,</span><span class="pln"> CW_USEDEFAULT</span><span class="pun">,</span><span class="pln"> </span><span class="com">//Top left corner of window</span><span class="pln">
width</span><span class="pun">,</span><span class="pln"> </span><span class="com">//Width of our window</span><span class="pln">
height</span><span class="pun">,</span><span class="pln"> </span><span class="com">//Height of our window</span><span class="pln">
NULL</span><span class="pun">,</span><span class="pln"> </span><span class="com">//Handle to parent window</span><span class="pln">
NULL</span><span class="pun">,</span><span class="pln"> </span><span class="com">//Handle to a Menu</span><span class="pln">
hInstance</span><span class="pun">,</span><span class="pln"> </span><span class="com">//Specifies instance of current program</span><span class="pln">
NULL </span><span class="com">//used for an MDI client window</span><span class="pln">
</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(!</span><span class="pln">hwnd</span><span class="pun">)</span><span class="pln"> </span><span class="com">//Make sure our window has been created</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="com">//If not, display error</span><span class="pln">
</span><span class="typ">MessageBox</span><span class="pun">(</span><span class="pln">NULL</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Error creating window"</span><span class="pun">,</span><span class="pln">
</span><span class="str">"Error"</span><span class="pun">,</span><span class="pln"> MB_OK </span><span class="pun">|</span><span class="pln"> MB_ICONERROR</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">false</span><span class="pun">;</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="typ">ShowWindow</span><span class="pun">(</span><span class="pln">hwnd</span><span class="pun">,</span><span class="pln"> </span><span class="typ">ShowWnd</span><span class="pun">);</span><span class="pln"> </span><span class="com">//Shows our window</span><span class="pln">
</span><span class="typ">UpdateWindow</span><span class="pun">(</span><span class="pln">hwnd</span><span class="pun">);</span><span class="pln"> </span><span class="com">//Its good to update our window</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="kwd">true</span><span class="pun">;</span><span class="pln"> </span><span class="com">//if there were no errors, return true</span><span class="pln">
}
int messageloop(){ //The message loop
MSG msg</span><span class="pun">;</span><span class="pln"> </span><span class="com">//Create a new message structure</span><span class="pln">
</span><span class="typ">ZeroMemory</span><span class="pun">(&</span><span class="pln">msg</span><span class="pun">,</span><span class="pln"> </span><span class="kwd">sizeof</span><span class="pun">(</span><span class="pln">MSG</span><span class="pun">));</span><span class="pln"> </span><span class="com">//clear message structure to NULL</span><span class="pln">
</span><span class="kwd">while</span><span class="pun">(</span><span class="kwd">true</span><span class="pun">)</span><span class="pln"> </span><span class="com">//while there is a message</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="com">//if there was a windows message</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="typ">PeekMessage</span><span class="pun">(&</span><span class="pln">msg</span><span class="pun">,</span><span class="pln"> NULL</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="lit">0</span><span class="pun">,</span><span class="pln"> PM_REMOVE</span><span class="pun">))</span><span class="pln">
</span><span class="pun">{</span><span class="pln">
</span><span class="kwd">if</span><span class="pln"> </span><span class="pun">(</span><span class="pln">msg</span><span class="pun">.</span><span class="pln">message </span><span class="pun">==</span><span class="pln"> WM_QUIT</span><span class="pun">)</span><span class="pln"> </span><span class="com">//if the message was WM_QUIT</span><span class="pln">
</span><span class="kwd">break</span><span class="pun">;</span><span class="pln"> </span><span class="com">//Exit the message loop</span><span class="pln">
</span><span class="typ">TranslateMessage</span><span class="pun">(&</span><span class="pln">msg</span><span class="pun">);</span><span class="pln"> </span><span class="com">//Translate the message</span><span class="pln">
</span><span class="com">//Send the message to default windows procedure</span><span class="pln">
</span><span class="typ">DispatchMessage</span><span class="pun">(&</span><span class="pln">msg</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">else</span><span class="pun">{</span><span class="pln"> </span><span class="com">//Otherewise, keep the flow going</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="pun">(</span><span class="kwd">int</span><span class="pun">)</span><span class="pln">msg</span><span class="pun">.</span><span class="pln">wParam</span><span class="pun">;</span><span class="pln"> </span><span class="com">//return the message</span><span class="pln">
}
LRESULT CALLBACK WndProc(HWND hwnd, //Default windows procedure
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
switch( msg ) //Check message
{
</span><span class="kwd">case</span><span class="pln"> WM_KEYDOWN</span><span class="pun">:</span><span class="pln"> </span><span class="com">//For a key down</span><span class="pln">
</span><span class="com">//if escape key was pressed, display popup box</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(</span><span class="pln"> wParam </span><span class="pun">==</span><span class="pln"> VK_ESCAPE </span><span class="pun">){</span><span class="pln">
</span><span class="kwd">if</span><span class="pun">(</span><span class="typ">MessageBox</span><span class="pun">(</span><span class="lit">0</span><span class="pun">,</span><span class="pln"> </span><span class="str">"Are you sure you want to exit?"</span><span class="pun">,</span><span class="pln">
</span><span class="str">"Really?"</span><span class="pun">,</span><span class="pln"> MB_YESNO </span><span class="pun">|</span><span class="pln"> MB_ICONQUESTION</span><span class="pun">)</span><span class="pln"> </span><span class="pun">==</span><span class="pln"> IDYES</span><span class="pun">)</span><span class="pln">
</span><span class="com">//Release the windows allocated memory </span><span class="pln">
</span><span class="typ">DestroyWindow</span><span class="pun">(</span><span class="pln">hwnd</span><span class="pun">);</span><span class="pln">
</span><span class="pun">}</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
</span><span class="kwd">case</span><span class="pln"> WM_DESTROY</span><span class="pun">:</span><span class="pln"> </span><span class="com">//if x button in top right was pressed</span><span class="pln">
</span><span class="typ">PostQuitMessage</span><span class="pun">(</span><span class="lit">0</span><span class="pun">);</span><span class="pln">
</span><span class="kwd">return</span><span class="pln"> </span><span class="lit">0</span><span class="pun">;</span><span class="pln">
}
//return the message for windows to handle it
return DefWindowProc(hwnd,
msg,
wParam,
lParam);
}
我几乎忘了,如果您遇到这样的错误;
错误C2664:“ MessageBoxW”:无法将参数2从“ const char [6]”转换为“ LPCWSTR”
然后在顶部转到项目,设置属性…(或仅按ALT + F7),然后在左侧展开配置属性,然后单击“常规”。在右侧的底部显示字符集,将其从Unicode更改为Multi-Byte。
我忘记提及的另一件事是,如果您想使用国际字符(例如中文),请不要将字符集更改为多字节。保持原样,并在代码中的每个字符串之前加上大写字母“ L”。
一个例子是:
“你确定要离开?” —> L“确定要退出吗?”
您将必须记住始终在每个字符串前放置一个“ L”。另外,您可能必须将PeekMessage更改为PeekMessageL

浙公网安备 33010602011771号