Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Disabling/enabling system menu items?
Forum Updated to NodeBB v4.3 + New Features

Disabling/enabling system menu items?

Scheduled Pinned Locked Moved Unsolved General and Desktop
4 Posts 2 Posters 1.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Q Offline
    Q Offline
    Qt_User72653
    wrote on last edited by
    #1

    Does anyone have a working example of how to disable and enable items in the system menu on Windows?

    I've tried:

    EnableMenuItem(), which changes the flags for the item but doesn't actually disable it,

    SetWindowLong(), which doesn't seem to do anything,

    and,

    ModifyMenu() with GetMenuItemInfo(), which disables the item but when re-enabled no longer sends a windows command when clicked.

    I need to be able to temporarily disable an item and re-enable it later, for use with a frameless window.

    1 Reply Last reply
    0
    • Q Offline
      Q Offline
      Qt_User72653
      wrote on last edited by
      #2

      Update: so I put this into the constructor of one of my widgets:

        QTimer::singleShot(2500, [=] {
          EnableMenuItem(system_menu, SC_MAXIMIZE, MF_BYCOMMAND | MF_DISABLED);
        });
      

      With the menu open, after the timer executes, the maximize item is disabled, but when I close the menu and reopen it the maximize item is re-enabled.

      1 Reply Last reply
      0
      • Chris KawaC Offline
        Chris KawaC Offline
        Chris Kawa
        Lifetime Qt Champion
        wrote on last edited by
        #3

        If you want to disable maximizing of the window you should do that via window flags, for example in the constructor:

        MainWindow::MainWindow(QWidget *parent)
          : QMainWindow(parent
                       , Qt::Window
                       | Qt::CustomizeWindowHint
                       | Qt::WindowSystemMenuHint
                       | Qt::WindowMinimizeButtonHint
                       | Qt::WindowCloseButtonHint)
                       , ui(new Ui::MainWindow)
        {
           ...
        

        This will disable all the ways a window can be maximized (like aero snap or double click on the title bar), not just via system menu.

        But if you really want to fiddle with the system menu the timer started in a constructor is a really bad idea. The underlying native window (and menu) are created when the widget is first shown, so if the window is not shown immediately after it is created there might not yet be any system menu yet.

        The correct place to modify system menu is in response to WM_INITMENU message. You can implement a native event filter for example like this:

        bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, long* result)
        {
            MSG* msg = (MSG*)message;
            if (msg->message == WM_INITMENU)
            {
                HMENU menu = (HMENU)msg->wParam;
                EnableMenuItem(menu, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
            }
        
            return QMainWindow::nativeEvent(eventType, message, result);
        }
        
        Q 1 Reply Last reply
        1
        • Chris KawaC Chris Kawa

          If you want to disable maximizing of the window you should do that via window flags, for example in the constructor:

          MainWindow::MainWindow(QWidget *parent)
            : QMainWindow(parent
                         , Qt::Window
                         | Qt::CustomizeWindowHint
                         | Qt::WindowSystemMenuHint
                         | Qt::WindowMinimizeButtonHint
                         | Qt::WindowCloseButtonHint)
                         , ui(new Ui::MainWindow)
          {
             ...
          

          This will disable all the ways a window can be maximized (like aero snap or double click on the title bar), not just via system menu.

          But if you really want to fiddle with the system menu the timer started in a constructor is a really bad idea. The underlying native window (and menu) are created when the widget is first shown, so if the window is not shown immediately after it is created there might not yet be any system menu yet.

          The correct place to modify system menu is in response to WM_INITMENU message. You can implement a native event filter for example like this:

          bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, long* result)
          {
              MSG* msg = (MSG*)message;
              if (msg->message == WM_INITMENU)
              {
                  HMENU menu = (HMENU)msg->wParam;
                  EnableMenuItem(menu, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
              }
          
              return QMainWindow::nativeEvent(eventType, message, result);
          }
          
          Q Offline
          Q Offline
          Qt_User72653
          wrote on last edited by Qt_User72653
          #4

          @Chris-Kawa

          The problem with setting window flags is that I'm intercepting the maximize command to simulate the window being maximized, so I need a way to enable the restore button while disabling the maximize button. In my experience it's been easier to just make the window appear as if it was maximized rather than deal with all the issues regarding the window state and size when dealing with frameless windows on multiple monitors (I'm doing a completely custom window).

          The timer was just a (in)sanity test to see if the EnableMenuItem() function worked at all, and I found in my case it only did when the menu was already open when the function was called. It seems like every time I open the system menu, it's creating a new one, because none of my changes are permanent; even when I call EnableMenuItem() outside of the constructor.

          I have a native event filter installed on the qApp instance, but I never receive the WM_INITMENU message.

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved