Как получить выделенный текст любого приложения в приложение windows form
Это то, что я пытаюсь сделать,
когда пользователь выбирает любое слово (текст) любого запущенного приложения, дважды щелкнув мышью, конкретное выделенное слово должно быть вставлено в приложение windows, которое уже запущено.
до сих пор я реализовал логику, используя Global Keystroke
где пользователь должен вызвать CRT+ C комбинация клавиш клавиатуры для копирования выбранного слова в приложение win form.
что я хочу знать есть ли способ получить этот выбранный текст в приложение без нажатия кнопки клавиатуры?
2 ответов
после некоторого чтения я нашел способ:
- закрепите событие двойного щелчка, используя что-то вроде globalmousekeyhook.codeplex.com
- (необязательно) сохранить текущее состояние буфера обмена
- получить текущее положение мыши с
GetCursorPos
Сuser32.dll
-
сделать окна на основе позиции курсора с
WindowFromPoint
отuser32.dll
[DllImport("user32.dll")] public static extern IntPtr WindowFromPoint(Point lpPoint); [DllImport("user32.dll")] public static extern bool GetCursorPos(out Point lpPoint); public static IntPtr GetWindowUnderCursor() { Point ptCursor = new Point(); if (!(PInvoke.GetCursorPos(out ptCursor))) return IntPtr.Zero; return WindowFromPoint(ptCursor); }
отправить команду копирования с
SendMessage
формаuser32.dll
(см. Используя Библиотека User32.dll SendMessage для отправки Ключей с модификатором ALT)- Код
- (необязательно) восстановить содержимое буфера обмена, сохраненное на Шаге 2
я реализовал его этой проект, который принадлежит мне. ОК, как я могу справиться с этим, позвольте мне объяснить.
следует учитывать две основные вещи.
- как я могу получить текст внутри окна ?
- где я должен хранить его ?
Итак, ответ @jcrada содержит один хороший момент, который является вариантом 1.
шаги должны быть, под светом вышеуказанных подходов:
- добавить globalmousekeyhook из NuGet.
- зарегистрировать событие ClipboardContainsText через Usr32.dll файлы
- Регистрация правых событий для мыши
- и начать слушать
во-первых, создайте вспомогательный класс Win32, содержащий событие буфера обмена.
/// <summary>
/// This static class holds the Win32 function declarations and constants needed by
/// this sample application.
/// </summary>
internal static class Win32
{
/// <summary>
/// The WM_DRAWCLIPBOARD message notifies a clipboard viewer window that
/// the content of the clipboard has changed.
/// </summary>
internal const int WmDrawclipboard = 0x0308;
/// <summary>
/// A clipboard viewer window receives the WM_CHANGECBCHAIN message when
/// another window is removing itself from the clipboard viewer chain.
/// </summary>
internal const int WmChangecbchain = 0x030D;
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
}
Seconly, Регистрация событий мыши и буфера обмена,
public void Initialize()
{
var wih = new WindowInteropHelper(this.mainWindow);
this.hWndSource = HwndSource.FromHwnd(wih.Handle);
this.globalMouseHook = Hook.GlobalEvents();
this.mainWindow.CancellationTokenSource = new CancellationTokenSource();
var source = this.hWndSource;
if (source != null)
{
source.AddHook(this.WinProc); // start processing window messages
this.hWndNextViewer = Win32.SetClipboardViewer(source.Handle); // set this window as a viewer
}
this.SubscribeLocalevents();
this.growlNotifications.Top = SystemParameters.WorkArea.Top + this.startupConfiguration.TopOffset;
this.growlNotifications.Left = SystemParameters.WorkArea.Left + SystemParameters.WorkArea.Width - this.startupConfiguration.LeftOffset;
this.IsInitialized = true;
}
Событий Мыши;
private void SubscribeLocalevents()
{
this.globalMouseHook.MouseDoubleClick += async (o, args) => await this.MouseDoubleClicked(o, args);
this.globalMouseHook.MouseDown += async (o, args) => await this.MouseDown(o, args);
this.globalMouseHook.MouseUp += async (o, args) => await this.MouseUp(o, args);
}
private async Task MouseUp(object sender, MouseEventArgs e)
{
this.mouseSecondPoint = e.Location;
if (this.isMouseDown && !this.mouseSecondPoint.Equals(this.mouseFirstPoint))
{
await Task.Run(() =>
{
if (this.mainWindow.CancellationTokenSource.Token.IsCancellationRequested)
return;
SendKeys.SendWait("^c");
});
this.isMouseDown = false;
}
this.isMouseDown = false;
}
private async Task MouseDown(object sender, MouseEventArgs e)
{
await Task.Run(() =>
{
if (this.mainWindow.CancellationTokenSource.Token.IsCancellationRequested)
return;
this.mouseFirstPoint = e.Location;
this.isMouseDown = true;
});
}
private async Task MouseDoubleClicked(object sender, MouseEventArgs e)
{
this.isMouseDown = false;
await Task.Run(() =>
{
if (this.mainWindow.CancellationTokenSource.Token.IsCancellationRequested)
return;
SendKeys.SendWait("^c");
});
}
и последняя часть, что мы будем делать, когда поймаем,
private IntPtr WinProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case Win32.WmChangecbchain:
if (wParam == this.hWndNextViewer)
this.hWndNextViewer = lParam; //clipboard viewer chain changed, need to fix it.
else if (this.hWndNextViewer != IntPtr.Zero)
Win32.SendMessage(this.hWndNextViewer, msg, wParam, lParam); //pass the message to the next viewer.
break;
case Win32.WmDrawclipboard:
Win32.SendMessage(this.hWndNextViewer, msg, wParam, lParam); //pass the message to the next viewer //clipboard content changed
if (Clipboard.ContainsText() && !string.IsNullOrEmpty(Clipboard.GetText().Trim()))
{
Application.Current.Dispatcher.Invoke(
DispatcherPriority.Background,
(Action)
delegate
{
var currentText = Clipboard.GetText().RemoveSpecialCharacters();
if (!string.IsNullOrEmpty(currentText))
{
//In this section, we are doing something, because TEXT IS CAPTURED.
Task.Run(
async () =>
{
if (this.mainWindow.CancellationTokenSource.Token.IsCancellationRequested)
return;
await
this.WhenClipboardContainsTextEventHandler.InvokeSafelyAsync(this,
new WhenClipboardContainsTextEventArgs { CurrentString = currentText });
});
}
});
}
break;
}
return IntPtr.Zero;
}
трюк отправляет команду копирования в окно или операционную систему с другой стороны Control+C command, so SendKeys.SendWait("^c");
это делаешь.