windows 为什么模拟鼠标单击(使用 mouse_event)仅适用于选定的组件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3244002/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 14:50:10  来源:igfitidea点击:

Why does a simulated mouse click (using mouse_event) work on selected components only?

windowsdelphiwinapi

提问by Dian

I have multiple cursors (which are actually forms) that can be controlled by their respective mouse. (1 cursor for 1 user).

我有多个光标(实际上是表单),可以由它们各自的鼠标控制。(1 个用户的 1 个光标)。

I use SetCursorPosto position the default cursor (the original system cursor) in a position that will not take away the focus from my application, and use ShowCursor(false)to hide it.

SetCursorPos习惯于将默认光标(原始系统光标)定位在不会从我的应用程序中夺走焦点的位置,并用于ShowCursor(false)隐藏它。

I have a class that gets the handle of the mouse and the coordinates.

我有一个获取鼠标句柄和坐标的类

When the user clicks I use the SetCursorPosand the mouse_eventto simulate the clicks in that particular position.

当用户点击时,我使用SetCursorPosmouse_event来模拟该特定位置的点击。

My simulated mouse clicks only work on certain components' OnClick event (It was supposed to be only buttons and labels, but I experimented with the stuff on my project just to know what will or won't work):

我的模拟鼠标点击仅适用于某些组件的 OnClick 事件(它应该只是按钮和标签,但我在我的项目中试验了这些东西只是为了知道什么会或不会起作用):

It works on:

它适用于:

  • Buttons (TButton, TBitBtn, TAdvSmoothButton)
  • TAdvGrid
  • TMenuItem (but the direct child of the TMainMenu only)
  • TRadioButton
  • 按钮(TButton、TBitBtn、TAdvSmoothButton)
  • 网格
  • TMenuItem(但仅限 TMainMenu 的直接子项)
  • 单选按钮

It doesn't work on:

它不适用于:

  • TLabel
  • Panels (TPanel, TAdvSmoothPanel)
  • TCoolBar
  • TMenuItem (not direct child of TMainMenu)
  • 标签
  • 面板(TPanel、TAdvSmoothPanel)
  • 酷吧
  • TMenuItem(不是 TMainMenu 的直接子项)

This is my code:

这是我的代码:

 SetCursorPos(currentX , currentY);
 mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
 mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);

Why doesn't it work on some components? Is there a workaround (because I would like to be able to click labels using mouse_event).

为什么它不适用于某些组件?是否有解决方法(因为我希望能够使用 mouse_event 单击标签)。

EDIT: I tried checking if the clicking function was really called, so I put ShowMessage('clicked');before the SetCursorPos and mouse_event...but strangely everything (minor edit: everything except MenuItems) works fine now (except for the fact that I have a Message popping out everytime I try to click something). Does anybody have an idea why this behaves that way?

编辑:我尝试检查点击功能是否真的被调用,所以我放在ShowMessage('clicked');SetCursorPos 和 mouse_event 之前......但奇怪的是,一切(小编辑:除了 MenuItems 之外的一切)现在都可以正常工作(除了我有一条消息弹出的事实)每次我尝试点击某些东西时)。有人知道为什么会这样吗?

回答by Necrolis

mouse_event is actually deprecated, you should use SendInputinstead, see if that fixes anything (I would also suggest making the mouse move an input message, over using SetCursorPos), also, if your doing this for a specific application, PostMessagemight be a much better and simpler alternative

mouse_event 实际上已被弃用,您应该改用SendInput,看看是否可以解决任何问题(我还建议让鼠标移动输入消息,而不是使用 SetCursorPos),此外,如果您为特定应用程序执行此操作,则PostMessage可能很重要更好更简单的替代方案

回答by Sertac Akyuz

Seems to work here;

似乎在这里工作;

procedure TForm1.Panel1Click(Sender: TObject);
begin
  ShowMessage('Click');
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Pt: TPoint;
begin
  Pt := Panel1.ClientToScreen(Point(0, 0));
  SetCursorPos(Pt.x, Pt.y);
//  SetCursorPos(Panel1.ClientOrigin.x, Panel1.ClientOrigin.y);
  mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
  mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
end;

or, without SetCursorPos;

或者,没有SetCursorPos

procedure TForm1.Button1Click(Sender: TObject);
var
  Pt: TPoint;
begin
  Pt := Panel1.ClientToScreen(Point(0, 0));
  Pt.x := Round(((Pt.x + 1) * 65535) / Screen.Width);
  Pt.y := Round(((Pt.y + 1) * 65535) / Screen.Height);
  mouse_event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_MOVE or MOUSEEVENTF_LEFTDOWN,
      Pt.x, Pt.y, 0, 0);
  mouse_event(MOUSEEVENTF_ABSOLUTE or MOUSEEVENTF_MOVE or MOUSEEVENTF_LEFTUP,
      Pt.x, Pt.y, 0, 0);
end;

回答by Hans Passant

It works by accident right now, those components have probably captured the mouse. You need to pass the mouse pointer coordinates in the 2nd and 3rd arguments. Thus:

它现在偶然工作,那些组件可能已经捕获了鼠标。您需要在第二个和第三个参数中传递鼠标指针坐标。因此:

 //SetCursorPos(currentX , currentY);
 mouse_event(MOUSEEVENTF_LEFTDOWN, currentX, currentY, 0, 0);
 mouse_event(MOUSEEVENTF_LEFTUP, currentX, currentY, 0, 0);