使用C#从任何窗口捕获突出显示的文本

时间:2010-05-04 07:31:45

标签: c# forms sendmessage user32

如何使用c#从任何窗口读取突出显示/选定的文本。

我尝试了两种方法。

  1. 每当用户选择一些东西时发送“^ c”。但在这种情况下,我的剪贴板充斥着大量不必要的数据。有时它也会复制密码。
  2. 所以我将我的方法转换为第二种方法,发送消息方法。

    请参阅此示例代码

     [DllImport("user32.dll")]
        static extern int GetFocus();
    
        [DllImport("user32.dll")]
        static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
    
        [DllImport("kernel32.dll")]
        static extern uint GetCurrentThreadId();
    
        [DllImport("user32.dll")]
        static extern uint GetWindowThreadProcessId(int hWnd, int ProcessId);    
    
        [DllImport("user32.dll") ]
        static extern int GetForegroundWindow();
    
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
        static extern int SendMessage(int hWnd, int Msg, int wParam, StringBuilder lParam);     
    
       // second overload of SendMessage
    
        [DllImport("user32.dll")]
        private static extern int SendMessage(IntPtr hWnd, uint Msg, out int wParam, out int lParam);
    
        const int WM_SETTEXT = 12;
        const int WM_GETTEXT = 13;     
    
    private string PerformCopy()
        {
            try
            {
                //Wait 5 seconds to give us a chance to give focus to some edit window,
                //notepad for example
                System.Threading.Thread.Sleep(5000);
                StringBuilder builder = new StringBuilder(500);
    
                int foregroundWindowHandle = GetForegroundWindow();
                uint remoteThreadId = GetWindowThreadProcessId(foregroundWindowHandle, 0);
                uint currentThreadId = GetCurrentThreadId();
    
                //AttachTrheadInput is needed so we can get the handle of a focused window in another app
                AttachThreadInput(remoteThreadId, currentThreadId, true);
                //Get the handle of a focused window
                int focused = GetFocus();
                //Now detach since we got the focused handle
                AttachThreadInput(remoteThreadId, currentThreadId, false);
    
                //Get the text from the active window into the stringbuilder
                SendMessage(focused, WM_GETTEXT, builder.Capacity, builder);
    
                return builder.ToString();
            }
            catch (System.Exception oException)
            {
                throw oException;
            }
        }
    

    此代码在记事本中正常工作。但是,如果我尝试从另一个应用程序捕获,如Mozilla firefox或Visual Studio IDE,它不会返回文本。

    任何人都可以帮助我,我做错了吗?首先,我选择了正确的方法吗?

1 个答案:

答案 0 :(得分:3)

这是因为Firefox和Visual Studio都不使用内置的Win32控件来显示/编辑文本。

一般不可能获得“任何”所选文本的值,因为程序可以以任何方式重新实现自己版本的Win32控件看得合适,你的程序不可能期望与它们一起工作。

但是,您可以使用UI Automation API,它允许您与第三方控件的多数进行交互(至少是所有好的控件 - 例如Visual Studio和Firefox - 可能会使用UI自动化API,因为它是可访问性的要求)