Remove the System Menu of a QDialog on Windows

From Qt Wiki
Revision as of 17:37, 14 January 2015 by Maintenance script (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

How To: Remove the System Menu from a QDialog on Windows

This How To illustrates a – admittedly quite hacky – way to achieve a really native appearance for title bars of dialogs on Windows systems.

What goes wrong?

When using QDialogs on current Windows systems like Windows 7, there is one little thing you just can’t get right: It is near impossible to remove the system menu from the dialog title bar without removing the close button as well. In fact, trying to achieve a really native look for dialogs using the window flags provided by Qt is an exercise in futility.

Why does it go wrong?

The reason for this issue is a peculiarity in the Windows API: There is a dedicated window class for dialogs on windows. Window classes are – put simply – blueprints for window creation. The combination of window flags that enables the title bar without system menu and a close button does for some reason only work for windows created from the dialog window class. Unfortunately, Qt does not use the dialog window class for dialog creation, which is the reason for this shortcoming. See http://msdn.microsoft.com/en-us/library/windows/desktop/ms633574(v=vs.85).aspx for more details on window classes.

How to fix it?

There is a back door in Qt that allows for a workaround: The create() method of QWidget can be used to replace the native window handle managed by Qt with a new handle created by the Windows API. This makes it possible to create a new native window with the correct window class and hand it over to the QWidget as a replacement for the existing window:

mydialog.h

mydialog.cpp

The code above depends on functions available in user32.dll so an additional import library is required. Add the following to your .pro file:

Issues and Shortcomings

  • After applying the trick above, QWidget::setWindowFlags() cannot be used without bringing back the system menu immediately. Extra flags must be set before applying the hack or by using the appropriate Windows API functions directly.
  • Using this workaround involves a certain overhead, since two native window handles are created for every new dialog instance.
  • Since QWidget::create() is protected it is not possible to apply the hack to the predefined Qt dialogs without subclassing them.

Categories: