Set position when invoking context menu handlers

When my context menu shell extension is invoked from Directory Opus, it's resulting in its dialog showing at the top left hand side of the primary monitor (i.e. 0,0) - which doesn't happen when it's invoked from Windows Explorer.

It appears that Directory Opus is calling IContextMenu::InvokeCommand with the extended CMINVOKECOMMANDINFOEX structure, but isn't specifying the CMIC_MASK_PTINVOKE flag and setting the ptInvoke member.

There's nothing strictly wrong with that behaviour; it's not mandatory to do that as far as I'm aware, but it would be playing nice if it did do it.

If I ignore that flag/position, with Windows Explorer, calling GetMessagePos (to get the cursor position for the last Windows message) results in the mouse position at the point of invoking the context menu, which is generally fine for positioning a dialog close to the menu item. However Directory Opus is inconsistent; when a context menu is invoked from the Folder Tree pane, GetMessagePos gives good results, but when invoked from the right hand panes, it returns 0.

Would it be possible to make DO's right hand pane and its Folder Tree pane consistent, and ideally have them both set the CMIC_MASK_PTINVOKE flag and set the ptInvoke member to the appropriate position?

What kind of thing do you need this for? I'm having trouble working out what it would be useful for, at least where using using GetCursorPos to get the current pointer position would not work just as well.

Microsoft's documentation of the field has very little detail, which makes it unclear exactly what it's meant to be set to, and makes me wonder how anyone (on either side of the structure) is meant to know how to use it. (Is it the mouse position? The top-left corner of the context menu? (The first menu or the sub-menu with the item in it?) The top-left of the menu item that was selected? In screen coordinates or relative to the menu, or the parent window that spawned the menu?)

Another complication is that Opus lets people run context menu items via toolbar buttons and hotkeys. The mouse cursor may be nowhere near the file being acted on, or even the Opus window. Would what you're aiming to do still make sense in that situation? It would have to cope with that possibility in either case.

Hi Leo,

It's there to provide a position to display UI at.

It's usage is similar to why the WM_CONTEXTMENU message passes coordinates - because by the time any UI is shown, the user could have moved the mouse elsewhere (such as a different monitor) with the result that the UI would show up where the mouse currently is, rather than where it was when the operation was invoked.

It's screen co-ordinates, and I guess is just meant to be as good an estimate as to where to position UI as you can get. So, if the operation is instigated by a mouse operation, it would be the cursor position when you received the mouse click. If it were a keyboard operation on a menu item, it would be a point near to where the menu item is on screen. If it's a keyboard accelerator operation, the position probably depends on what makes sense to the current focus of the application.

Does that help clarify the usage?

Makes sense. I'll have a look in more detail when I have time. From a quick look this morning, we don't have the menu position information in all situations (only some), and I'm pretty sure we never have the position of the selected menu item itself, which it sounds like you really need. But we might be able to plumb it through, depending on how difficult it is.

In terms of GetMessagePos vs GetCursorPos, the difference should be minor unless the machine's under heavy load, in which case it's hard to know if the user would want the UI to appear where the mouse now is or where it was and seems fairly arbitrary. Where it was is probably more correct though, I agree. At least when the mouse was used at all. For keyboard stuff, you'd want the menu item rather than the mouse position, so that's what we'll aim to return in all cases.

Presumably you don't care if it's the top-left, middle, bottom-right etc. of the menu item, as long as it's somewhere near it?

1 Like

Somewhere near to ought to be fine Leo; just so that whatever UI consequently appears is in the area of whatever the user was doing when they invoked the operation.

We've implemented this for the next update.

FWIW, in my testing, I found that File Explorer only gives you the position sometimes. If you right-click things in Explorer's folder tree, you don't get any position there. So it doesn't seem like something you can really rely on, but Opus will make things easier for you now at least.

Yes, the tree pane doesn't provide the information, but in that situation GetMessagePos seems to provide a reasonable position. I guess a different team at MS implemented that - the left hand not knowing what the right one does :slight_smile: It's inconsistent in other ways too - Alt+Enter not showing Properties as it does in the listview pane.

1 Like

That change is in the beta released today: Directory Opus 12.24.1 (Beta)

Well done; more consistent than Windows Explorer is :slight_smile: