c++ - Win32 : Why is full-screen mode buggy?

标签 c++ winapi

目前,我正在尝试制作一个简单的 Win32 应用程序,它可以在全屏和窗口模式之间来回切换。我正在使用 the Chromium way of doing this作为引用。我创建了一个类来处理窗口,使事情变得更简单。

我希望通过在按下 F4 键时切换全屏来实现这一点。不幸的是,样式似乎应用正确,但窗口没有调整大小或移动到正确的区域。它还会在返回到原始位置之前捕捉到屏幕的左上角片刻。出于某种原因,当我切换全屏时,窗口的输入会传递到它下面的那个。然后我必须去任务管理器杀死程序,因为我无法关闭窗口或应用程序。

我已经尝试在创建时将 HWND 的样式存储在一个类变量中(它以窗口模式开始)并使用该值为全屏窗口创建必要的样式并恢复窗口模式窗口。我也尝试立即使用 GetWindowLongPtr 获取窗口样式当ToggleFullscreen函数被调用。这两个都不起作用。

这是我的代码:

窗口处理程序

#include <Windows.h> // Win32 API

#ifndef WINDOWHANDLER
#define WINDOWHANDLER

class WindowHandler // WindowHandler
{
     public:
          WindowHandler(); // Constructor

          void Destroy() { DestroyWindow(hwnd); } // Destroy the handler

          void ToggleFullscreen(); // Toggle fullscreen

     protected:
          static LRESULT CALLBACK WindowProc // Window procedure
          (
               HWND hwnd,
               UINT message,
               WPARAM wParam,
               LPARAM lParam
          );

          HWND hwnd; // The window

          // Everything involved in fullscreen
          bool fullscreen = false; // Whether the window is fullscreen or not

          RECT windowRect = {}; // The restored window size

          long int windowStyles = 0; // The restored window styles
          long int extendedWindowStyles = 0; // The restored window extended styles
};

#endif

窗口处理程序

#include "WindowHandler.h" // Header file

WindowHandler::WindowHandler() // Constructor
{
     WNDCLASS wndClass = {}; // The window information
     wndClass.lpfnWndProc = WindowProc;
     wndClass.hInstance = GetModuleHandle(nullptr);
     wndClass.lpszClassName = L"FullscreenTest";

     RegisterClass(&wndClass); // Register the window

     hwnd = CreateWindowEx // Create the window and store a pointer to the handler for the procedure to use
     (
          0,
          L"FullscreenTest",
          L"Stack Overflow Repro",
          WS_OVERLAPPEDWINDOW,
          CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
          nullptr,
          nullptr,
          GetModuleHandle(nullptr),
          this
     );

     if (hwnd == nullptr) Destroy(); // Destroy the handler if the window is invalid
     else // Otherwise...
     {
          GetWindowRect(hwnd, &windowRect); // Store the window size

          windowStyles = GetWindowLongPtr(hwnd, GWL_STYLE); // Store the window styles
          extendedWindowStyles = GetWindowLongPtr(hwnd, GWL_EXSTYLE); // Store the extended window styles

          ShowWindow(hwnd, SW_SHOW); // Show the window
     }
}

void WindowHandler::ToggleFullscreen() // Toggle fullscreen
{
     if (!fullscreen) // If fullscreen is not enabled
     {
          MONITORINFO monitorInfo; // Get the monitor info
          monitorInfo.cbSize = sizeof(monitorInfo);
          GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST), &monitorInfo);

          SetWindowLongPtr(hwnd, GWL_STYLE, windowStyles & ~(WS_CAPTION | WS_THICKFRAME)); // Set the window styles
          SetWindowLongPtr // Set the extended window styles
          (
               hwnd,
               GWL_EXSTYLE,
               extendedWindowStyles & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE)
          );

          SetWindowPos // Resize, move, and refresh the window
          (
               hwnd,
               nullptr,
               monitorInfo.rcMonitor.left,
               monitorInfo.rcMonitor.top,
               monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left,
               monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top,
               SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED
          );

          fullscreen = true; // Indicate that fullscreen is on
     }
     else // Otherwise...
     {
          SetWindowLongPtr(hwnd, GWL_STYLE, windowStyles); // Set the window styles
          SetWindowLongPtr(hwnd, GWL_EXSTYLE, extendedWindowStyles); // Set the extended window styles

          SetWindowPos // Resize, move, and refresh the window
          (
               hwnd,
               nullptr,
               windowRect.left,
               windowRect.top,
               windowRect.right - windowRect.left,
               windowRect.bottom - windowRect.top,
               SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED
          );

          fullscreen = false; // Indicate that fullscreen is off
     }
}

LRESULT CALLBACK WindowHandler::WindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) // Window procedure
{
     WindowHandler* handlerPtr; // Pointer to the window handler

     if (message == WM_CREATE) // If the window is being created...
     {
          CREATESTRUCT* createStruct = reinterpret_cast<CREATESTRUCT*>(lParam); // Get the pointer's container
          handlerPtr = reinterpret_cast<WindowHandler*>(createStruct->lpCreateParams); // Get the pointer
          SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)handlerPtr); // Store the pointer
     }
     else handlerPtr = reinterpret_cast<WindowHandler*>(GetWindowLongPtr(hwnd, GWLP_USERDATA)); // Otherwise, get the pointer

     if (handlerPtr) { // If the pointer is valid...
          switch (message)
          {
               case WM_PAINT: // Paint the window
                    {
                         PAINTSTRUCT paintStruct;
                         HDC hdc = BeginPaint(hwnd, &paintStruct);
                         FillRect(hdc, &paintStruct.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
                         EndPaint(hwnd, &paintStruct);
                    }
                    return 0;
               case WM_DESTROY: // Destroy the window
                    PostQuitMessage(0);
                    return 0;
               case WM_KEYDOWN: // Process input
                    switch ((int)wParam)
                    {
                         case VK_ESCAPE: // Quit if the escape key is pressed
                              handlerPtr->Destroy();
                              break;
                         case VK_F4: // Toggle fullscreen if F4 is pressed
                              handlerPtr->ToggleFullscreen();
                              break;
                    }
                    return 0;
               default: // Do the default action if the message was not processed
                    return DefWindowProc(hwnd, message, wParam, lParam);
          }
     }
     else return DefWindowProc(hwnd, message, wParam, lParam); // Do the default action if the pointer is not valid
}

主程序

#include "WindowHandler.h" // Window handler

int WINAPI wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) // Win32 main function
{
     WindowHandler repro; // Create a window handler

     MSG msg = {}; // Message structure
     while (GetMessage(&msg, nullptr, 0, 0)) // Message loop
     {
          TranslateMessage(&msg);
          DispatchMessage(&msg);
     }

     return 0;
}

最佳答案

代替:

          windowStyles = GetWindowLongPtr(hwnd, GWL_STYLE);
          extendedWindowStyles = GetWindowLongPtr(hwnd, GWL_EXSTYLE);

          ShowWindow(hwnd, SW_SHOW); // Show the window


和:
          ShowWindow(hwnd, SW_SHOW); // Show the window

          windowStyles = GetWindowLongPtr(hwnd, GWL_STYLE);
          extendedWindowStyles = GetWindowLongPtr(hwnd, GWL_EXSTYLE);


WS_VISIBLE 样式位直到第一个 ShowWindow(SW_SHOW) 之后才会设置.

关于c++ - Win32 : Why is full-screen mode buggy?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61512998/

相关文章:

c++ - const 对和 const 对之间的区别

c++ - main() Qt 项目中动态分配的对象

windows - 无边框窗口。如何添加阴影和删除 1px 边框?

c - WINAPI 代表什么

c++ - 如何在 C++ winapi 中获取加载图标的大小

c++ - 使用 win32 或其他库导入 .reg 文件

C++在虚方法中访问公共(public)变量

c++ - 无法找出 C++ 中 Caesar Cipher 的问题

c++ - 我的客户端服务器代码无法正常工作

c++ - 如何在C++/Win32中使用IVirtualDesktopManager接口(interface)