Форум: "Основная";
Текущий архив: 2006.06.04;
Скачать: [xml.tar.bz2];
ВнизКак сделать окно активным и послать клавиши? Найти похожие ветки
← →
TStas © (2006-04-24 14:51) [0]Через FindWindow(nil, "Имя окна") нахожу окно и получаю на него handel.
А вот дальше... Ни Windows.SetFocus(handel) ни т.п. не помогает - окно как
было не активным, так активным и не стало.
Выход-то я нашел: почему-то через сервер сценариев все изумительно работает,
только вот мне вполне рабочий способ кажется слишком кривым, хотелось бы все
дельфями сделать, тем более, что точно так можно. Примеры скаченные с форума
почему-то тоже не работают. Послать надо Ctrl+V и Ctrl+Enter
← →
SuperBug © (2006-04-24 15:59) [1]После некоторых поисков по MSDN и прочим хэлпам удалось сконструировать следующий код, сразу хочу сказать что он не идеален,но поставленную задачу похоже решает
var Hndl:HWND;
ThrId:HWND;
begin
hndl:=FindWindow(nil,"Безымянный - Блокнот");
ThrID:=GetWindowThreadProcessId(hndl,nil);
if ThrID<>0 then
if AttachThreadInput(ThrID, GetCurrentThreadId,true) then
begin
SetActiveWindow(hndl);
ShowWindow(hndl,SW_SHOWNORMAL);
keybd_event( VK_RETURN,
13,
KEYEVENTF_EXTENDEDKEY or 0,0 );
AttachThreadInput(ThrID, GetCurrentThreadId,false);
end;
end;
единственно что, мне было лениво искать виртуальные коды для Ctrl+V и Ctrl+Enter поэтому этот примерчик делает активным окно блокнота и посылает туда просто Enter
← →
SuperBug © (2006-04-24 16:29) [2]да,сразу извинюсь, из-за невнимательного прочтения MSDN вкралась досадная ошибка: после эмуляции нажатия необходимо сразу же эмулировать и отжатие,а то такая фигня будет....
код отжатия:keybd_event( VK_RETURN,
13,
KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP,0 );
← →
SuperBug © (2006-04-24 17:20) [3]чего-то в процессе исследования данного вопроса меня взял живой интерес,поэтому доведу уж этот пост до конца :)
1.в предыдущих постах есть маленький баг,в качестве скэн-кода должео стоять не 13 а 28,эти цифры получаются с использование функции MapVirtualKey, таблицу VK легко найти в MSDN
2. Чтобы иммитировать двойное нажатие клавиш типа Ctrl+V и Ctrl+Enter надо поочередно вызвать нажатие Ctrl (VK_CONTROL,scan 29) и V($56,scan 47), а затем вызвать отжатие этих клавиш, сначала V потом Ctrl, порядок вроде без разницы, но так красивше :)))))
3.флаг KEYEVENTF_EXTENDEDKEY вроде может и неиспользваться.
Вроде все,если будут уточнения и дополнения-пишите :)))
← →
TStas © (2006-04-24 19:01) [4]Вечером попробую. Только я пробовал посылать через PostMessage коды клавиш получал очень просто: положил ApplicationEvent и смотрел, что он мне покажет при нажатиях. Так он msg.wParam возвращал 17 для Ctrl и 13 для Enter.
← →
TStas © (2006-04-24 19:22) [5]А вот в lParam какие-то длинные числа. Уж не знаю что это и учитываются ли они где
← →
SuperBug © (2006-04-24 19:39) [6]1.Что касается "каких-то длинных чисел" - то про них хорошо описано в справке по дельфи для WM_KEYDOWN как раз в пункте про lParam %)
2.те самые 13 для Enter и 17 для Ctrl - это и есть виртуальные коды клавиш, их помимо MSDN можно найти и в файле Windows.pas
3.а вот насчет посылки кодов через PostMessage меня гложут определенные сомнения,будут ли отрабатываться посланные нажатия совместно или по очереди....что-то мучают предположения,что второе ближе к истине
← →
TStas © (2006-04-25 17:45) [7]Так 17 и 13 вещи известные, просто у тебя указаны были другие числа, что меня и удивило
← →
SuperBUG © (2006-04-25 17:52) [8]ну так есть же заразница виртуал-кей и скан-код....
← →
TStas © (2006-04-25 23:38) [9]Чего-то с посылкой клавиш не получается. Мне кажется, надо послать нажатие CTrl, потом V, Enter и отпускание Ctrl. PostMessage почему-то не срабатывает, а код
keybd_event( VK_RETURN,
13,
KEYEVENTF_EXTENDEDKEY or 0,0 ); я не понял. Enter при этом посылается, но вот как послать сочетание. Если можно, поподробнее.
И еще, не нужно ли вставлять задержку, все-таки это аська, пробами в скрипте я подобрал 2000 мс. Проверял пока код на блокнотике. Окно активным делается и строка переводится.
← →
TStas © (2006-04-26 00:56) [10]С посылкой клавиш все получилось, только во что странно: ни Activate, ни Show, ни SetFocus ни даже SetActiveWindow(handle);
ShowWindow(handle,SW_SHOWNORMAL); не возвращают фокус моей программе, почему - непонятно. Скрипт возвращал.
← →
Царев Евгений © (2006-04-26 08:31) [11]
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
{****************************PostKeyEx32**************************************** **********}
procedure PostKeyEx32(Key: Word; const Shift: TShiftState; SpecialKey: Boolean);
{************************************************************
* Procedure PostKeyEx32
*
* Parameters:
* key : virtual keycode of the key to send. For printable
* keys this is simply the ANSI code (Ord(character)).
* shift : state of the modifier keys. This is a set, so you
* can set several of these keys (shift, control, alt,
* mouse buttons) in tandem. The TShiftState type is
* declared in the Classes Unit.
* specialkey: normally this should be False. Set it to True to
* specify a key on the numeric keypad, for example.
* Description:
* Uses keybd_event to manufacture a series of key events matching
* the passed parameters. The events go to the control with focus.
* Note that for characters key is always the upper-case version of
* the character. Sending without any modifier keys will result in
* a lower-case character, sending it with [ssShift] will result
* in an upper-case character!
*Created: 17.7.98 by P. Below
************************************************************}
type
TShiftKeyInfo = record
Shift: Byte;
Vkey : Byte;
end;
ByteSet = set of 0..7;
const
ShiftKeys: array [1..3] of TShiftKeyInfo =
((Shift: Ord(ssCtrl); Vkey: VK_CONTROL),
(Shift: Ord(ssShift); Vkey: VK_SHIFT),
(Shift: Ord(ssAlt); Vkey: VK_MENU));
var
Flag: DWORD;
bShift: ByteSet absolute Shift;
I: Integer;
begin
for I := 1 to 3 do begin
if ShiftKeys[I].Shift In bShift Then
keybd_event(ShiftKeys[I].Vkey,MapVirtualKey(ShiftKeys[I].Vkey,0),0,0);
end;
if SpecialKey then
Flag := KEYEVENTF_EXTENDEDKEY
else
Flag := 0;
keybd_event(Key,MapvirtualKey(Key,0),Flag,0);
Flag := Flag or KEYEVENTF_KEYUP;
keybd_event(Key, MapvirtualKey(Key,0),Flag,0);
for i := 3 downto 1 do begin
if ShiftKeys[I].Shift In bShift then
keybd_event(ShiftKeys[I].Vkey,MapVirtualKey(ShiftKeys[I].Vkey,0),KEYEVENTF_KEYUP ,0);
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var h:THandle;
begin
H := FindWindow("Notepad",nil);
if H > 0 then
if SetForegroundWindow(H) then
begin
// Извиняюсь что не Ord но что то с функцией(ORD) не получается на XP, в 2k все работало
PostKeyEx32(65,[ssShift],False);// A
PostKeyEx32(66,[],False);// b
PostKeyEx32(67,[],False);// c
PostKeyEx32(VK_RETURN,[],False);// Enter
PostKeyEx32(VK_F4,[ssAlt],False); // Закрываем блокнот Alt+F4
Sleep(5000); // ждем 5 секунд "Сохранять не сохранять" :)
//Application.Restore;// Если свернуто
SetForegroundWindow(Handle);// Активизируем форму
end;
end;
end.
← →
ANB © (2006-04-26 09:58) [12]Добавлю от себя имхо.
Иммитация нажатий через keybd_event работает неустойчиво.
SetForegroundWindow MS постоянно подрезает, то что работало в 98, не факт, что отработает в XP. Плюс любой случайный клик мышкой может все сломать.
Намного надежнее работает способ через сообщения (WM_KEYDOWN, WM_CHAR, WM_KEYUP). Причем можно не заботится о раскладке и регистре.
← →
Cash © (2006-04-26 13:26) [13]ANB © (26.04.06 09:58) [12]:
А чему должен быть равен LParam для этих сообщений?
(для: WM_KEYDOWN, WM_CHAR, WM_KEYUP).
← →
SuperBUG © (2006-04-26 16:24) [14]TStas © ,
а где ты сказал что фокус обратно должен вернуться????
Что касается предложенной <Царев Евгений © > функцией SetForegroundWindow,то все очень здорово работает,если только приложение ,которому все засылается не свернуто,иначе все теряется,т.е. первый вывод-если приложение свернуто-неплохо бы его в таком вырианте развернуть!!! А вот для возвращения фокуса своему приложению действительно неплохо подходит.
← →
TStas © (2006-04-26 19:30) [15]Все теперь хорошо работает, прямо сейчас пользуюсь.
>ANB PostMessage пробовал, в lParam писал 0 совсем не работало
← →
Acidlex (2006-04-27 13:47) [16]Когда то у меня была подобная задача, но
мне надо было посылать комбинации клавиш без активизации окна.
К сожалению я ее не решил, может кто нибуть поможет :)
Плюс ко всему, некоторые программы, кроме обработки сообщения, сканируют клавиатуру на нажатие клавиш.
был пример через JournalPlaybackProc (точно непомню), но работал с глюками :( , а сам я неразобрался.
← →
TStas © (2006-04-27 14:53) [17]>Acidlex А разьве можно посылать комбинацию клавишь в неактивное окно?
← →
Leonid Troyanovsky © (2006-04-28 02:11) [18]
> TStas © (27.04.06 14:53) [17]
> >Acidlex А разьве можно посылать комбинацию клавишь в неактивное
> окно?
Скорее всего, в общем случае, корректно сделать это не удастся.
Рассмотрим другой пример by Peter Below
http://groups.google.com/group/borland.public.delphi.nativeapi/msg/69c29080f4913c2b
И попробуем применить его к блокноту, посылая нажатие Сtrl+V,
т.е., вставка из буфера.
На моей w2k вставка происходит лишь так:
procedure TForm1.Button1Click(Sender: TObject);
var
tid: DWORD;
h: HWND;
begin
tid := GetWindowThreadProcessID(h, nil);
h := FindWindow("Notepad", nil);
h := FindWindowEx(h, 0, "EDIT", nil);
AttachThreadInput(GetCurrentThreadId, tid, True);
Windows.SetFocus(h); // необходимо передать фокус Блокноту
PostKeyEx(h, Ord("V"), [ssCtrl], false);
Windows.SetFocus(Handle);
AttachThreadInput(GetCurrentThreadId, tid, false);
end;
если, кроме того,
PostMessage( hWindow, WM_KEYUP, key, lparam or $C0000000);
заменить на
SendMessage( hWindow, WM_KEYUP, key, lparam or $C0000000);
(Вместо Application.ProcessMessages использован Sleep(100))
Понятно, что в данном конкретном случае добиться желаемого
можно было б проще, послав окну WM_CHAR ^C, или WM_PASTE,
но, комбинация клавиш выглядит именно так.
Т.е., из-за того, что фокус, все равно, необходимо переместить
на целевое окно, способ с посылкой сообщений никаких
преимуществ по сравнению с keybd_event не имеет.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2006-04-28 02:14) [19]
> Leonid Troyanovsky © (28.04.06 02:11) [18]
> tid := GetWindowThreadProcessID(h, nil);
..
> h := FindWindowEx(h, 0, "EDIT", nil);
Имелось ввиду
h := FindWindowEx(h, 0, "EDIT", nil);
tid := GetWindowThreadProcessID(h, nil);
Sorry.
--
Regards, LVT.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.06.04;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.058 c