Я создаю небольшую утилиту в C #, которая добавляет некоторый текст в активное текстовое поле при нажатии глобальной горячей клавиши, это тип функции автозаполнения. У меня работает глобальная горячая клавиша, но теперь я не знаю, как получить текущий текст в активном текстовом поле (если активным окном является текстовое поле, которое есть.) До сих пор я пробовал использовать
а. GetForegroundWindow, а затем используя этот дескриптор, вызывая GetWindowText. Это дало мне название окна активного окна, а не содержимое текстового поля.
б. GetActiveWindow и используя этот дескриптор для вызова GetWindowText. Это не дает мне никакого текста.
Вот пример того, что я сделал
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
[ DllImport("user32.dll") ]
static extern int GetForegroundWindow();
[ DllImport("user32.dll") ]
static extern int GetWindowText(int hWnd, StringBuilder text, int count);
[DllImport("user32.dll")]
static extern int GetActiveWindow();
public static void TestA() {
int h = GetForegroundWindow();
StringBuilder b = new StringBuilder();
GetWindowText(h, b, 256);
MessageBox.Show(b.ToString());
}
public static void TestB() {
int h = GetActiveWindow();
StringBuilder b = new StringBuilder();
GetWindowText(h, b, 256);
MessageBox.Show(b.ToString());
}
Итак, есть идеи, как этого добиться?
Изменить 28.01.2009:
Итак, я узнал, как это сделать. Вот что я использовал:
using System;
using System.Text;
using System.Runtime.InteropServices;
public class Example
{
[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);
const int WM_SETTEXT = 12;
const int WM_GETTEXT = 13;
public static void Main()
{
//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);
Console.WriteLine("Text in active window was " + builder);
builder.Append(" Extra text");
//Change the text in the active window
SendMessage(focused, WM_SETTEXT, 0, builder);
Console.ReadKey();
}
}
Несколько замечаний по этому поводу. Пример ждет 5 секунд, прежде чем что-либо делать, что дает вам возможность сфокусироваться на каком-либо окне редактирования. В моем реальном приложении я использую горячую клавишу, чтобы вызвать это, но это только запутало бы этот пример. Кроме того, в производственном коде вы должны проверить возвращаемые значения вызовов win32, чтобы увидеть, были ли они успешными или нет.