【问题标题】:SendMessage WM_COPY not working when sent to chrome window DELPHISendMessage WM_COPY 在发送到 chrome 窗口 DELPHI 时不起作用
【发布时间】:2020-03-24 07:19:45
【问题描述】:

我已经尝试解决这个问题好几个星期了。我正在尝试在 Delphi 中创建一个在后台运行并捕获任何热键并执行 Ctrl + c 的应用程序。所以我所做的就是抓住热键,例如 ALT + 右箭头,然后模拟 Ctrl + c 并将命令扔到当前窗口。

我注意到的是,当我尝试向 Firefox 发送命令时,如下所示:

SendMessage(FireFoxHandle, WM_COPY, 0, 0);
sleep(250);
CopiedText := ClipBoard.AsText;

复制成功,我得到了预期的文本。但是,一旦我将同一行代码用于 chrome(chrome_widget_1) 或记事本等其他窗口,我什么也得不到。所以我尝试的是获取chrome和记事本的子窗口并尝试将命令发送到子窗口。

  1. 将“Chrome 旧版窗口”作为“chrome_widget_1”窗口的子窗口,但是当我尝试在选项卡中选择文本时,模拟 Ctrl + c,仍然无法正常工作。

  2. 在 stackoverflow 中找到了一个示例,用于将 wm_copy 发送到记事本的子窗口,该编辑类似于以下代码:

ParentWindw := FindWindow('Notepad',nil);
if ParentWindow <> 0 then
begin
  ChildWindow := FindWindowEx(ParentWindow, 0, 'Edit', nil);
  SendMessage(ChildWindow, WM_COPY, 0, 0);
  sleep(250);
  CopiedText := ClipBoard.AsText;
end;

代码有效,但有什么动态方法可以确定我需要用于 wm_copy 命令的子窗口吗?我不仅要记事本窗口,还要要所有可以使用的窗口。

或者无论如何我可以在 Delphi 中以编程方式在任何窗口中复制突出显示的文本,特别是在 xe2 中?

我已经研究过 sendinput、keyevents 并尝试了它们,但没有运气。我已经没有办法让它工作了。

提前感谢您的帮助。

【问题讨论】:

  • 不,没有动态方式。您需要了解每个特定应用程序。
  • 系统中没有任何东西可以保证任意窗口都会响应该消息
  • 你为什么要这么做?
  • @Olivier 嗨,因为我需要创建一个可以模拟 ctrl + c 的应用程序,在任何窗口中复制当前突出显示的文本。
  • 同样,发送WM_COPY 消息是行不通的。也许您应该询问您的根本问题,而不是您提出的解决方案(这是行不通的)。

标签: google-chrome delphi delphi-xe2 notepad windows-messages


【解决方案1】:

您在接受的答案中提供的 MouseAndKeyInput 代码只是 Windows 上 SendInput() 的包装,我在 cmets 中告诉您使用 3 天前。您可以(并且应该)完全摆脱这 5 个 .pas 文件,并将这 3 个单独的 KeyInput 方法调用替换为对 SendInput() 的 1 个调用。它可以一次发送所有 4 个键输入(Ctrl 向下、C 向下、C 向上、Ctrl 向上)原子地(这对于确保其他事件不会与您的事件混合很重要) ,例如:

var
  Inputs: array[0..3] of TInput;
begin
  ZeroMemory(@Inputs, SizeOf(Inputs));

  Sleep(250);

  Inputs[0].type := INPUT_KEYBOARD;
  Inputs[0].ki.wVk := VK_CONTROL;

  Inputs[1].type := INPUT_KEYBOARD;
  Inputs[1].ki.wVk := Ord('C');

  Inputs[2].type := INPUT_KEYBOARD;
  Inputs[2].ki.wVk := Ord('C');
  Inputs[2].ki.dwFlags := KEYEVENTF_KEYUP;

  Inputs[3].type := INPUT_KEYBOARD;
  Inputs[3].ki.wVk := VK_CONTROL;
  Inputs[3].ki.dwFlags := KEYEVENTF_KEYUP;

  SendInput(4, Inputs, SizeOf(TInput));

  Sleep(250);

  Memo1.Lines.Add(Clipboard.AsText);
end;

调用SendInput() 并将其cInputs 参数设置为1(如KeyInputMouseInput 那样)在实践中几乎总是是一个错误,并且只应在极少数情况下进行.

【讨论】:

  • 好的,试过了,效果很好。将改为使用它。非常感谢。
【解决方案2】:

好的。在这里找到与我有关的问题Topic: [SOLVED] Simulate ctrl+c press in active application (Windows)。那里的一个人建议使用“MouseAndKeyInput”,可以在这里找到并下载BGRA Controls。在下载链接里面会找到5个文件,分别是:

KeyInputIntf.pas
MouseAndKeyInput.pas
MouseInputIntf.pas
WinKeyInput.pas
WinMouseInput.pas

将这些文件添加到我的项目中,并将“MouseAndKeyInput”声明为我项目的实现用途。现在在我模拟 ctr c 的过程中:

Sleep(250);

KeyInput.Apply([ssCtrl]);
KeyInput.Press('C');
KeyInput.Unapply([ssCtrl]);

Sleep(250);

Memo1.Lines.Add(Clipboard.AsText);

备忘录中显示的文本是我从我目前正在工作的当前活动应用程序中突出显示的文本或行。

能够做到这一点到谷歌浏览器标签和记事本和任何其他应用程序。

感谢所有在这里提供帮助的人!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-07
    • 2014-06-01
    • 2013-03-12
    • 2013-06-04
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多