MCPcopy Create free account
hub / github.com/AutoHotkey/AutoHotkey / Display

Method Display

source/script_menu.cpp:1121–1267  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1119
1120
1121ResultType UserMenu::Display(bool aForceToForeground, int aX, int aY)
1122// aForceToForeground defaults to true because when a menu is displayed spontaneously rather than
1123// in response to the user right-clicking the tray icon, I believe that the OS will revert to its
1124// behavior of "resisting" a window that tries to "steal focus". I believe this resistance does
1125// not occur when the user clicks the icon because that click causes the task bar to get focus,
1126// and it is likely that the OS allows other windows to steal focus from the task bar without
1127// resistance. This is done because if the main window is *not* successfully activated prior to
1128// displaying the menu, it might be impossible to dismiss the menu by clicking outside of it.
1129{
1130 if (mMenuType != MENU_TYPE_POPUP)
1131 return g_script.RuntimeError(ERR_INVALID_MENU_TYPE);
1132 if (!mMenuItemCount)
1133 return OK; // Consider the display of an empty menu to be a success.
1134 if (!CreateHandle()) // Create if needed. No error msg since so rare.
1135 return FAIL;
1136 //if (!IsMenu(mMenu))
1137 // mMenu = NULL;
1138 if (this == g_script.mTrayMenu)
1139 {
1140 // These are okay even if the menu items don't exist (perhaps because the user customized the menu):
1141 CheckMenuItem(mMenu, ID_TRAY_SUSPEND, g_IsSuspended ? MF_CHECKED : MF_UNCHECKED);
1142 CheckMenuItem(mMenu, ID_TRAY_PAUSE, g->IsPaused ? MF_CHECKED : MF_UNCHECKED);
1143 }
1144
1145 POINT pt;
1146 if (aX == COORD_UNSPECIFIED || aY == COORD_UNSPECIFIED)
1147 GetCursorPos(&pt);
1148 if (!(aX == COORD_UNSPECIFIED && aY == COORD_UNSPECIFIED)) // At least one was specified.
1149 {
1150 // If one coordinate was omitted, pt contains the cursor position in SCREEN COORDINATES.
1151 // So don't do something like this, which would incorrectly offset the cursor position
1152 // by the window position if CoordMode != Screen:
1153 //CoordToScreen(pt, COORD_MODE_MENU);
1154 POINT origin = {0};
1155 CoordToScreen(origin, COORD_MODE_MENU);
1156 if (aX != COORD_UNSPECIFIED)
1157 pt.x = aX + origin.x;
1158 if (aY != COORD_UNSPECIFIED)
1159 pt.y = aY + origin.y;
1160 }
1161
1162 // UPDATE: For v1.0.35.14, must ensure one of the script's windows is active before showing the menu
1163 // because otherwise the menu cannot be dismissed via the escape key or by clicking outside the menu.
1164 // Testing shows that ensuring any of our thread's windows is active allows both the tray menu and
1165 // any popup or context menus to work correctly.
1166 // UPDATE: For v1.0.35.12, the script's main window (g_hWnd) is activated only for the tray menu because:
1167 // 1) Doing so for GUI context menus seems to prevent mouse clicks in the menu or elsewhere in the window.
1168 // 2) It would probably have other side effects for other uses of popup menus.
1169 HWND fore_win = GetForegroundWindow();
1170 bool change_fore;
1171 if (change_fore = (!fore_win || GetWindowThreadProcessId(fore_win, NULL) != g_MainThreadID))
1172 {
1173 // Always bring main window to foreground right before TrackPopupMenu(), even if window is hidden.
1174 // UPDATE: This is a problem because SetForegroundWindowEx() will restore the window if it's hidden,
1175 // but restoring also shows the window if it's hidden. Could re-hide it... but the question here
1176 // is can a minimized window be the foreground window? If not, how to explain why
1177 // SetForegroundWindow() always seems to work for the purpose of the tray menu?
1178 //if (aForceToForeground)

Callers 1

MainWindowProcFunction · 0.80

Calls 3

CoordToScreenFunction · 0.85
MsgSleepFunction · 0.85
RuntimeErrorMethod · 0.80

Tested by

no test coverage detected