[X]
Alt+F4
)时,该应用程序并未完全终止 - 它保留在任务管理器的进程列表中。
当我从
WndProc
DefWindowProc()
时,问题仍然存在。该程序在后台徘徊,我必须手动从任务管理器中杀死它。
电流代码
#include <Windows.h>
#include <stdio.h>
#include <gl/GL.h>
#include <iostream>
const char *GREEN = "\x1b[38;2;45;200;120m";
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void GeneratePixelFormat(HDC &dc);
void SettingUpConsole();
void SetupRC(HDC hDC, GLuint nFontList);
void RenderScene(GLuint nFontList);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdArg, int nCmd)
{
// SettingUpConsole();
WNDCLASS wc = {0};
wc.hInstance = hInstance;
wc.lpszClassName = "Window Class";
// ? CS_OWNDC is required in OpenGL because some old drivers are not very stable without this (check page 656 to 660 in OpenGL SuperBbile)
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(248, 248, 255));
wc.cbWndExtra = 0;
wc.cbClsExtra = 0;
if (!RegisterClass(&wc))
return 0;
HWND WindowHandle = CreateWindowExA(
0, wc.lpszClassName, "Custom Window",
// ! When making window for OpenGL it is required to set clipchildren and siblings
// ? If not used then opengl may draw onto sibling or children window also
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, 1000, 460,
NULL, NULL, 0, NULL);
if (!WindowHandle)
{
return 0;
}
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
// printf("Running message loop.\n");
}
printf("\x1b[38;2;120mExiting Loop.");
return 0;
}
LRESULT CALLBACK WndProc(HWND WindowHandle, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HDC dc = NULL;
static HGLRC rc = NULL;
static GLuint nFontList;
switch (uMsg)
{
case WM_CREATE:
{
printf("%sGetting window's handle\n", GREEN);
dc = GetDC(WindowHandle);
printf("%sSetting pixel format\n", GREEN);
GeneratePixelFormat(dc);
printf("%sCreating rendering context...\n", GREEN);
rc = wglCreateContext(dc);
printf("%sSetting current context.\n", GREEN);
wglMakeCurrent(dc, rc);
printf("%sSending message 30 times per second (30fps)\n", GREEN);
SetTimer(WindowHandle, 101, 33, NULL);
SetupRC(dc, nFontList);
printf("\x1b[38;2;150;150;150m\n");
return 0;
}
case WM_TIMER:
{
InvalidateRect(WindowHandle, NULL, FALSE);
printf("MESSAGE SENT\n");
return 0;
}
case WM_CLOSE:
{
printf("WM_CLOSE received. Destroying window...\n");
ReleaseDC(WindowHandle, dc);
wglMakeCurrent(dc, NULL);
wglDeleteContext(rc);
DestroyWindow(WindowHandle);
return 0;
}
case WM_DESTROY:
{
printf("WM_DESTROY received. Posting quit message...\n");
PostQuitMessage(0);
KillTimer(WindowHandle, 101);
// ! Do not remove ExitProcess T_T U_U
// ? Don't know why but closing the window don't close the process in the task manager
// ? Therefore using ExitProcess(0) to force process to stop when wm_destory message received.
// ExitProcess(0);
return 0;
}
case WM_SIZE:
{
RenderScene(nFontList);
SwapBuffers(dc);
ValidateRect(WindowHandle, NULL);
return 0;
}
case WM_PAINT:
{
RenderScene(nFontList);
SwapBuffers(dc); // Ensure the rendered scene is displayed
ValidateRect(WindowHandle, NULL);
return 0;
}
default:
return DefWindowProc(WindowHandle, uMsg, wParam, lParam);
}
}
void SettingUpConsole()
{
AllocConsole();
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
// Set console to ASCII mode
SetConsoleOutputCP(CP_ACP);
// Enable virtual terminal processing
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD consoleMode;
GetConsoleMode(hConsole, &consoleMode);
consoleMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(hConsole, consoleMode);
}
void GeneratePixelFormat(HDC &dc)
{
static PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), // Size of this structure
1, // Version of this structure
PFD_DRAW_TO_WINDOW | // Draw to window (not to bitmap)
PFD_SUPPORT_OPENGL | // Support OpenGL calls in window
PFD_DOUBLEBUFFER, // Double buffered mode
PFD_TYPE_RGBA, // RGBA color mode
32, // Want 32-bit color
0, 0, 0, 0, 0, 0, // Not used to select mode
0, 0, // Not used to select mode
0, 0, 0, 0, 0, // Not used to select mode
16, // Size of depth buffer
0, // No stencil
0, // No auxiliary buffers
0, // Obsolete or reserved
0, // No overlay and underlay planes
0, // Obsolete or reserved layer mask
0, // No transparent color for underlay plane
0}; // Obsolete
int nPixelFormat = ChoosePixelFormat(dc, &pfd);
SetPixelFormat(dc, nPixelFormat, &pfd);
}
void SetupRC(HDC hDC, GLuint nFontList)
{
// Set up the font characteristics
HFONT hFont;
GLYPHMETRICSFLOAT agmf[128]; // Throw away
LOGFONT logfont;
logfont.lfHeight = -10;
logfont.lfWidth = 0;
logfont.lfEscapement = 0;
logfont.lfOrientation = 0;
logfont.lfWeight = FW_BOLD;
logfont.lfItalic = FALSE;
logfont.lfUnderline = FALSE;
logfont.lfStrikeOut = FALSE;
logfont.lfCharSet = ANSI_CHARSET;
logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
logfont.lfQuality = DEFAULT_QUALITY;
logfont.lfPitchAndFamily = DEFAULT_PITCH;
strcpy(logfont.lfFaceName, "Arial");
// Create the font and display list
hFont = CreateFontIndirect(&logfont);
SelectObject(hDC, hFont);
// Create display lists for glyphs 0 through 128 with 0.1 extrusion
// and default deviation. The display list numbering starts at 1000
// (it could be any number).
nFontList = glGenLists(128);
wglUseFontOutlines(hDC, 0, 128, nFontList, 0.0f, 0.5f,
WGL_FONT_POLYGONS, agmf);
DeleteObject(hFont);
}
void RenderScene(GLuint nFontList)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Blue 3D text
glColor3ub(0, 0, 255);
glPushMatrix();
glListBase(nFontList);
glCallLists(6, GL_UNSIGNED_BYTE, "SDFSDF");
glPopMatrix();
}
# My Folders
include_folder = ./include
lib_folder = ./lib
# Libraries to include
my_libraries = User32.lib Gdi32.lib ucrt.lib kernel32.lib vcruntime.lib msvcrt.lib opengl32.lib
# INFO(Include Folders)
# Windows Kit Include Folders
kit_include_1 = "C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/winrt"
kit_include_2 = "C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/ucrt"
kit_include_3 = "C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/um"
kit_include_4 = "C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/shared"
kit_include_5 = "C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/cppwinrt"
# Windows Kit Lib Folders
kit_lib_1 = "C:/Program Files (x86)/Windows Kits/10/Lib/10.0.22621.0/um/x64"
kit_lib_2 = "C:/Program Files (x86)/Windows Kits/10/Lib/10.0.22621.0/ucrt/x64"
# MSVC Include Folders
msvc_include = "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.41.34120/include"
msvc_atlmfc_include = "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.41.34120/atlmfc/include"
# MSVC Lib Folders
msvc_lib = "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.41.34120/lib/x64"
msvc_atlmfc_lib = "C:/Program Files/Microsoft Visual Studio/2022/Community/VC/Tools/MSVC/14.41.34120/atlmfc/lib/x64"
# INFO(Combined Include Folders)
include_folders = /I$(msvc_include) /I$(msvc_atlmfc_include) /I$(kit_include_1) /I$(kit_include_2) /I$(kit_include_3) /I$(kit_include_4) /I$(kit_include_5) /I$(include_folder) /I"C:/Program Files (x86)/Windows Kits/10/Include/10.0.22621.0/shared"
#INFO(Combined Lib Folders)
lib_folders = /LIBPATH:$(msvc_lib) /LIBPATH:$(msvc_atlmfc_lib) /LIBPATH:$(kit_lib_1) /LIBPATH:$(kit_lib_2) /LIBPATH:$(lib_folder) $(my_libraries)
# When using windows kit 10.0.19041.0 i.e. Win32
build:
cl main.cpp ${include_folders} /EHsc /link ${lib_folders} /OUT:./bin/program.exe /SUBSYSTEM:WINDOWS /NODEFAULTLIB /ENTRY:WinMain
del *.obj
# ? Testing if I can use my custom made Logger.dll if I use g++ rather than msvc, because I was not able to use Logger.dll with msvc
# building with g++ without -mwindows flag
# -mwindows flag is used to hide the console window
# mark the entry point as WinMain
buildGPP:
g++ main.cpp -o ./bin/program.exe -I$(include_folder) -L$(lib_folder) -L./bin -lUser32 -lGdi32 -lucrt -lkernel32 -lLogger
问题
我目前使用KillProcess功能手动杀死该过程。我应该保留还是会造成任何问题? (尽管我没有看到任何人使用它。)
DefWindowProc()
WM_CLOSE
DestroyWindow()
WM_DESTROY
调用PostQuitMessage(0)
检查了消息循环在退出后通过打印日志消息而退出(
printf("Exiting main loop."))
确实打印,含义循环终止,但该过程却没有。aadditional注释
我应该遵循任何调试步骤,以追踪为什么该过程持续存在?
您的消息循环:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GetMessage
WM_QUIT
WM_QUIT
IF
while (GetMessage(&msg, NULL, 0, 0) > 0) // Ensure GetMessage doesn't return -1 (error)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
printf("Main loop exited. Process should terminate.\n");
。被打印了,但该过程仍然存在,其他事情使它保持活力。