![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как включить верхний регистр в чужом процессе ? [D7, Win2k, WinXP]
ANB © (2005-08-29 14:39:00)Чтобы напечатать строго большую или маленькую букву независимо от текущего состояния. Попробовал вот так - не помогает. :
- всегда печатает маленькими. Пробовал вместо FF - 1, никакого эффекта.
// Установим регистр
ThreadFrom := GetCurrentThreadId;
ThreadTo := GetWindowThreadProcessId(hWindow, nil);
AttachThreadInput(ThreadFrom, ThreadTo, True);
GetKeyBoardState(KeyBoardState);
KeyBoardState[VK_CAPITAL] := 0;
if (bUpper) then begin
KeyBoardState[VK_SHIFT] := $FF;
KeyBoardState[VK_LSHIFT] := $FF;
end else begin
KeyBoardState[VK_SHIFT] := $FF;
KeyBoardState[VK_LSHIFT] := $FF;
end;
SetKeyBoardState(KeyBoardState);
// Эмулируем нажатие клавиши
keybd_event(dwVK, bScanCode, dwFlags, 0);
AttachThreadInput(ThreadFrom, ThreadTo, False);
ANB (2005-09-02 16:51:00) [1]
> alpet © (02.09.05 16:20) [76]
Все замечательно работает без пауз и в нормальном регистре, если передавать WM_CHAR. Ну и язык теперь тоже нормально. Спасибо за помощь.
alpet (2005-09-02 16:20:00) [2]Весьма работоспособен и след. код. Надо только символы в верхнем регистре передавать. Паузу я обычно ставлю в 5 - хватает как правило для notepad.
d := 5;
ks [vk_shift] := ks [vk_shift] or $80;
SetKeyboardState (ks);
PostMessage (h, WM_KEYDOWN, Ord ('A'), 0);
Sleep (d);
ks [vk_shift] := ks [vk_shift] and $7F;
SetKeyboardState (ks);
Sleep (d);
PostMessage (h, WM_KEYDOWN, Ord ('Q'), 0);
Sleep (d);
Если вставить в обработчик таймера, печатае: "AqAqAqAq"
ANB (2005-09-02 16:15:00) [3]
> alpet © (02.09.05 15:49) [70]
- точно, ошибка верталась. Написал PROCESS_ALL_ACCESS и все заработало.
ANB (2005-09-02 16:01:00) [4]
> alpet © (02.09.05 15:55) [71]
- спасибо. Я еще пошаманю с паузой по твоему совету и могу выложить готовый код, может кому надо.
ANB (2005-09-02 16:00:00) [5]
> alpet © (02.09.05 15:55) [71]
- да работает уже все ! И регистр и язык и через сообщения и через эмуляцию. Немного с бубном поплясали и готово.
ANB (2005-09-02 15:59:00) [6]
> alpet © (02.09.05 15:49) [70]
- так я ее переключал. Короче, спасло вот это :
SendMessage(hWindow, WM_INPUTLANGCHANGE, $CC, KBD);
Причем KBD можно любую передавать. Главное - $CC - на языке включить и везде печататает и по русски и по английски.
alpet (2005-09-02 15:55:00) [7]По поводу регистра:
ks [VK_SHIFT] := $81;
SetKeyboardState (ks);
PostMessage (hWnd, WM_CHAR, Ord ('A'), 0);
Sleep (500);
ks [VK_SHIFT] := $00;
SetKeyboardState (ks);
PostMessage (hWnd, WM_CHAR, Ord ('b'), 0);
Sleep (500);
alpet (2005-09-02 15:49:00) [8]Перед отправкой русских букв надо действительно переключать расскладку, но можно обойтись без keybd_event:
PostMessage (hWnd, WM_INPUTLANGCHANGEREQUEST, 0, $419); // switch to ru
PostMessage (hWnd, WM_INPUTLANGCHANGEREQUEST, 0, $409); // switch to eng
Насчет WaitForInputIdle - какой результат функция возвращает? Если ошибку попробуй процесс открывать PROCESS_ALL_ACCESS.
ANB (2005-09-02 15:03:00) [9]
> alpet © (02.09.05 13:14) [66]
- не, перестало работать. Поставил Sleep обратно. Черт с ним, не критично. Пока закоментарил ожидание.
ANB (2005-09-02 14:50:00) [10]Перепроверил - первый вариант даже регистр не сохраняет.
ANB (2005-09-02 14:47:00) [11]
> alpet © (02.09.05 13:14) [66]
- клевая идея. Сейчас попробую. У меня еще одна бяка. Посылаю через WM_Char русские буквы, а приезжают крякозябры. Через keybd_event я переключаю раскладку и все работает. А здесь не хочет. Регистр сохраняется. Английские буквы тоже нормально приезжают.
Виртуальный код пытался генерить 2-мя способами :
1. dwVK := VkKeyScanEx(sKey[1], KBD); // KBD - раскладка
2. dwVK := ord(sKey[1]);
В sKey[1] лежит буква.
alpet (2005-09-02 13:14:00) [12]Попробуй обойтись без Sleep:
begin
hm := GetForegroundWindow;
ctid := GetCurrentThreadId ();
tid := GetWindowThreadProcessId (hm, pid);
if tid <> ctid then AttachThreadInput (ctid, tid, true);
hProcess := OpenProcess (SYNCHRONIZE, false, pid);
h := GetFocus;
GetKeyboardState (ks);
ks [VK_CONTROL] := $81;
SetKeyboardState (ks);
PostMessage (h, WM_KEYDOWN, VK_HOME, 0);
PostMessage (h, WM_KEYUP, VK_HOME, 0);
if hProcess <> 0 then WaitForInputIdle (hProcess, 500)
else sleep (500);
ks [VK_CONTROL] := $00;
SetKeyboardState (ks);
if tid <> ctid then AttachThreadInput (ctid, tid, false);
CloseHandle (hProcess);
end;
Для большей оптимизации hProcess можно получать при запуске программы, например если запускать magic через CreateProcess.
ANB (2005-09-02 12:29:00) [13]
> alpet © (02.09.05 11:39) [63]
- спасибо.
ANB (2005-09-02 12:04:00) [14]
> alpet © (02.09.05 11:39) [63]
- УРРРРЯЯЯЯЯ !!! Со слипами и SetKeyboardState (с атачем) все работает.
alpet (2005-09-02 11:39:00) [15][62] ANB © (02.09.05 11:12)
почти. вместо $FF надо использовать $81 или $80. При этом старший бит соответствует состоянию клавиши - нажата/не нажата, а младший - состояние в предыдущий раз (т.е. скорее используется для GetKeyboardState).
ANB (2005-09-02 11:12:00) [16]
> alpet © (02.09.05 10:25) [61]
- я его правильно пытался делать ?
alpet (2005-09-02 10:25:00) [17][59] ANB © (02.09.05 09:52)
AttachThreadInput необходим, как же без него будет работать SetKeyboardState
ANB (2005-09-02 09:54:00) [18]
> Наиль © (02.09.05 01:18) [57]
1. через keybd_event у меня и так уже все работает.
2. через PostMessage пока не получается (но твой вариант не работает - я уже писал)
3. для многих приложений работает и SendMessage
ANB (2005-09-02 09:52:00) [19]
> alpet © (01.09.05 18:25) [56]
- и будет работать без атача ?
Нажатая кнопка обозначается $80 ? 1 - не подходит ?
Наиль (2005-09-02 01:26:00) [20]Я так давно читаю эту ветку, что забыл про что спрашивается.
Похоже, что мой ответ в тему, а Ctrl+A лишнее.