I have implemented a custom titlebar for my window and I want to display the default system (context) menu when right-clicking on it. My current approach is as follows:
auto sysMenu = ctrl_->MSWGetSystemMenu();
if( sysMenu )
{
//sysMenu->Bind( wxEVT_MENU, &WxWindow::onSystemMenu, this );
ctrl_->PopupMenu( sysMenu, pos );
}
It successfully displays the system menu, but clicking on any item doesn't seem to have any effect. I initially thought it would send a relevant message, such as SC_CLOSE
, to the window's message handler, but it's not happening. My second assumption was that I might need to create my own handler and handle the message there. So, I created a handler function named onSystemMenu
like below:
void onSystemMenu( wxCommandEvent& e )
{
int id = e.GetId();
switch( id )
{
case wxID_MAXIMIZE_FRAME: // Maximize the window
ctrl_->Maximize();
break;
case wxID_RESTORE_FRAME: // Restore the window to its previous size and position
ctrl_->Restore();
break;
case wxID_ICONIZE_FRAME: // Minimize the window
ctrl_->Iconize();
break;
case wxID_CLOSE_FRAME: // Close the window
ctrl_->Close();
break;
}
}
However, the received ID is always different from those expected values. For instance, I'm receiving values like -4048
, which doesn't correspond to any of the IDs I listed. I still believe there should be a way to achieve this without manually creating a handler. Can someone please provide assistance?
It seems the following code works:
auto pos = wxGetMousePosition();
auto hwnd = ctrl_->GetHandle();
auto menu = GetSystemMenu( hwnd, FALSE );
if( menu )
{
MENUITEMINFO mInfo;
mInfo.cbSize = sizeof( MENUITEMINFO );
mInfo.fMask = MIIM_STATE;
mInfo.fType = 0;
// update the options
mInfo.fState = MF_ENABLED;
SetMenuItemInfo( menu, SC_RESTORE, FALSE, &mInfo );
SetMenuItemInfo( menu, SC_SIZE, FALSE, &mInfo );
SetMenuItemInfo( menu, SC_MOVE, FALSE, &mInfo );
SetMenuItemInfo( menu, SC_MAXIMIZE, FALSE, &mInfo );
SetMenuItemInfo( menu, SC_MINIMIZE, FALSE, &mInfo );
mInfo.fState = MF_GRAYED;
WINDOWPLACEMENT wp;
GetWindowPlacement( hwnd, &wp );
switch( wp.showCmd )
{
case SW_SHOWMAXIMIZED:
SetMenuItemInfo( menu, SC_SIZE, FALSE, &mInfo );
SetMenuItemInfo( menu, SC_MOVE, FALSE, &mInfo );
SetMenuItemInfo( menu, SC_MAXIMIZE, FALSE, &mInfo );
SetMenuDefaultItem( menu, SC_CLOSE, FALSE );
break;
case SW_SHOWMINIMIZED:
SetMenuItemInfo( menu, SC_MINIMIZE, FALSE, &mInfo );
SetMenuDefaultItem( menu, SC_RESTORE, FALSE );
break;
case SW_SHOWNORMAL:
SetMenuItemInfo( menu, SC_RESTORE, FALSE, &mInfo );
SetMenuDefaultItem( menu, SC_CLOSE, FALSE );
break;
}
auto Selected = TrackPopupMenu(
menu, TPM_RIGHTBUTTON | TPM_RETURNCMD, pos.x, pos.y, 0, hwnd, NULL );
if( Selected )
SendMessage( hwnd, WM_SYSCOMMAND, Selected, 0 );
}
Maybe a bug in PopupMenu
of wxWidgets?!