我如何在 C# 中模拟 CTRL+C

发布于 2024-08-14 15:51:45 字数 2195 浏览 3 评论 0原文

我有以下代码,在记事本中运行良好,但在 WORD 中运行不佳!

 [DllImport("user32.dll")]
 public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

 [DllImport("user32.dll")]
 public static extern IntPtr GetForegroundWindow();

 [DllImport("user32.dll", SetLastError = true)]
 public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

 [DllImport("kernel32.dll")]
 public static extern uint GetCurrentThreadId();

 [DllImport("user32.dll")]
 public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

 [DllImport("user32.dll")]
 public static extern IntPtr GetFocus();

 [DllImport("user32.dll")]
 public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);

 // second overload of SendMessage
 [DllImport("user32.dll")]
 public static extern int SendMessage(IntPtr hWnd, uint Msg, out int wParam, out int lParam);

 [DllImport("user32.dll")]
 public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);

 public const uint WM_GETTEXT = 0x0D;
 public const uint WM_GETTEXTLENGTH = 0x0E;
 public const uint EM_GETSEL = 0xB0;

        IntPtr hWnd = WinUser.GetForegroundWindow();
        uint processId;
        uint activeThreadId = WinUser.GetWindowThreadProcessId(hWnd, out processId);
        uint currentThreadId = WinUser.GetCurrentThreadId();

        WinUser.AttachThreadInput(activeThreadId, currentThreadId, true);
        IntPtr focusedHandle = WinUser.GetFocus();
        WinUser.AttachThreadInput(activeThreadId, currentThreadId, false);

        int len = WinUser.SendMessage(focusedHandle, WinUser.WM_GETTEXTLENGTH, 0, null);
        StringBuilder sb = new StringBuilder(len);
        int numChars = WinUser.SendMessage(focusedHandle, WinUser.WM_GETTEXT, len + 1, sb);

        int start, next;
        string selectedText = "";
        WinUser.SendMessage(focusedHandle, WinUser.EM_GETSEL, out start, out next);
        try
        {
            selectedText = sb.ToString().Substring(start, next - start);
        }

不幸的是,当选择 WORD 或任何“richtextbox”中的文本时,上面会返回“{Microsoft Word Document}”。 CTRL+C 是怎么做到的?

注意:这在记事本或任何简单的文本编辑器中都可以正常工作。

I have the following code which works fine in notepad but not in WORD!!

 [DllImport("user32.dll")]
 public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

 [DllImport("user32.dll")]
 public static extern IntPtr GetForegroundWindow();

 [DllImport("user32.dll", SetLastError = true)]
 public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);

 [DllImport("kernel32.dll")]
 public static extern uint GetCurrentThreadId();

 [DllImport("user32.dll")]
 public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

 [DllImport("user32.dll")]
 public static extern IntPtr GetFocus();

 [DllImport("user32.dll")]
 public static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, StringBuilder lParam);

 // second overload of SendMessage
 [DllImport("user32.dll")]
 public static extern int SendMessage(IntPtr hWnd, uint Msg, out int wParam, out int lParam);

 [DllImport("user32.dll")]
 public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count);

 public const uint WM_GETTEXT = 0x0D;
 public const uint WM_GETTEXTLENGTH = 0x0E;
 public const uint EM_GETSEL = 0xB0;

        IntPtr hWnd = WinUser.GetForegroundWindow();
        uint processId;
        uint activeThreadId = WinUser.GetWindowThreadProcessId(hWnd, out processId);
        uint currentThreadId = WinUser.GetCurrentThreadId();

        WinUser.AttachThreadInput(activeThreadId, currentThreadId, true);
        IntPtr focusedHandle = WinUser.GetFocus();
        WinUser.AttachThreadInput(activeThreadId, currentThreadId, false);

        int len = WinUser.SendMessage(focusedHandle, WinUser.WM_GETTEXTLENGTH, 0, null);
        StringBuilder sb = new StringBuilder(len);
        int numChars = WinUser.SendMessage(focusedHandle, WinUser.WM_GETTEXT, len + 1, sb);

        int start, next;
        string selectedText = "";
        WinUser.SendMessage(focusedHandle, WinUser.EM_GETSEL, out start, out next);
        try
        {
            selectedText = sb.ToString().Substring(start, next - start);
        }

unfortunately the above returns "{Microsoft Word Document}" when selecting a text in WORD or any "richtextbox".
How does CTRL+C do it?

NOTE: This works fine in notepad or on any simple text editor.

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

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

发布评论

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

评论(3

☆獨立☆ 2024-08-21 15:51:46

我非常确定 Word 不会响应 EM_ 消息。这些消息特定于 Windows 编辑控件;碰巧记事本对其文本使用了普通的编辑控件。

您也许能够使用 Word COM 自动化界面来实现您想要的目标。没有 100% 保证可以从其他应用程序检索文本的方法。

编辑:我不是这方面的专家,但您可能会通过辅助功能 API 取得更大的成功。应用程序(例如记事本或 Word)可以公开一组代表其 UI 的对象,您可以从应用程序中查询这些对象。

I'm pretty sure Word is not going to respond to EM_ messages. These messages are specific to Windows edit controls; it just to happens that Notepad uses a plain edit control for its text.

You might be able to achieve what you want using the Word COM automation interfaces. There's no 100% guaranteed means to retrieve text from another application.

Edit: I'm no expert on this, but you might have more success with the accessibility APIs. It's possible for an app (such as Notepad or Word) to expose a set of objects representing its UI that you can query from your app.

土豪 2024-08-21 15:51:45

我认为你应该看看这个教程 C# 剪贴板复制和粘贴。在 C# 中使用复制粘贴实际上并不像您想象的那么难。

复制

Clipboard.SetText(txtClipboard.Text);

粘贴

txtClipboard.Text = Clipboard.GetText();

查看上述链接以获取更多信息和示例。您还应该查看 MSDN 页面对于剪贴板

I think you should look into this tutorial on C# Clipboard Copy and Pasting. Using Copy paste in C# is not actualy as hard as you might think.

Copy

Clipboard.SetText(txtClipboard.Text);

Paste

txtClipboard.Text = Clipboard.GetText();

Check the Above link for more information and examples. You should also look at the MSDN page for Clipboard.

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