Форум программистов, компьютерный форум, киберфорум
Наши страницы

Lazarus

Войти
Регистрация
Восстановить пароль
 
 
Andrew Puchinin
2 / 3 / 1
Регистрация: 25.04.2016
Сообщений: 96
#1

Считать нажатый символ в фоновом режиме - Lazarus

14.06.2016, 17:40. Просмотров 607. Ответов 18
Метки нет (Все метки)

Здравствуйте.
Читал что-то про ловушки в Delphi, мало, что понял. Можете написать код программы с помощью ловушек, которая, скажем, повторяет нажатый символ. То есть я запускаю программу, оставляю её работать где-то позади, сам открываю блокнот, нажимаю 'а', и в блокноте возникает две буквы а. Нажимаю б - две буквы б.
И объясните, пожалуйста, заодно, как вообще с этими ловушками работать.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.06.2016, 17:40
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Считать нажатый символ в фоновом режиме (Lazarus):

Программа в фоновом режиме - Delphi
Программисты, прошу помощи!! Дали вот такое задание: Создайте приложение, которое в фоновом режиме создает в указанной пользователем...

Программа в фоновом режиме - C++
банальный пример - вирус который висит в процесах и творит какие-то дела. как делаются такие проги? не вирусы)), а не консольные ...

Работа в фоновом режиме - PHP
Сразу извиняюсь за название темы и раздел. Я не знал, где эту тему создать и как её назвать. Вопрос прозвучит не только о PHP, а вообще про...

Съёмка в фоновом режиме - Программирование Android
Как получить картинку с камеры в фоновом режиме (без Surface)? Неважно, на Java или в native, главное, чтобы это работало на старых...

Работа в фоновом режиме - C# WPF
Приветствую всех. Вопрос следующий. Как сделать так, чтобы работа выполняла работу в фоновом режиме? Т.е если к примеру при не свернутом...

Работа в Фоновом режиме! - Delphi
Хочу написать таймер для отключения компьютера(после включения сворачивается в трей)... проблема в том что после сворачивания в трей...

18
Joey
Модератор
826 / 548 / 147
Регистрация: 05.05.2015
Сообщений: 3,181
Записей в блоге: 1
15.06.2016, 13:23 #2
Andrew Puchinin, есть такая функция WinAPI RegisterHotKey, она регистрирует любую клавишу в системе так, чтобы при нажатии этой клавиши твоя программа была уведомлена. Все, что я могу предложить по твоей задаче - это зарегестрировать таким образом все клавиши на клавиатуре

Добавлено через 2 минуты
И при нажатии той или иной клавиши посылать активному окну (GetForeGroundWindow https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx - получить активное окно, SendMessage http://www.vsokovikov.narod.ru/New_M...endmessage.htm - послать сообщение этому окну, в твоем случае - WM_KeyDown - https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx)
1
Andrew Puchinin
2 / 3 / 1
Регистрация: 25.04.2016
Сообщений: 96
17.06.2016, 13:45  [ТС] #3
Joey, правильно ли я понял, что RegisterHotKey определяет только комбинацию клавиш, которая начинается с вспомогательных клавиш, вроде Alt, Ctrl и т.д. ?

Добавлено через 4 минуты
третий параметр fsModifiers принимает значения, указывая на нажатие этих клавиш. Может можно приравнять его nill...
0
Joey
Модератор
826 / 548 / 147
Регистрация: 05.05.2015
Сообщений: 3,181
Записей в блоге: 1
17.06.2016, 14:03 #4
Andrew Puchinin, просто не посылаете ни одного модифаера, передаете []
0
Andrew Puchinin
2 / 3 / 1
Регистрация: 25.04.2016
Сообщений: 96
17.06.2016, 15:31  [ТС] #5
Спасибо, и еще вопрос: второй параметр RegisterHotKey - идентификатор - указано, что, чтобы избежать конфликта с уже существующими идентификаторами, нужно использовать функцию GlobalAddAtom. Что мне нужно передать туда в параметрах, чтобы получить правильный уникальный id?

Добавлено через 15 минут
и кстати, попробовал, на [] ругается: Incompatible type for arg no. 3: Got "Array Of Const", expected "LongWord"

Добавлено через 9 минут
Можно я для простоты задачи попрошу написать строку обработки одного символа? У меня выходит так:

Delphi
1
2
3
4
5
6
7
8
9
10
var
  Wind: THandle;
  a_pressed: boolean;
 
begin
  Wind:=GetForeGroundWindow();
  a_pressed:=RegisterHotKey(Wind,GlobalAddAtom(<smth>),<smth>,ord('a'));
  if (a_pressed=true) then
    ...
end.
И, собственно, вопрос, что должно быть на месте двух пропусков. Во втором случае, на сколько я понимаю, надо как-то создать пустую переменную типа LongWord.
0
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
25533 / 17086 / 5416
Регистрация: 22.10.2011
Сообщений: 30,252
Записей в блоге: 6
17.06.2016, 18:37 #6
Цитата Сообщение от Andrew Puchinin Посмотреть сообщение
на [] ругается
Разумеется. Если нет модификаторов - надо передавать не пустое множество, и не пустой константный массив, а просто 0.
Цитата Сообщение от Andrew Puchinin Посмотреть сообщение
что должно быть на месте двух пропусков
На месте второго - 0, как уже написано выше. А на месте первого - название атома (строка), но нужно запомнить, что вернет GlobalAddAtom, чтобы потом нормально удалить горячую клавишу через UnRegisterHotKey. И не забыть удалить сам атом через GlobalDeleteAtom...
0
Andrew Puchinin
2 / 3 / 1
Регистрация: 25.04.2016
Сообщений: 96
17.06.2016, 19:36  [ТС] #7
Я чего-то не так делаю... Пытаюсь продебажить, a_pressed всегда равно false:

Delphi
1
2
id:=GlobalAddAtom('a');
a_pressed:=RegisterHotKey(Wind,id,0,ord('a'));
А GlobalDeleteAtom ругается на то, что передаваемый параметр не типа Word. Как GlobalAddAtom и GlobalDeleteAtom могут принимать параметры разных типов?..
0
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
25533 / 17086 / 5416
Регистрация: 22.10.2011
Сообщений: 30,252
Записей в блоге: 6
17.06.2016, 22:57 #8
Цитата Сообщение от Andrew Puchinin Посмотреть сообщение
a_pressed всегда равно false:
Чтобы найти причину:
If the function fails, the return value is zero. To get extended error information, call GetLastError.
А вообще:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// класс формы:
  TForm1 = class(TForm)
    // ...
  private
  public
    id : ATOM; // Вот с такими описаниями
    a_pressed : BOOL;
  end; 
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  id:=GlobalAddAtom('MyAtom');
  a_pressed:=RegisterHotKey(Handle,id,0,ord('a')); // все нормально создается, a_pressed = true
end;
 
procedure TForm1.FormDestroy(Sender: TObject);
begin
  UnRegisterHotKey(Handle, id);
  GlobalDeleteAtom(id);
end;
0
Andrew Puchinin
2 / 3 / 1
Регистрация: 25.04.2016
Сообщений: 96
18.06.2016, 00:36  [ТС] #9
Создал. Запустилось. Но, простите пожалуйста... почему a_pressed теперь всегда равно true? Можно еще раз насчет изначальной задачи - нужно отловить нажатие на символ вне программы, т.е. a_pressed должно быть равно true только в том случае, когда нажался символ где-либо в системе. volvo, В Вашей программе a_pressed действительно всегда равно true, или это я опять чего-то не понимаю?.. Если всегда, то еще раз вопрос - как этот код изменить так, чтобы отлавливать нажатие на символ?
P.s.: я поставил на форму таймер, чтобы программа не завершалась сразу после первого ввода.
0
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
25533 / 17086 / 5416
Регистрация: 22.10.2011
Сообщений: 30,252
Записей в блоге: 6
18.06.2016, 00:42 #10
Цитата Сообщение от Andrew Puchinin Посмотреть сообщение
a_pressed должно быть равно true только в том случае, когда нажался символ где-либо в системе
a_pressed - это признак успешности/неуспешности установки горячей клавиши. А чтобы сами нажатия таких клавиш ловить - нужно ловить сообщение WM_HOTKEY, и там отлавливать только те, у которых WPARAM = id. Это и будут нажатые "а" без модификатора. И вот тогда уже делать с ними, что нужно, отсылать еще одно нажатие в активное окно, или еще чего.
0
Andrew Puchinin
2 / 3 / 1
Регистрация: 25.04.2016
Сообщений: 96
18.06.2016, 13:59  [ТС] #11
У меня заработали вспомогательные клавиши и цифры. Работать не хотят почему-то только буквы. Вот код:

Delphi
1
2
3
4
5
6
7
procedure TForm1.FormCreate(Sender: TObject);
begin
  id1:=GlobalAddAtom('SPACE');
  RegisterHotKey(Handle,id1,0,VK_SPACE);
  id2:=GlobalAddAtom('A');
  RegisterHotKey(Handle,id2,0,ord('A'));
end;
Delphi
1
2
3
4
5
6
7
procedure TForm1.WMHotKey(var Mes: TMessage);
begin
  if (Mes.WParam=id1) then
    Edit1.Text:=Edit1.Text+' 1';
  if (Mes.WParam=id2) then
    Edit2.Text:=Edit2.Text+' 2';
end;
Delphi
1
2
3
4
5
6
7
Procedure TForm1.FormDestroy(Sender: TObject);
begin
  UnRegisterHotKey(Handle,id1);
  UnRegisterHotKey(Handle,id2);
  GlobalDeleteAtom(id1);
  GlobalDeleteAtom(id2);
end;
В случае SPACE все замечательно работает, в случае с A - нет.

Добавлено через 17 минут
Только, если вводить пробел в другой программе, он в ней не печатается и только выводит единички на форму
0
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
25533 / 17086 / 5416
Регистрация: 22.10.2011
Сообщений: 30,252
Записей в блоге: 6
18.06.2016, 16:25 #12
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Может тебе все-таки хуками воспользоваться?
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
uses ..., JwaWinUser;
 
function LLKeyProc(nCode: integer; wp: WPARAM; lp: LPARAM): LRESULT; stdcall;
var
  vk: DWORD;
begin
  if nCode = HC_ACTION then
  begin
    vk := LPKBDLLHOOKSTRUCT(lp)^.vkCode;
    if wParam = WM_KEYDOWN then
      case vk of
        VK_A:
          Form1.Edit2.Text := Form1.Edit2.Text + ' 2';
        VK_SPACE:
          Form1.Edit1.Text := Form1.Edit1.Text + ' 1';
      end;
  end;
  Result := CallNextHookEx(0, nCode, wp, lp);
end;
 
var
  hook: HHOOK;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  hook := SetWindowsHookEx(WH_KEYBOARD_LL, @LLKeyProc, GetModuleHandle(nil), 0);
end;
 
procedure TForm1.FormDestroy(Sender: TObject);
begin
  UnhookWindowsHookEx(hook);
end;
прекрасно ловит нажатия...
2
Andrew Puchinin
2 / 3 / 1
Регистрация: 25.04.2016
Сообщений: 96
18.06.2016, 21:43  [ТС] #13
Да, спасибо, работает. Только не реагирует на строчные символы, но я его в этом уже победил. Правда, думаю, немного через пятую точку:

Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
var
  hook, hook2: HHOOK;
  Caps: boolean;
 
function CapsLLKeyProc(nCode: integer; wp: WPARAM; lp: LPARAM): LRESULT; stdcall;
var
  vk: DWORD;
  Window: THandle;
begin
  Caps:=true;
  Window:=GetForeGroundWindow();
  if nCode = HC_ACTION then
    begin
      vk := LPKBDLLHOOKSTRUCT(lp)^.vkCode;
      if (wp = WM_KEYDOWN) then
        begin
          case vk of
            ord('A'):
              Form1.Edit2.Text := Form1.Edit2.Text + ' A2';
          end;
        end;
    end;
  Result := CallNextHookEx(0, nCode, wp, lp);
  UnhookWindowsHookEx(hook2);
end;
 
function LLKeyProc(nCode: integer; wp: WPARAM; lp: LPARAM): LRESULT; stdcall;
var
  vk: DWORD;
  Window: THandle;
begin
  Window:=GetForeGroundWindow();
  if nCode = HC_ACTION then
  begin
    vk := LPKBDLLHOOKSTRUCT(lp)^.vkCode;
    if (wp = WM_KEYDOWN) then
      begin
        case vk of
          ord('A'):
            if (Caps=false) then
              Form1.Edit2.Text := Form1.Edit2.Text + ' a2';
          160:
            begin
              hook2:=SetWindowsHookEx(WH_KEYBOARD_LL,@CapsLLKeyProc,
                                      GetModuleHandle(nil), 0);
            end;
        end;
      end;
  end;
  if (Caps=true) then
    Caps:=false;
  Result := CallNextHookEx(0, nCode, wp, lp);
end;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  Caps:=false;
  hook := SetWindowsHookEx(WH_KEYBOARD_LL, @LLKeyProc,
                           GetModuleHandle(nil), 0);
end;
 
Procedure TForm1.FormDestroy(Sender: TObject);
begin
   UnhookWindowsHookEx(hook);
end;
И кстати, кажется не

Delphi
1
if wParam = WM_KEYDOWN then
а

Delphi
1
if wp = WM_KEYDOWN then
volvo, можно еще один глупый вопрос? Если коротко, как послать сообщение открытому окну о том, что нажата клавиша?

Цитата Сообщение от Joey Посмотреть сообщение
Andrew Puchinin, есть такая функция WinAPI RegisterHotKey, она регистрирует любую клавишу в системе так, чтобы при нажатии этой клавиши твоя программа была уведомлена. Все, что я могу предложить по твоей задаче - это зарегестрировать таким образом все клавиши на клавиатуре
Добавлено через 2 минуты
И при нажатии той или иной клавиши посылать активному окну (GetForeGroundWindow https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx - получить активное окно, SendMessage http://www.vsokovikov.narod.ru/New_M...endmessage.htm - послать сообщение этому окну, в твоем случае - WM_KeyDown - https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx)
Можно пояснить для особо одаренных?
1
volvo
Супер-модератор
Эксперт Pascal/DelphiАвтор FAQ
25533 / 17086 / 5416
Регистрация: 22.10.2011
Сообщений: 30,252
Записей в блоге: 6
18.06.2016, 21:55 #14
Цитата Сообщение от Andrew Puchinin Посмотреть сообщение
как послать сообщение открытому окну о том, что нажата клавиша?
Зачем? Открытое окно готово получить это сообщение? При использовании хука ничего никому посылать не нужно, окно и так получит нажатие клавиши. Ну, а если нужно выслать какое-то сообщение, которое это окно умеет обрабатывать - то выше уже было написано: получить хендл активного окна через GetForegroundWindow и выслать ему сообщение через SendMessage, в чем проблема?
0
Joey
Модератор
826 / 548 / 147
Регистрация: 05.05.2015
Сообщений: 3,181
Записей в блоге: 1
18.06.2016, 22:01 #15
Andrew Puchinin, Функция SendMessage.
А в одном комментарии на форуме этого не объяснишь, WinAPI - очень сложная штука (по крайней мере, для новичка точно)
0
18.06.2016, 22:01
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.06.2016, 22:01
Привет! Вот еще темы с ответами:

Приложения в фоновом режиме - Windows 8, 8.1
Народ вот в чем проблема заключается 8ка отключает автоматически приложения когда переключаешся между ними, к примеру если в ie играет...

Скриншот в фоновом режиме - Программирование Android
Цель - создание приложения, работающего в фоне и делающего снимок всего экрана с любой текущей активной задачей пользователя, а не моего...

СистемнаяИнформация в фоновом режиме - 1С
добрый день, друзья. Обнаружено странное поведение. есть код з.ИдентификаторКлиента = Строка(ПолучитьИдентификаторКлиента());//...

Sleep() в фоновом режиме - C++
Мне надо, чтобы пока функция sleep() выполняется, я мог еще что-то делать, но пока она не кончится я не могу ничего сделать, помогите или...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru