Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Win32: full-screen and hiding taskbar

I have a window, which I SetWindowPos(window, HWND_TOP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), SWP_FRAMECHANGED);

It covers the whole screen, ok, but it takes a while (0.5 sec) to cover the taskbar as well.

Is there a way to come over the taskbar immediately? I found that setting HWND_TOPMOST does it immediately, but it stays above all the other windows, even if I switch the app - this is something I don't want. Also, if I first hide the window and then show it, it somehow forces the window to redraw and covers the taskbar immediately, but it flickers (because of the hiding). Is there another way?

like image 861
Lars Kanto Avatar asked Mar 04 '10 20:03

Lars Kanto


People also ask

Why won't my taskbar hide when I go fullscreen?

Open Start > Settings and choose Personalization > Taskbar from the menu. Expand the Taskbar behaviors section and check the Automatically hide the taskbar. On Windows 10, open Start > Settings > Personalization > Taskbar and toggle on the Automatically hide the taskbar in desktop mode option.

Why is the taskbar showing in fullscreen?

Disable the Taskbar Lock To disable taskbar lock, right-click on the taskbar and check if Lock the taskbar option is checked. If it's checked, click on it to uncheck the option and turn off the taskbar lock. Once disabled, try to open your browser or media player in fullscreen to see if the taskbar has disappeared.

How do I switch a window between normal and fullscreen?

Press Alt+Enter while you're playing a full-screen game to enable windowed mode. You can press the shortcut again to switch out of windowed mode and re-enable full-screen mode, too.


2 Answers

Yup, HWND_TOPMOST does it for me. Here is a section of code that makes full-screen work well (and quick) for me:

 bool enterFullscreen(HWND hwnd, int fullscreenWidth, int fullscreenHeight, int colourBits, int refreshRate) {     DEVMODE fullscreenSettings;     bool isChangeSuccessful;     RECT windowBoundary;      EnumDisplaySettings(NULL, 0, &fullscreenSettings);     fullscreenSettings.dmPelsWidth        = fullscreenWidth;     fullscreenSettings.dmPelsHeight       = fullscreenHeight;     fullscreenSettings.dmBitsPerPel       = colourBits;     fullscreenSettings.dmDisplayFrequency = refreshRate;     fullscreenSettings.dmFields           = DM_PELSWIDTH |                                             DM_PELSHEIGHT |                                             DM_BITSPERPEL |                                             DM_DISPLAYFREQUENCY;      SetWindowLongPtr(hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_TOPMOST);     SetWindowLongPtr(hwnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);     SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, fullscreenWidth, fullscreenHeight, SWP_SHOWWINDOW);     isChangeSuccessful = ChangeDisplaySettings(&fullscreenSettings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL;     ShowWindow(hwnd, SW_MAXIMIZE);      return isChangeSuccessful; } 

Note that this will change the resolution if you tell it the wrong settings. This is what I usually want, but if you don't like that, you can find out your resolution by using (where mainWindow is returned from something like CreateWindow() or CreateWindowEx()):

 windowHDC = GetDC(mainWindow); fullscreenWidth  = GetDeviceCaps(windowHDC, DESKTOPHORZRES); fullscreenHeight = GetDeviceCaps(windowHDC, DESKTOPVERTRES); colourBits       = GetDeviceCaps(windowHDC, BITSPIXEL); refreshRate      = GetDeviceCaps(windowHDC, VREFRESH); 

When you want to get out of full-screen you do something like this:

 bool exitFullscreen(HWND hwnd, int windowX, int windowY, int windowedWidth, int windowedHeight, int windowedPaddingX, int windowedPaddingY) {     bool isChangeSuccessful;      SetWindowLongPtr(hwnd, GWL_EXSTYLE, WS_EX_LEFT);     SetWindowLongPtr(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);     isChangeSuccessful = ChangeDisplaySettings(NULL, CDS_RESET) == DISP_CHANGE_SUCCESSFUL;     SetWindowPos(hwnd, HWND_NOTOPMOST, windowX, windowY, windowedWidth + windowedPaddingX, windowedHeight + windowedPaddingY, SWP_SHOWWINDOW);     ShowWindow(hwnd, SW_RESTORE);      return isChangeSuccessful; } 

I set my code to change between full-screen and windowed mode using a hotkey, and I keep the windowed mode variables as global, so that when changing to windowed mode, it stays put.

This code also has the advantage of running in the equivalent of "exclusive mode" (I'm using XP, and haven't tried it on the newer versions of windows), which means it'll be much, much faster. Let me know if I've made any mistakes from condensing the code (from my much bigger code).

like image 35
Warpspace Avatar answered Sep 28 '22 17:09

Warpspace


Edit 2. There is even a better way for doing fullscreen, the chromium way, source taken from here:

http://src.chromium.org/viewvc/chrome/trunk/src/ui/views/win/fullscreen_handler.cc?revision=HEAD&view=markup

void FullscreenHandler::SetFullscreenImpl(bool fullscreen, bool for_metro) {   ScopedFullscreenVisibility visibility(hwnd_);    // Save current window state if not already fullscreen.   if (!fullscreen_) {     // Save current window information.  We force the window into restored mode     // before going fullscreen because Windows doesn't seem to hide the     // taskbar if the window is in the maximized state.     saved_window_info_.maximized = !!::IsZoomed(hwnd_);     if (saved_window_info_.maximized)       ::SendMessage(hwnd_, WM_SYSCOMMAND, SC_RESTORE, 0);     saved_window_info_.style = GetWindowLong(hwnd_, GWL_STYLE);     saved_window_info_.ex_style = GetWindowLong(hwnd_, GWL_EXSTYLE);     GetWindowRect(hwnd_, &saved_window_info_.window_rect);   }    fullscreen_ = fullscreen;    if (fullscreen_) {     // Set new window style and size.     SetWindowLong(hwnd_, GWL_STYLE,                   saved_window_info_.style & ~(WS_CAPTION | WS_THICKFRAME));     SetWindowLong(hwnd_, GWL_EXSTYLE,                   saved_window_info_.ex_style & ~(WS_EX_DLGMODALFRAME |                   WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));      // On expand, if we're given a window_rect, grow to it, otherwise do     // not resize.     if (!for_metro) {       MONITORINFO monitor_info;       monitor_info.cbSize = sizeof(monitor_info);       GetMonitorInfo(MonitorFromWindow(hwnd_, MONITOR_DEFAULTTONEAREST),                      &monitor_info);       gfx::Rect window_rect(monitor_info.rcMonitor);       SetWindowPos(hwnd_, NULL, window_rect.x(), window_rect.y(),                    window_rect.width(), window_rect.height(),                    SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);     }   } else {     // Reset original window style and size.  The multiple window size/moves     // here are ugly, but if SetWindowPos() doesn't redraw, the taskbar won't be     // repainted.  Better-looking methods welcome.     SetWindowLong(hwnd_, GWL_STYLE, saved_window_info_.style);     SetWindowLong(hwnd_, GWL_EXSTYLE, saved_window_info_.ex_style);      if (!for_metro) {       // On restore, resize to the previous saved rect size.       gfx::Rect new_rect(saved_window_info_.window_rect);       SetWindowPos(hwnd_, NULL, new_rect.x(), new_rect.y(),                    new_rect.width(), new_rect.height(),                    SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);     }     if (saved_window_info_.maximized)       ::SendMessage(hwnd_, WM_SYSCOMMAND, SC_MAXIMIZE, 0);   } } 

Edit. It is probably better to create a fullscreen window as BrendanMcK pointed it out in a comment to this answer, see this link: http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05/414910.aspx ("How do I cover the taskbar with a fullscreen window?")

The new code using the link above would be:

HWND CreateFullscreenWindow(HWND hwnd) {  HMONITOR hmon = MonitorFromWindow(hwnd,                                    MONITOR_DEFAULTTONEAREST);  MONITORINFO mi = { sizeof(mi) };  if (!GetMonitorInfo(hmon, &mi)) return NULL;  return CreateWindow(TEXT("static"),        TEXT("something interesting might go here"),        WS_POPUP | WS_VISIBLE,        mi.rcMonitor.left,        mi.rcMonitor.top,        mi.rcMonitor.right - mi.rcMonitor.left,        mi.rcMonitor.bottom - mi.rcMonitor.top,        hwnd, NULL, g_hinst, 0); } 

Old answer below - do not use it, stays only for the record on how NOT to do this.

You have to hide taskbar and menubar to see fullscreen immediately.

Here is the code (uses WTL), call SetFullScreen(true) to go into full screen mode:

template <class T, bool t_bHasSip = true> class CFullScreenFrame { public:     bool m_fullscreen;     LONG m_windowstyles;     WINDOWPLACEMENT m_windowplacement;      CFullScreenFrame()          :         m_fullscreen(false),         m_windowstyles(0)     { }      void SetFullScreen(bool fullscreen)     {         ShowTaskBar(!fullscreen);          T* pT = static_cast<T*>(this);          if (fullscreen) {             if (!m_fullscreen) {                 m_windowstyles = pT->GetWindowLongW(GWL_STYLE);                 pT->GetWindowPlacement(&m_windowplacement);             }          }          // SM_CXSCREEN gives primary monitor, for multiple monitors use SM_CXVIRTUALSCREEN.         RECT fullrect = { 0 };                       SetRect(&fullrect, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));          WINDOWPLACEMENT newplacement = m_windowplacement;         newplacement.showCmd = SW_SHOWNORMAL;         newplacement.rcNormalPosition = fullrect;          if (fullscreen) {             pT->SetWindowPlacement(&newplacement);             pT->SetWindowLongW(GWL_STYLE,  WS_VISIBLE);             pT->UpdateWindow();         } else {             if (m_fullscreen) {                 pT->SetWindowPlacement(&m_windowplacement);                 pT->SetWindowLongW(GWL_STYLE, m_windowstyles);                 pT->UpdateWindow();             }         }          m_fullscreen = fullscreen;     }      void ShowTaskBar(bool show)     {         HWND taskbar = FindWindow(_T("Shell_TrayWnd"), NULL);         HWND start = FindWindow(_T("Button"), NULL);          if (taskbar != NULL) {             ShowWindow(taskbar, show ? SW_SHOW : SW_HIDE);             UpdateWindow(taskbar);         }         if (start != NULL) {              // Vista             ShowWindow(start, show ? SW_SHOW : SW_HIDE);             UpdateWindow(start);         }            } }; 

You also have to add some code to WM_CLOSE message:

case WM_CLOSE:     ShowTaskBar(true); 

There is one caveat with this solution, if your application crashes or is killed through task manager, then user losses taskbar on his system permanently! (unless he runs your application again, goes into fullscreen and exits, then he will see the taskbar again).

Earlier in my answer I pointed to "atlwince.h" but that function worked only on Windows CE, the one I pasted above works fine with XP, Vista and 7.

like image 177
Czarek Tomczak Avatar answered Sep 28 '22 17:09

Czarek Tomczak