Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Win32: Why is full-screen mode buggy?

Tags:

c++

winapi

Currently, I'm trying to make a simple Win32 application that switches back and forth between fullscreen and windowed mode. I'm using the Chromium way of doing this as a reference. I created a class to handle windows to make things simpler.

I expected this to work by toggling fullscreen when the F4 key was pressed. Unfortunately, the styles appear to be applied correctly, but the window doesn't resize or move to the correct area. It also snaps to the top left corner of the screen for a moment before it returns to its original position. For some reason, input for the window passes to the one below it when I toggle fullscreen. Then I have to go to Task Manager to kill the program because I can't close the window or application.

I've tried storing the styles of the HWND in a class variable at creation (it starts out in windowed mode) and using the value to create the necessary style for the fullscreen window and restoring the windowed mode window. I have also tried immediately getting the window styles with GetWindowLongPtr when the ToggleFullscreen function is called. Both of these do not work.

Here is my code:

WindowHandler.h

#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

WindowHandler.cpp

#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
}

main.cpp

#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;
}
like image 293
Najm Hoda Avatar asked Apr 29 '20 22:04

Najm Hoda


People also ask

What is exclusive fullscreen mode?

Exclusive Fullscreen Mode is a new feature available for the macOS Luna Secondary App 5.1 or newer and allows you to disable multi-tasking gestures and keyboard commands like command+tab, app switching with gestures, and more when using your secondary screen's keyboard and mouse/trackpad.

How do I make my EXE file full screen?

Open the program, maximize the window by clicking the square icon in the upper-right corner. Then, press and hold the Ctrl key and close the program. Re-open the program to see if it opens as maximized.

What is exit full screen?

Using the F11 key on your computer's keyboard will let you both enter and exit full-screen mode in many applications. If you use a laptop, you might need to press Fn + F11 to activate this keyboard shortcut.


1 Answers

Replace:

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

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

With:

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

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

The WS_VISIBLE style bit does not get set until after that first ShowWindow(SW_SHOW).

like image 116
dxiv Avatar answered Oct 02 '22 15:10

dxiv