是否可以编写一个windows应用程序,当在另一个窗口应用程序中选择文本时,该应用程序会收到通知

本文关键字:应用程序 选择 文本 窗口 另一个 通知 是否 windows 一个 | 更新日期: 2023-09-27 18:27:07

我很好奇是否可以编写一个程序来监控我的文本选择。一种可能的用途是编写一个编辑器/IDE不可知的代码格式化程序:

  1. 应用程序/服务P启动并以某种方式挂接到窗口,以便在任何窗口中选择文本时都会收到通知
  2. 启动了另一个应用程序A
  3. 用户选择A中的文本
  4. P会收到所选文本的通知

-->我很高兴能走到这一步。。。

是否可以编写一个windows应用程序,当在另一个窗口应用程序中选择文本时,该应用程序会收到通知

如果不了解将要使用的每个控件/应用程序,这是不可能的,因为它们都可以以不同的方式处理/处理它。

我认为您不能注册任何类型的钩子。我认为你需要不断地对"聚焦"或选定的窗口进行民意调查。

您可能可以使用Windows Automation API来实现这一点,据我所知,这超过了旧的Accelability API:http://msdn.microsoft.com/en-us/library/ms747327.aspx

我已经使用这个API来自动化GUI测试。我对它有点生疏,所以我不确定,但我有理由相信你可以将它用于你正在尝试做的事情。基本上,API允许你遍历自动化对象的树,根在桌面上。每个自动化元素往往是某种类型的窗口控件,不同的控件实现不同的模式。您还可以访问鼠标光标下的元素,也可以直接访问当前选定/聚焦的元素。

之后,我注意到例如TextPattern类有一个GetSelection()方法,它被记录为"检索与当前文本选择相关联的不相交文本范围的集合。"我打赌文本框的自动化对象实现了TextPattern。http://msdn.microsoft.com/en-us/library/system.windows.automation.textpattern.aspx

这段代码可以帮助您在聚焦窗口中获得聚焦控件文本,我希望这能有所帮助:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace TextFocusedns 
{
    public partial class TextFocusedFrm : Form
    {
        #region APIs
        [DllImport("user32.dll")]
        public static extern bool GetCursorPos(out Point pt);
        [DllImport("user32.dll", EntryPoint = "WindowFromPoint", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr WindowFromPoint(Point pt);
        [DllImport("user32.dll", EntryPoint = "SendMessageW")]
        public static extern int SendMessageW([InAttribute] System.IntPtr hWnd, int Msg, int wParam, IntPtr lParam);
        public const int WM_GETTEXT = 13;
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        internal static extern IntPtr GetForegroundWindow();
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        internal static extern IntPtr GetFocus();
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern int GetWindowThreadProcessId(int handle, out int processId);
        [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
        internal static extern int AttachThreadInput(int idAttach, int idAttachTo, bool fAttach);
        [DllImport("kernel32.dll")]
        internal static extern int GetCurrentThreadId();
        [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern int GetWindowText(IntPtr hWnd, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpString, int nMaxCount);
        #endregion
        private System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer() { Interval = 100, Enabled = true };
        public TextFocusedFrm()
        {
            InitializeComponent();
        }
        private void TextFocusedFrm_Load(object sender, EventArgs e)
        {
            timer.Tick += new EventHandler(timer_Tick);
            timer.Start();
        }
        void timer_Tick(object sender, EventArgs e)
        {
            try
            {
                MultiLineTextBox.Text = GetTextFromFocusedControl();
            }
            catch (Exception exp)
            {
                MultiLineTextBox.Text += exp.Message;
            }
        }
        //Get the text of the focused control
        private string GetTextFromFocusedControl()
        {
            try
            {
                int activeWinPtr = GetForegroundWindow().ToInt32();
                int activeThreadId = 0, processId;
                activeThreadId = GetWindowThreadProcessId(activeWinPtr, out processId);
                int currentThreadId = GetCurrentThreadId();
                if (activeThreadId != currentThreadId)
                    AttachThreadInput(activeThreadId, currentThreadId, true);
                IntPtr activeCtrlId = GetFocus();
                return GetText(activeCtrlId);
            }
            catch (Exception exp)
            {
                return exp.Message;
            }
        }
        //Get the text of the control at the mouse position
        private string GetTextFromControlAtMousePosition()
        {
            try
            {
                Point p;
                if (GetCursorPos(out p))
                {
                    IntPtr ptr = WindowFromPoint(p);
                    if (ptr != IntPtr.Zero)
                    {
                        return GetText(ptr);
                    }
                }
                return "";
            }
            catch (Exception exp)
            {
                return exp.Message;
            }
        }
        //Get the text of a control with its handle
        private string GetText(IntPtr handle)
        {
            int maxLength = 512;
            IntPtr buffer = Marshal.AllocHGlobal((maxLength + 1) * 2);
            SendMessageW(handle, WM_GETTEXT, maxLength, buffer);
            string w = Marshal.PtrToStringUni(buffer);
            Marshal.FreeHGlobal(buffer);
            return w;
        }
    }
}
相关文章: