WIN32:关闭窗口

问题描述 投票:0回答:1

问题

我最近开始使用OpenGL学习Win32编程,并正在尝试创建一个基本窗口并测试提供的各种功能。但是,我注意到,当我关闭窗口(使用关闭按钮
    [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(); }
我的makefile

# 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
问题

AM我在窗口的清理过程或创建过程中缺少某些内容,这些过程导致窗口/过程在任务管理器中未终止流程?
我目前使用KillProcess功能手动杀死该过程。我应该保留还是会造成任何问题? (尽管我没有看到任何人使用它。)

我尝试了什么:
  1. 仅在WNDProc中使用
  2. DefWindowProc()
  3. ,但该过程仍然存在。
注释

WM_CLOSE

调用
    DestroyWindow()
  1. WM_DESTROY
    调用
  2. PostQuitMessage(0)
  3. 检查了消息循环在退出后通过打印日志消息而退出(
    printf("Exiting main loop."))
    确实打印,含义循环终止,但该过程却没有。
    
    aadditional注释
    
    
    我应该遵循任何调试步骤,以追踪为什么该过程持续存在?
    
  4. message循环应正确处理WM_QUIT,
    您的消息循环:
  5. while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }

GetMessage
    收到时返回0,将退出循环。这通常会导致Winmain退出,从而终止该过程。 但是,如果另一个thread
  1. 使过程保持生命,则可能永远不会完全终止。 尝试将消息循环修改为在接收到
  2. WM_QUIT
时登录:
c++ winapi window win32gui
1个回答
0
投票
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");
。被打印了,但该过程仍然存在,其他事情使它保持活力。
    

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.