Est-il possible d’écrire une application Windows qui reçoit une notification lorsque du texte est sélectionné dans une autre application Windows?

Je suis curieux de savoir s’il est possible d’écrire un programme qui surveille ma sélection de texte. Une utilisation possible serait d’écrire un éditeur de code agnostique éditeur / IDE:

  1. L’application / service, P, est lancée et se connecte d’une manière ou d’une autre à Windows de manière à être notifiée lorsque du texte est sélectionné dans n’importe quelle fenêtre.
  2. Une autre application, A, est lancée.
  3. L’utilisateur sélectionne le texte dans A.
  4. P est notifié avec le texte sélectionné.

-> Je serais ravi d’aller aussi loin …

Cela n’est pas possible sans une connaissance spécifique de chaque contrôle / application qui sera utilisé car ils peuvent tous gérer / traiter différemment.

Je ne pense pas que vous pouvez enregistrer une sorte de crochet. Je pense que vous devrez constamment interroger la fenêtre “ciblée” ou sélectionnée.

Pour ce faire, vous pouvez probablement utiliser l’API Windows Automation, qui, à ma connaissance, a dépassé l’ancienne API Accessibilité: http://msdn.microsoft.com/en-us/library/ms747327.aspx

J’ai utilisé cette API pour automatiser les tests d’interface graphique. Je suis un peu rouillé avec ça, donc je ne sais pas avec certitude, mais je suis raisonnablement convaincu que vous pourriez l’utiliser pour ce que vous essayez de faire. Fondamentalement, l’API vous permet de parcourir l’arborescence des objects d’automatisation avec la racine sur le bureau. Chaque élément d’automatisation a tendance à être un contrôle Windows quelconque et différents contrôles implémentent différents modèles. Vous pouvez également accéder aux éléments situés sous le curseur de la souris et vous pouvez éventuellement accéder directement à l’élément actuellement sélectionné / sélectionné.

Après cela, je remarque que la classe TextPattern a par exemple une méthode GetSelection () qui est documentée comme “Récupère une collection de plages de texte disjointes associées à la sélection de texte ou aux sélections en cours.” Je parie que l’object Automation pour les zones de texte implémente le TextPattern. http://msdn.microsoft.com/en-us/library/system.windows.automation.textpattern.aspx

Ce code vous aide à obtenir un texte de contrôle ciblé dans une fenêtre ciblée, j’espère que cela vous aidera:

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([InAtsortingbute] 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)] SsortingngBuilder lpSsortingng, 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 ssortingng 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 ssortingng 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 ssortingng GetText(IntPtr handle) { int maxLength = 512; IntPtr buffer = Marshal.AllocHGlobal((maxLength + 1) * 2); SendMessageW(handle, WM_GETTEXT, maxLength, buffer); ssortingng w = Marshal.PtrToSsortingngUni(buffer); Marshal.FreeHGlobal(buffer); return w; } } }