1

I have an app written in Qt and on Windows I handle native events myself, to have a custom window with native feeling.

I'm removing the caption like this, to achieve that the window is also positioned correctly when the taskbars auto-hide option is on.

DWORD style = GetWindowLong (hwnd, GWL_STYLE);
style &= ~WS_CAPTION;
style |= (WS_MAXIMIZEBOX | WS_THICKFRAME);
SetWindowLong (hwnd, GWL_STYLE, style);

..and I hide the border like suggested in the MSDN documentation:

switch (msg)
{
    case WM_NCCALCSIZE:
    {
        // this removes the window frame and title bar we added with WS_THICKFRAME and
        // WS_CAPTION
        *result = 0;
        return true;
    }

    ...

I get a fully functional frameless window BUT when I hit the taskbar the border appears, which I don't want. So does anyone have an idea why this happens and how I could bypass it?

Btw if I don't remove the caption from the style I also have a frameless window and this problem doesn't appear but then I run into other problems.

easysaesch
  • 159
  • 1
  • 14
  • `&= WS_CAPTION` turns off everything but the `WS_CAPTION` bit. Do you really mean `&= ~WS_CAPTION` ? – Jonathan Potter Mar 22 '18 at 15:13
  • yeah I edited it. Thanks. – easysaesch Mar 22 '18 at 15:32
  • Your window procedure is unfamiliar. What is `result`? and why the function returns `true`? – Barmak Shemirani Mar 22 '18 at 15:53
  • Ah I'm still in Qt context. `*result = 0` would be equal to `return 0` in WindowProc. – easysaesch Mar 22 '18 at 16:00
  • Can you give the link to the MSDN page that recommended mucking with WM_NCCALCSIZE? Under WM_NCCALCSIZE, I see, "Starting with Windows Vista, removing the standard frame by simply returning 0 when the wParam is TRUE does not affect frames that are extended into the client area using the DwmExtendFrameIntoClientArea function. Only the standard frame will be removed." Sounds suspiciously related. – Adrian McCarthy Mar 22 '18 at 20:22

1 Answers1

1

From SetWindowLong reference:

Certain window data is cached, so changes you make using SetWindowLong will not take effect until you call the SetWindowPos function. Specifically, if you change any of the frame styles, you must call SetWindowPos with the SWP_FRAMECHANGED flag for the cache to be updated properly.

Call SetWindowPos like this to fix the problem:

SetWindowPos( hwnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE );

This will also cause Windows to send a WM_NCCALCSIZE message to your window to recalculate the NC area.

zett42
  • 25,437
  • 3
  • 35
  • 72
  • I just tried it. When interacting with the task bar the window frame still appears and disappears as soon as I resize the window. – easysaesch Mar 22 '18 at 16:24
  • @bob I think in `WM_NCCALCSIZE` you are missing the check if `wParam` is `TRUE` as described in the reference of this message (in the comments section). If not, you should call the original window procedure to let the system do the default. – zett42 Mar 22 '18 at 16:42
  • So the standard frame that I got rid of is not the same that appears when I hit the task bar? I haven't used the dwmapi so I don't have an idea what to do. – easysaesch Mar 22 '18 at 16:53
  • @bob I have a more detailed [answer](https://stackoverflow.com/a/43819334/7571258) to another question, maybe this helps you. – zett42 Mar 22 '18 at 17:11
  • I see what you did there. I tested out your sample code. Changing the style of it to how I did in my app, reproduces the problem I have. So removing the caption by `style &= ~WS_CAPTION;` leads to the same problem when hitting the taskbar. So I guess a solution would be not removing the caption BUT when I do this, the window overlaps the taskbar when maximizing. – easysaesch Mar 28 '18 at 14:22