I’m writing a C# automation tool.
Since Microsoft UI Automation doesn’t provide any way of simulating right-clicks or raising context menus, I’m using SendMessage to do this instead. I’d rather not use SendInput because I don’t want to have to grab focus.
When I call SendMessage, however, it crashes the target app.
Here’s my code:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
public void RightClick<T>(T element) where T: AutomationElementWrapper
{
const int MOUSEEVENTF_RIGHTDOWN = 0x0008; /* right button down */
const int MOUSEEVENTF_RIGHTUP = 0x0010; /* right button up */
var point = element.Element.GetClickablePoint();
var processId = element.Element.GetCurrentPropertyValue(AutomationElement.ProcessIdProperty);
var window = AutomationElement.RootElement.FindFirst(
TreeScope.Children,
new PropertyCondition(AutomationElement.ProcessIdProperty,
processId));
var handle = window.Current.NativeWindowHandle;
var x = point.X;
var y = point.Y;
var value = ((int)x)<<16 + (int)y;
SendMessage(new IntPtr(handle), MOUSEEVENTF_RIGHTDOWN, IntPtr.Zero, new IntPtr(value));
SendMessage(new IntPtr(handle), MOUSEEVENTF_RIGHTUP, IntPtr.Zero, new IntPtr(value));
}
Any idea what I’m doing wrong?
You’re mixing up your types. You’re using
SendMessage, which takes a window message (which by convention are namedWM_…), but you’re passing it aMOUSEINPUT.dwFlagsvalue that’s meant forSendInput(which are namedMOUSEEVENTF_…). You’re basically passing gibberish.What your code is actually doing is sending a window message whose numeric value is 8 (which, in window messages, means
WM_KILLFOCUS), followed by a window message of 0x10 == 16 (WM_CLOSE). It’s the latter that’s likely causing you problems — you’re telling the window to close. I’m not sure why it would crash, but it would certainly exit.If you’re using
SendMessage, you need to pass it window messages (WM_, for exampleWM_RBUTTONDOWNandWM_RBUTTONUP).