如何在其他应用程序中可靠地调用剪贴板复制/粘贴操作而不扰乱输入队列

发布于 2024-10-06 08:03:41 字数 739 浏览 5 评论 0原文

不久前,我编写了一个简单的应用程序,当用户按下某些热键时,它会用一些 unicode 符号包围任何应用程序中任何输入字段中的选定文本。基本上,应用程序的逻辑如下:

  • 注册全局热键。
  • 热键已触发,现在设置剪贴板监视器并调用剪贴板复制以查看是否选择了某些文本。
  • 如果剪贴板已更改并且现在包含文本,请用符号包围所述文本,然后调用剪贴板粘贴,以便输入字段将使用修改后的文本进行更新。

问题是,我无法以可靠的方式从其他应用程序获取复制/粘贴功能。迄今为止我所尝试过的:

  1. 如果我发送 WM_COPY/WM_PASTE,它通常会被忽略,具体取决于应用程序。
  2. 如果我使用 SendInput、keybd_event 或任何其他键盘混乱的东西来按下/取消按下常用的剪贴板热键,它通常会篡改用户按下的键:复制/粘贴使用 control 或 shift,这对于所有通用热键来说也很流行应用程序,包括我的应用程序。
  3. 如果我使用 Journal Hook 直接将键盘消息注入系统输入队列,有时会正常工作,有时会出现奇怪的故障。另外,其他应用程序可能会自己使用 JournalHook,这会严重扰乱我的应用程序。更不用说默认的安全策略使日志挂钩难以使用。
  4. 我一直在尝试使用 Windows UI 自动化而不是剪贴板魔术来获取/设置输入字段中的文本,但它很少起作用。

因此,如果您知道使其他应用程序可靠地使用复制/粘贴功能的其他方法,或者甚至可以设计完全不同的方法,我真的很感激您告诉我:)

A while ago I wrote a simple app, which surrounds selected text in any input field in any application with some unicode symbols when user presses some hotkey. Basically, app's logic is as follows:

  • Register global hotkey.
  • Hotkey fired, now set clipboard monitor and invoke clipboard copy to see if some text was selected.
  • If clipboard has changed and now contains text, surround said text with symbols and then invoke clipboard paste, so input field will be updated with modified text.

The problem is, I can't get copy/paste functionality from other apps in a reliable way. What I have tried to date:

  1. If I send WM_COPY/WM_PASTE, it's more often ignored than not, depending on the application.
  2. If I use SendInput, keybd_event or any other keyboard-messing stuff to press/unpress usual clipboard hotkeys, it will often tamper with user-pressed keys: copy/paste uses control or shift, which are also quite popular for all generic hotkeys in all apps, my app included.
  3. If I use Journal Hook to directly inject keyboard messages into system input queue, sometimes it will work fine, and sometimes weird glitches will occur. Also, other applications may be using JournalHook for themselves, and that will mess my app badly. Not to mention that default security policies make journal hook hard to use.
  4. I've been trying to get/set text in the input fields using Windows UI automation instead of clipboard magic, but it rarely works.

So, if you know other ways to make other applications reliably use copy/paste functionality, or can even devise entirely different approach, I'd really appreciate you telling me :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

此刻的回忆 2024-10-13 08:03:41

我认为你的方法还不错,也许你可以从 WM_DRAWCLIPBOARD 开始,这样你就可以监视剪贴板。可以在此处找到一个很好的示例代码。

接下来我会看一下 SendKeys 类 - 注意:Flush、Buffer 等。使用它来发送 ctrl+c/v 而不是 Windows 消息!如果它有效,您应该会从监视器收到通知。
现在我将使用 Cliboard 类操作数据并将其粘贴回来。

I think your approach isn't that bad, maybe you can start with WM_DRAWCLIPBOARD so you can monitor the clipboard. A nice sample code can be found here.

Next I'd take a look at SendKeys class - Attention: Flush, Buffer, etc. Use this to send ctrl+c/v instead of a windows message! You should get a notification from your monitor if it worked.
Now I'd use the Cliboard class to maniplulate the Data and paste it back.

‖放下 2024-10-13 08:03:41

哦,看来我只能找到或多或少可靠的方法来调用没有 SendInput 或日志钩子的复制粘贴,但我必须处理它:-)所以这里是,以防有人发现它有用:

  1. 记住并重置通过 AttachThreadInput(yourAppThreadId, targetAppThreadId) + SetKeyboardState(keyStateWithoutKeyboardModifiers) 进行键盘修饰符。
  2. 通过 SetKeyboardState(keyStateWithControl) 将 Ctrl 键修饰符设置为 Ctrl+C/V 热键。
  3. 然后使用 C 或 V 键的 WM_KEYDOWN 消息将 PostMessage 发送到焦点控制句柄,无论您希望复制还是粘贴。
  4. 调用 Thread.CurrentThread.Join(20) 让其他应用程序处理消息 - 这是整个交易中最迟缓的时刻,因为我找不到确定的方法来知道其他应用程序何时会有空消息队列。
  5. 恢复记住的键盘修饰符。

另外,每次执行 SetKeyboardState 时,请随后调用 SetForegroundWindow(focusedControlHandle) 和 SetFocus(focusedControlHandle) 。

Oh, it seems that I could only find more or less reliable way of invoking copy-paste without SendInput or journal hook, but I have to deal with it :-) So here it is, in case someone find it useful:

  1. Remember and reset keyboard modifiers via AttachThreadInput(yourAppThreadId, targetAppThreadId) + SetKeyboardState(keyStateWithoutKeyboardModifiers).
  2. Set Ctrl key modifier via SetKeyboardState(keyStateWithControl) for Ctrl+C/V hotkey.
  3. Then PostMessage to focused control handle with WM_KEYDOWN message for C or V key, whether you want it to copy or paste.
  4. Call Thread.CurrentThread.Join(20) to let other app process messages — and that's the most retarded moment in the whole deal, since I couldn't find the sure way to know when other app will have empty message queue.
  5. Restore remembered keyboard modifiers.

Also, every time you do SetKeyboardState, call SetForegroundWindow(focusedControlHandle) and SetFocus(focusedControlHandle) afterwards.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文