Show the system menu of a window at the current mouse cursor position (Views: 27)
Problem/Question/Abstract: How can I show the system menu of a window at the position of the mouse cursor and not at the window's title bar? Answer: Solve 1: The problem is that the system menu sends WM_SYSCOMMAND messages to the window identified by Handle, and you are probably looking for WM_COMMAND messages. r := integer(TrackPopupMenuEx(GetSystemMenu(handle, false), TPM_LEFTALIGN or TPM_RETURNCMD or TPM_RIGHTBUTTON or TPM_HORIZONTAL or TPM_VERTICAL, x, y, handle, nil)); SendMessage(handle, WM_SYSCOMMAND, r, 0); Solve 2: Well, you can pop the system menu up where you want using code like the one below: procedure TForm1.SpeedButton1Click(Sender: TObject); var h: HMENU; begin h := GetSystemMenu(handle, false); TrackPopupMenu(h, TPM_LEFTALIGN or TPM_LEFTBUTTON, speedbutton1.Left + clientorigin.X, speedbutton1.Top + speedbutton1.Height + clientorigin.y, 0, handle, nil); end; The problem is that the menu will not work this way. If you use TrackPopupMenu to show the menu its items will send WM_COMMAND messages to the form when clicked by the user. But the form expects WM_SYSCOMMAND messages from the system menu. So you have to trap the WM_COMMAND messages, figure out which of them come from the menu (there will be lots of others, from buttons and the like) and translate them into WM_SYSCOMMAND. { ... } private { Private declarations } procedure WMCommand(var msg: TWMCommand); message WM_COMMAND; { ... } procedure TForm1.WMCommand(var msg: TWMCommand); begin if msg.NotifyCode = 0 then {message comes from a menu} if msg.ItemID >= SC_SIZE then begin {looks like system menu item} PostMessage(handle, WM_SYSCOMMAND, TMessage(msg).WParam, TMessage(msg).LParam); Exit; end; inherited; end; Solve 3: There is an undocumented Windows message (Message ID:$313) that can do it: procedure TForm1.Button1Click(Sender: TObject); const WM_POPUPSYSTEMMENU = $313; begin SendMessage(Handle, WM_POPUPSYSTEMMENU, 0, MakeLong(Mouse.CursorPos.X, Mouse.CursorPos.Y)); end; |