C++ 如何正确关闭/终止简单的Windows应用程序
拥有如此简单的DirectX应用程序:C++ 如何正确关闭/终止简单的Windows应用程序,c++,winapi,visual-c++,C++,Winapi,Visual C++,拥有如此简单的DirectX应用程序: #include <d3dx9.h> #include <tchar.h> #include <chrono> #include "Utils.h" //#pragma comment (lib, "d3d9.lib") //#pragma comment (lib, "d3dx9.lib") using namespace std::chrono_lite
#include <d3dx9.h>
#include <tchar.h>
#include <chrono>
#include "Utils.h"
//#pragma comment (lib, "d3d9.lib")
//#pragma comment (lib, "d3dx9.lib")
using namespace std::chrono_literals;
using namespace std::chrono;
const wchar_t g_szClassName[] = _T("myWindowClass");
// we use a fixed timestep of 1 / (60 fps) = 16 milliseconds
//constexpr std::chrono::nanoseconds timestep(16ms);
constexpr std::chrono::nanoseconds timestep(1000ms);
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
wchar_t msgbuf[100];
int loop_cnt = 0;
bool handle_events() {
// poll for events
return false; // true if the user wants to quit the game
}
void update(long long lag) {
// update game logic here
swprintf_s(msgbuf, _T("update - loop_cnt: %d\n"), loop_cnt++);
OutputDebugString(msgbuf);
}
void render() {
// render stuff here
}
VOID OnPaint(HDC hdc) {
}
// ------------ D3D ------------
IDirect3D9* pD3D;
IDirect3DDevice9* pDev;
IDirect3DVertexBuffer9* pVB;
const DWORD OURVERT_FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;
struct OurVertex {
float x, y, z; // pozycja
float rhw; // komponent rhw
D3DCOLOR color; // kolor
};
// -----------------------------
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow) {
using clock = std::chrono::high_resolution_clock;
WNDCLASSEX wc;
HWND hWnd;
MSG Msg = {0};
std::chrono::nanoseconds lag(0ns);
auto start_time = clock::now();
bool quit_game = false;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc)) {
MessageBox(NULL, _T("Window Registration Failed!"), _T("Error!"), MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hWnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
_T("The title of my window"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
480, // initial x size
640, // initial y size
NULL,
NULL,
hInstance,
NULL
);
OutputDebugString(_T("--> WinMain <-- \n"));
if (hWnd == NULL) {
MessageBox(NULL, _T("Window Creation Failed!"), _T("Error!"), MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// ------------ D3D ------------
pD3D = Direct3DCreate9(D3D_SDK_VERSION);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.Windowed = true;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
OurVertex verts[] = {
{ 20.0f, 20.0f, 0.5f, 1.0f, 0xffff0000, },
{ 100.0f, 20.0f, 0.5f, 1.0f, 0xff00ff00, },
{ 20.0f, 100.0f, 0.5f, 1.0f, 0xff00ff55, },
{ 100.0f, 100.0f, 0.5f, 1.0f, 0xff0000ff},
};
pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &pDev);
HRESULT hr = pDev->CreateVertexBuffer(4*sizeof(OurVertex), D3DUSAGE_DYNAMIC, OURVERT_FVF, D3DPOOL_DEFAULT, &pVB, 0);
check_HRESULT(_T("CreateVertexBuffer"), hr);
void* data;
pVB->Lock(0, 4*sizeof(OurVertex), &data, D3DLOCK_DISCARD);
memcpy(data, (void*)verts, sizeof(verts));
pVB->Unlock();
// -----------------------------
// Step 3: The Message Loop
while (TRUE) {
while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE) > 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
if (Msg.message == WM_QUIT)
break;
// Run game logic
auto current_time = clock::now();
auto frame_time = current_time - start_time;
start_time = current_time;
lag += duration_cast<nanoseconds>(frame_time);
// update game logic as lag permits
while (lag >= timestep) {
lag -= timestep;
pDev->Clear(0, 0, D3DCLEAR_TARGET, 0xff000000, 1, 0);
pDev->BeginScene();
pDev->SetFVF(OURVERT_FVF);
pDev->SetStreamSource(0, pVB, 0, sizeof(OurVertex));
pDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
pDev->EndScene();
pDev->Present(0, 0, 0, 0);
update(lag.count()); // update at a fixed rate each time
}
}
OutputDebugString(_T("--> AFTER MSG LOOP END <-- \n"));
return Msg.wParam;
}
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
代码可能有什么问题
另外,我正在Windows 10上使用Microsoft Visual Studio Community 2019。消息循环可能永远不会终止
while(peek消息(&Msg,NULL,0,0,PM_REMOVE)>0){
翻译信息(&Msg);
发送消息(&Msg);
}
如果(Msg.message==WM\u退出)
打破
您正在处理所有消息,但只检查最后一条消息是否为WM\u QUIT
消息。相反,您需要检查所有消息并正确退出循环,如下所示:
bool运行{true};
(跑步时){
while(运行&&peek消息(&Msg,NULL,0,0,PM_REMOVE)>0){
翻译信息(&Msg);
发送消息(&Msg);
running=Msg.message!=WM\u QUIT;
}
//不严格要求;您可以运行另一个渲染循环并
//运行时最外层的循环退出为false
如果(!正在运行)
打破
链接错误只是表示进程仍在运行。映射到进程中的可执行映像无法写入。这就是链接器所抱怨的。Thx用于回复。我提供的代码无效。非常相似的代码(与我的问题相同,只检查最后一条消息)出现在Direct X教程网站上…这是否意味着出现的代码也无效?如果是相同的代码,那么它也会因为相同的原因被破坏。缺陷很容易被忽略,因为一切看起来都正常。直到重新编译。我猜这只是编程第一条规则的另一种表现:找到的每一个代码在互联网上是垃圾。是的,你是对的,朋友:-)谢谢你给我指出问题。有一件事仍然让我想知道-怎么可能在发送WM_退出消息后,系统仍在发送其他额外消息?因此唯一的后续消息也需要是低优先级的。是这样的候选消息,还是计时器消息s、 正如所解释的,“当线程从其消息队列中检索
WM_QUIT
消息时,它应该退出其消息循环”。这个答案中的代码只是遵循契约。
--> WinMain <--
update - loop_cnt: 0
update - loop_cnt: 1
update - loop_cnt: 2
update - loop_cnt: 3
update - loop_cnt: 4
update - loop_cnt: 5
...
LINK : fatal error LNK1168: cannot open ...Game_Loop_Windows_1.exe for writing
...
MSB6006: "link.exe" exited with code 1168.
1>Done building project "Game_Loop_Windows_1.vcxproj" -- FAILED