Closed FaithBeam closed 6 months ago
Hello! Thanks for posting this issue! I'm not sure, seems like it should work the way you assume. I will look into it.
Well, I can reproduce this behavior, but I don't know why that happens, and searching for that particular behavior in Windows API didn't yield any results, though I do think it's some weird quirk of the Windows API. I will try looking into it later, but for now all I can do is just shrug.
As a workaround, you can simulate events in a different thread. For example, wrapping calls to eventSimulator
in Task.Run
made this work for me - but you shouldn't use Task.Run
as you need to guarantee the correct sequence of simulated events, and Task.Run
won't give you such a guarantee.
I appreciate you looking into this. I recreated the issue with direct win32 calls using the cswin32 nupkg. Comment lines 32-42 to not send rmb clicks and properly suppress xb1:
using System.Runtime.InteropServices;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.UI.Input.KeyboardAndMouse;
using Windows.Win32.UI.WindowsAndMessaging;
namespace newtest;
class Program
{
static unsafe void Main(string[] args)
{
var handle = PInvoke.GetModuleHandle((string?)null);
var hhook = PInvoke.SetWindowsHookEx(
WINDOWS_HOOK_ID.WH_MOUSE_LL,
(code, param, lParam) =>
{
if (code < 0)
{
return PInvoke.CallNextHookEx(null, code, param, lParam);
}
if (param == PInvoke.WM_XBUTTONDOWN || param == PInvoke.WM_XBUTTONUP)
{
var msll = Marshal.PtrToStructure<MSLLHOOKSTRUCT>(lParam);
// switch on high-order word
switch (((ushort*)&msll.mouseData)[1])
{
case PInvoke.XBUTTON1:
Console.WriteLine("XB1");
// send rmb
var input = new INPUT { type = INPUT_TYPE.INPUT_MOUSE };
input.Anonymous.mi.dx = msll.pt.X;
input.Anonymous.mi.dy = msll.pt.Y;
input.Anonymous.mi.dwFlags =
MOUSE_EVENT_FLAGS.MOUSEEVENTF_ABSOLUTE
| MOUSE_EVENT_FLAGS.MOUSEEVENTF_RIGHTDOWN
| MOUSE_EVENT_FLAGS.MOUSEEVENTF_RIGHTUP;
input.Anonymous.mi.mouseData = 0;
input.Anonymous.mi.dwExtraInfo = 0;
input.Anonymous.mi.time = 0;
PInvoke.SendInput(1, &input, sizeof(INPUT));
// suppress xb1
return (LRESULT)(-1);
}
}
return PInvoke.CallNextHookEx(null, code, param, lParam);
},
handle,
0
);
while (PInvoke.GetMessage(out var lpMsg, HWND.Null, 0, 0) != -1)
{
PInvoke.TranslateMessage(lpMsg);
PInvoke.DispatchMessage(lpMsg);
}
}
}
To be able to run that code, it needs a project with cswin32 nupkg and a NativeMethods.txt designating which functions/structs to generate. I've created that here: https://github.com/FaithBeam/win32-suppress-issue
I've tried "converting" the original mouse click by editing the code, param, and lparam values and returning CallNetHook in the lowlevelmouseproc, but that didn't work. The original mouse click went through.
Well, in that case I don't think I can really do anything to fix this behavior as this is a quirk of the Windows API itself. I think the best way to do what you want is to simulate events on a different thread.
I'm going to close this issue as a won't-fix, but we can continue the discussion.
System: Windows 11 Sharphook version: 5.3.2 .NET Version: 8.0
Hello! I'd like to "convert" a real mouse button 4 click into a simulated mouse button 2 click. My set up is that I listen for mouse button 4 press and release events, suppress that event, and simulate mouse button 2 press and release events. However, I cannot get this to work when I simulate a mouse event. Both the original mouse click and simulated mouse go through. I can suppress the original mouse click when I simulate a keyboard event though.
Here is a video to show what I'm writing about: https://www.youtube.com/watch?v=TDHwdC9fakI
In the video I show two scenarios:
We can see that scenario two does not work because the tabs get flipped through in notepad++ because of mouse button 4.
Here is the code in the video:
Am I doing this incorrectly?
Thank you!