Подскажите, пожалуйста, как научить программу отлавливать факт нажатия кнопок клавиатуры в окне другого приложения?
В общем нужно что-то типа клавиатурного шпиона написать...
// Получаем хэндл активного приложенияВозможно, .NET позволяет сделать это же самое и проще...
HWND hWnd = ::GetForegroundWindow();
DWORD myProcessId, otherProcessId;
DWORD otherThread=::GetWindowThreadProcessId(hWnd, &otherProcessId);
DWORD myThread = ::GetWindowThreadProcessId(mуWnd, &myProcessId);
// Подключаемся к другому потоку
::AttachThreadInput(myThread, otherThread, true);
// Получаем в его контексте дочернее окно с фокусом, обрабатываем его как нужно
HWND hWndOfFocused = ::GetFocus();
// И отсоединяемся от чужого процесса
::AttachThreadInput(myThread, otherThread, false);
winH = GetForegroundWindow();
int otherThread = GetWindowThreadProcessId(winH, out otherProcessId);
int myThread = GetWindowThreadProcessId(this.Handle, out myProcessId);
AttachThreadInput(myThread, otherThread, true);
IntPtr n = GetFocus();
for (int i = 0; i < buf.Count; i++)
SendKeys.Send("{BACKSPACE}");
LoadKeyboardLayout(LANG_EN_US, KLF_ACTIVATE);
foreach (int i in buf)
SendKeys.Send(abc[1, i - 'а']);
LoadKeyboardLayout(LANG_Ru_RU, KLF_ACTIVATE);
SendMessage(txtbox, WM_SETFOCUS, nul, nul);
SendMessage(txtbox, WM_KEYDOWN, (IntPtr) 'х', nul);
SendMessage(txtbox, WM_CHAR, (IntPtr) 'х', nul);
SendMessage(txtbox, WM_KEYUP, (IntPtr) 'х', nul);
txtbox = FindWindowEx(winH, IntPtr.Zero, "Edit", null);
::SendMessage(hWndOfFocused, WM_SETTEXT, 0,(long int)"Just a test\0");, приводит к появлению этого текста в чужом приложении... НО!!! Не везде, естественно. Универсального способа нет и вряд ли он будет, потому что это сработает только тогда, когда контрол является оконным, то есть, если у него вообще есть HWND. А если нет? А если чужое приложение рисует на канве (как это делал ICQ, например, в форме быстрого ответа. Не знаю, может сейчас уже изменили, и там тоже используются оконные компоненты?), что тогда делать будешь?
void getActControl(IntPtr myWnd), ни в случае активного NotePad-а, ни в случае активного Word-а не получаю нулей в myFocused...
{
while(myWnd != IntPtr.Zero)
{
uint otherPID = 0;
uint otherTID = NativeMethods.GetWindowThreadProcessId(myWnd, out otherPID);
NativeMethods.AttachThreadInput(NativeMethods.GetCurrentThreadId(), otherTID, true);
IntPtr myFocused = NativeMethods.GetFocus();
NativeMethods.AttachThreadInput(NativeMethods.GetCurrentThreadId(), otherTID, false);
st += "Handle = " + myWnd.ToString() + " (Focused: " + myFocused.ToString() + ") \n";
getActControl(NativeMethods.GetWindow(myWnd, 5)); // 5 = GW_CHILD
myWnd = NativeMethods.GetWindow(myWnd, 2); // 2 = GW_HWNDNEXT
}
}
// Вызываю так:
string st = "";
IntPtr actWin = NativeMethods.GetForegroundWindow();
st += "** Handle: " + actWin.ToString() + "\n";
getActControl(NativeMethods.GetWindow(actWin, 5)); // 5 = GW_CHILD
foreach(string ss in st.Split('\n')) {
listBox1.Items.Add(ss);
}