1
votes

I want a window which behaves identically to normal Overlapped window, except it does not have capton bar when maximized (to make more room for the client area). I can remove WS_CAPTION|WS_SYSMENU from the window style. However, I cannot find way to get window position and size right:

A normal window is maximized by expanding work area rectangle with border width. This makes border to "hang" outside. When I remove WS_CAPTION, the border is different (3 vs 4 pixels in my case) so I have to reposition the window somehow.

What I have tried:

  • First change style, then maximize: this does not maximize to work area, but to full screen instead. Looks like this is a feature of window manager that relies on WS_CAPTION style. Other than that, the border is "hanging" correctly.

  • First maximize, then change style, position and size:

    • I can't find API to get the maximized size and position. However, work area of closest monitor looks good to me.
    • I can't find API to expand window rect with appropriate "hanging border". AdjustWindowRectEx is almost there, however non-client area is not the same as border (obviously it also includes caption and menu). I also tried to do the math myself using GetSystemMetrics values, but it seems too unpredictable. The border could be SM_CXSIZEFRAME, or SM_CXSIZEFRAME+SM_CXPADDEDBORDER, or SM_CXFIXEDFRAME, and maybe this depends on OS version, theme and whatever.

Is it possible to do this in a robust, "official" way?
I put my own answer below but it is too hacked.

2
I don't think you actually want to do this. Maximised windows behave differently to Fullscreen windows and trying to make them the same is so painful - with so much potential user confusion - that, since the release of Windows 95 - no-one has pulled it off. Browsers and media players and games all have a Fullscreen mode that is distinct from being maximised. You need your own UI of course to enter and leave fullscreen mode - but all you do is strip off all chrome and size the window to exactly fit the full display.Chris Becke
So I am not supposed to keep window border? This makes things a lot simpler.shekh
Yep. The shell understands this kind of fullscreen window - if a window is sized to exactly fill a display the shell will automatically hide the taskbar while it is the active window.Chris Becke
Raymond Chen explains this in detail on his blog here: blogs.msdn.microsoft.com/oldnewthing/20100412-00/?p=14353Adrian McCarthy
I saw oldnewthing article and all the comments.shekh

2 Answers

1
votes

You are already removing the caption. If you don't want to show the borders, then remove the borders as well. Get ready to restore the border later. Find the desktop rectangle, and position the window in to that rectangle. The full screen window can have WS_OVERLAPPED or WS_POPUP flag with no caption and no borders. Example:

void switch_view()
{
    RECT rc;
    SystemParametersInfo(SPI_GETWORKAREA, 0, &rc, 0);
    DWORD style = GetWindowLongPtr(hwnd, GWL_STYLE);
    if(style & WS_CAPTION)
    {
        SetWindowLongPtr(hwnd, GWL_STYLE, WS_OVERLAPPED);
        SetWindowLongPtr(hwnd, GWL_EXSTYLE, 0);
        SetWindowPos(hwnd, NULL, 0, 0, rc.right, rc.bottom,
            SWP_SHOWWINDOW | SWP_FRAMECHANGED);
    }
    else
    {
        SetWindowLongPtr(hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW);
        SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
            SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
    }
}
1
votes

This is what I get after many attempts.

  • The border problem is solved. As suggested by others, I remove border together with caption. Therefore no need to calculate it. There is also no need to calculate border for captioned window with border, because this is special-cased by window manager.

  • To obtain and maintain the right size, I use MonitorFromWindow and GetMonitorInfo. The position and size are applied together with style change (both ways) and also in WM_SIZE handler. Watching WM_SIZE allows to recover from external minimize-restore events, as well as TaskBar change etc.

  • For unknown reason, moving with Win+Arrow keys does not work. This issue only exists when the window is in maximized state and without caption. Using this workaround:

    • in WM_WINDOWPOSCHANGING set WS_CAPTION style. This allows window to move correctly. Afterwards, the WM_SIZE handler applies the right style/position/size again.
    • Approach that failed: use restored window rather than maximized. In this case there is too much going wrong in restore-move-maximize-restore lifecycle (either restore or maximize goes to wrong monitor).