Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Отсылка комбинации клавиш в чужое окно [D7, XP]


NewBie ©   (2009-02-06 12:31:00) 

Мне необходимо поуправлять чужим приложением.
В результате гуугления из Delphi World 6 Pro выдрал вот такую процедуру:
procedure GetAllWindow;
Var
WindowHandle:HWnd;
WindowsName:string;
begin
WindowHandle:=FindWindow('TApplication',0);          // Найдем первое окно верхнего уровня любого класса
While (WindowHandle<>0) do Begin        // Если такое окно существует
 SetLength(WindowsName,100);//буфер
 GetWindowText(WindowHandle,
               pchar(WindowsName),
               Length(WindowsName));//заголовок окна
 if (Pos('Light Alloy',WindowsName)<>0) and (WindowHandle<>0) then begin
  LAHandle:=WindowHandle;//хэндл нашли
  break;//дальше искать не надо
 end;
 Application.ProcessMessages;         // Дадим возможность поработать другим
 WindowHandle:=GetNextWindow(WindowHandle,GW_HWNDNEXT);   // Найдем следующее окно в системе.
End;
end;


теперь хочу послать что-то в программу, например, эмулирую нажатие пробела:

PostMessage(LAHandle, WM_KEYDOWN, 32, 0);

Всё прекрасно работает.
Но мне надо послать комбинацию клавиш: Ctrl + -> (контрол + вправо).

Погуглив нашёл варианты ответов, но никак не допетраю что к чему и как заставить их работать:

Тут как отослать Ctrl+C консольному окну:
http://www.delphikingdom.ru/asp/answer.asp?IDAnswer=66086
но у меня GUI, вроде не наш метод.
Тут человека проглючило:
http://www.delphikingdom.ru/asp/answer.asp?IDAnswer=65752
однако дальше меня заинтересовала: keybd_event
Нашёл такое:
http://www.delphikingdom.com/asp/answer.asp?IDAnswer=48998
однако код аналогичный этому:

01: var
02:    ThreadID,my:cardinal;
03: begin
04:    ThreadID:=GetWindowThreadProcessId(GetForegroundWindow,nil);
05:    my:=GetWindowThreadProcessId(handle,nil);
06:    AttachThreadInput(ThreadID,my,true);
07:    windows.setfocus(form1.memo1.handle);
08:    keybd_event(VK_CONTROL, 0, 0, 0);
09:    keybd_event(86, 0, 0, 0);
10:    keybd_event(86, 0, KEYEVENTF_KEYUP, 0);
11:    keybd_event(VK_CONTROL, 0,KEYEVENTF_KEYUP, 0);
12:    AttachThreadInput(ThreadID,my,false);
13: end;


Строка 4 - Получаю список потоков в системе?
Строка 5 - выделяю свой поток по известному хэдлу?
Строка 6 - подключаюсь к потоку.
Строка 7 - Устанавливаю фокус. По идее вместо мемо из примера могу указать хэндл программы, к которой подключаюсь?
Строка 8 - говорю программе, что нажат Ctrl
Строка 9 - посылаю код клавиши 86 (в моём случае 4d - это получается 77 в десятичной?)
Строка 10 и Строка 11 - говорю, что клавиши отпущены.
Строка 12 - отпускаю процесс на волю

Не погу понять в чём я не прав. Спасибо за помощь заранее.


Leonid Troyanovsky   (2009-02-06 17:10:00) [1]


> NewBie   (06.02.09 12:31)  

> Но мне надо послать комбинацию клавиш: Ctrl + -> (контрол
> + вправо).

Поизучай оное приложение с помощью, например, winsight32.
Если на искомую комбинацию генерируется, скажем, WM_COMMAND,
то слать проще его, а не делать чужому окну foreground & keybd_event.

Другие же методы весьма ограничены, бо не foreground поток (окно)
никто не обяжет обрабатывать клавиатурный ввод, да и API  для
модификации очереди ввода чужого потока не предусмотрено.

--
Regards, LVT.


Leonid Troyanovsky   (2009-02-06 16:58:00) [2]


> NewBie   (06.02.09 12:31)  

> Строка 4 - Получаю список потоков в системе?

Получаем идентификатор потока, создавшего foreground окно.

> Строка 5 - выделяю свой поток по известному хэдлу?

Это строку проще написать так my := GetCurrentThreadId.

> Строка 6 - подключаюсь к потоку.

Ну, пусть так.
По-научному она attaches the input processing mechanism
of one thread to that of another thread.

> Строка 7 - Устанавливаю фокус. По идее вместо мемо из примера
> могу указать хэндл программы, к которой подключаюсь?

Здесь надо указать хендл контрола, который должен получать
клавиатурный ввод.

> Строка 9 - посылаю код клавиши 86 (в моём случае 4d - это
> получается 77 в десятичной?)

А почему 4d, если нужна VK_RIGHT $27.
И, во-ще, RTFM: msdn: Virtual-Key Codes

--
Regards, LVT.


Ru   (2009-02-06 12:46:00) [3]

17 - код Ctrl
39 - код вправо


Ru   (2009-02-06 12:44:00) [4]

Нашёл ещё такой пример:
Последовательное нажатие сначала Shift потом '/' тоже не проходит:
PostMessage(hwork,WM_KEYDOWN,(WPARAM)0x10,0x002a0001); // нажат Shift
PostMessage(hwork,WM_KEYDOWN,(WPARAM)0xbf,0x00350001); // нажат '/'
PostMessage(hwork,WM_KEYUP,(WPARAM)0xbf,0xC0350099);
PostMessage(hwork,WM_KEYUP,(WPARAM)0x10,0xC02a0001);

http://www.rsdn.ru/forum/message/302838.flat.aspx
Попробовал его переделать:


PostMessage(LAHandle,WM_KEYDOWN, 17,0); // нажат Ctrl
PostMessage(LAHandle,WM_KEYDOWN,39,0); // нажата -> (вправо)
PostMessage(LAHandle,WM_KEYUP,39,0); //отпустили вправо
PostMessage(LAHandle,WM_KEYUP,17,0); //отпустили Ctrl


Почти работает. Во всяком случае эмуляция нажатия кнопки вправо.
А как добить чтобы работала комбинация?


Наверх

Титульная страница Поиск, карта сайта Написать письмо