Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Как при помощи Sendinput отправить текст из tEdit?

74K
15 октября 2011 года
Stawer
6 / / 10.10.2011
Здравствуйте!
Скажите пожалуйста, как в Delphi при помощи Sendinput отправить текст из tEdit любое приложение? Даже если моё приложение неактивно (хочу использовать горячие клавиши в ActionManager).
Буду очень признателен за помощь.
19K
15 октября 2011 года
Alegun
269 / / 10.09.2010
Примерно вот так (у принимающей "площадки для писанины" должон быть фокус)
Код:
procedure SendText(ds:string);
var
TI: TInput;
KI: TKeybdInput;
i: integer;
begin
TI.Itype := INPUT_KEYBOARD;
for i := 1 to Length(ds) do
begin
KI.wVk := Ord(UpCase(ds));
KI.dwFlags := 0;
TI.ki := KI;
SendInput(1, TI, SizeOf(TI));
KI.dwFlags := KEYEVENTF_KEYUP;
TI.ki := KI;
SendInput(1, TI, SizeOf(TI));
end;
end;

По данной теме УК Freeman любезно выложил вот эту прогу, очень полезно в ней покопаться. Правда SendInput работает не везде и только с английской раскладкой клавиатуры (могу и заблуждаться), так что лучше воспользоваться эмуляцией нажатий клавиш с помощью keybd_event. Процедурник получается довольно громоздким, в мессагу весь за раз не влезит, поэтому вот рабочий примерчик для D7 (будут баги - извиняйте, потому как собирал прям с ходу, на коленках:), если что не понятно, постите - объясню):
74K
15 октября 2011 года
Stawer
6 / / 10.10.2011
Да, программа Фримена работает так как надо. Но в её исходниках я не разобрался. В твоём коде откуда берется сообщение? Ведь там не указан tEdit или текстовый файл как у Фримена.
Я использовал слудующий код:
 
Код:
var
  Pos: TPoint;
  Target: HWND;
...
if not GetCursorPos(Pos) then
  RaiseLastOSError;
Target := WindowFromPoint(Pos);
if Target<>0 then
  SendMessage(Target, EM_REPLACESEL, ord(True), LPARAM(PChar(Edit1.Text)));


НО! Он не работает в браузерах и прочих программах, не считаю ICQ, блокнота и ворда.
Пробовал Sendmessage заменть на Sendinput - но не знаю как его использовать, не компилирует. Думаю идею вы поняли?
Спасибо заранее.
10
15 октября 2011 года
Freeman
3.2K / / 06.03.2004
Цитата: Alegun
Правда SendInput работает не везде и только с английской раскладкой клавиатуры (могу и заблуждаться):


Заблуждаешься. Иначе как SpecChar отправляет символы Unicode? Собственно, SendInput понадобился именно потому, что нужно вводить символы, а не просто эмулировать нажатие клавиш. Функциональность для отправки любых символов есть только в SendInput.

Цитата: Alegun
лучше воспользоваться эмуляцией нажатий клавиш с помощью keybd_event.


Как раз наоборот. SendInput пришла на замену keybd_event, которая признана устаревшей, как подсказал koodeer, и я даже написал об этом в блоге.

Как понимаю, keybd_event была признана устаревшей именно потому, что не поддерживает Unicode.

19K
15 октября 2011 года
Alegun
269 / / 10.09.2010
Цитата: Stawer
... В твоём коде откуда берется сообщение? Ведь там не указан tEdit или текстовый файл как у Фримена.

Там используется tMemo, из него сообщение и берётся (Memo1.Text), вызывай процедуру, а ей передавай любой текст(в переменную ds):

 
Код:
// используется Sendinput, её код см выше:
SendText(Edit1.Text);

//используется keybd_event, она из примера, кинь на форму tEdit и напиши так:
SendTekst(Edit1.Text);


Цитата:
Я использовал слудующий код ...НО! Он не работает в браузерах и прочих программах, не считаю ICQ, блокнота и ворда.


И не будет - у тебя в Target лежит хэндл родительского окна, а оно как правило, без полей ввода и используется как подложка, нужно ещё его чилдов искать, хотя не факт, что они найдутся, я когда-то пробовал это делать спомощью EnumChildWindows, не получилось (иногда, возможно степень вложенности была >2), пришлось изголяться по-другому: процедура SendTekst (из примера) так и делает - извращается.

74K
16 октября 2011 года
Stawer
6 / / 10.10.2011
Цитата:
// используется Sendinput, её код см выше:
SendText(Edit1.Text);



Всё работает! Но одно "НО", у меня из tEdit вставляются только английские символы. Вместо русского предложения - //// только слэш.

19K
17 октября 2011 года
Alegun
269 / / 10.09.2010
Цитата: Stawer
Всё работает! Но одно "НО", у меня из tEdit вставляются только английские символы. Вместо русского предложения - //// только слэш.



Вопрос кодировки. Смотри, как изящно енто дело обрабатывает Freeman в своей SpecChar:

Код:
procedure SimulateKeystroke(Key: WideChar); overload;
var
  Input: array[0..1] of TInput;
begin
  FillChar(Input, SizeOf(Input), 0);
  with Input[0] do
  begin
    Itype := INPUT_KEYBOARD;
    with ki do
    begin
      wScan := Word(Key);
      dwFlags := KEYEVENTF_UNICODE
    end;
  end;
  with Input[1] do
  begin
    Itype := INPUT_KEYBOARD;
    with ki do
    begin
      wScan := Word(Key);
      dwFlags := KEYEVENTF_UNICODE or KEYEVENTF_KEYUP;
    end;
  end;
  SendInput(Length(Input), Input[0], SizeOf(TInput));
end;


Только учти, эта процедура обрабатывает за раз только один символ, а не всю строку сразу, тебе потребуется организовывать цикл:

 
Код:
var i:integer;
begin
for i:=1 to Length(строка) do SimulateKeystroke(WideChar(строка));
end;

надеюсь, с этим проблем не возникнет.
74K
17 октября 2011 года
Stawer
6 / / 10.10.2011
Прошу прощения за такой вопрос, но как связать два кода
 
Код:
var i:integer;
begin
for i:=1 to Length(строка) do SimulateKeystroke(WideChar(строка));
end;


и этот:

Код:
procedure SendText(ds:string);
var
TI: TInput;
KI: TKeybdInput;
i: integer;
begin
TI.Itype := INPUT_KEYBOARD;
for i := 1 to Length(ds) do
begin
KI.wVk := Ord(UpCase(ds));
KI.dwFlags := 0;
TI.ki := KI;
SendInput(1, TI, SizeOf(TI));
KI.dwFlags := KEYEVENTF_KEYUP;
TI.ki := KI;
SendInput(1, TI, SizeOf(TI));
end;
end;


И еще, что значит "строка" в первом коде? Я заменил это слово на "Edit1.Text" вообще бред получился. Спасибо за подробные объяснения
10
17 октября 2011 года
Freeman
3.2K / / 06.03.2004
Проще всего описать ещё одну процедуру SimulateKeystroke:
 
Код:
procedure SimulateKeystroke(const Source: WideString); overload;
var
  I: Integer;
begin
  for I := 1 to Length(Source) do
    SimulateKeystroke(Source);
end;


Потом достаточно будет вызвать SimulateKeystroke(Edit1.Text), и всё должно заработать.

Программа не моя, а eCat-а, я её лишь поддерживаю. Перепишу больше чем на 50% -- будет моя.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог