Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 23.12.2011, 17:32   #1
Ecosasha
Форумчанин
 
Регистрация: 22.05.2009
Сообщений: 248
По умолчанию Замена клавиш в чужом приложении при нажатии

Для чего это надо, для программ, игр, где не предусмотрена настройка клавиш, и файла настройки нормального.
Приведу пример, например, есть игра "Glove on Fight".
В ней клавиши для клавиатуры не настраиваются, а по умолчанию:
Стрелки - для движения персонажа
Z,X,C - удары.

Требуется переделать
W,A,S,D - для движения персонажа
J,K,L - удары.

Первое, что пришло в голову, это сделать по быстрому приложение на Дельфи, которое будет "активным всегда сверху и иметь в уголке просто маленький размер".
Нажимая на нем нужные клавишы WASD, мы просто отсылаем сообщение с другими клавишами другому приложению, зная его хэндл.

Проверяем:
Код:
// SetForegroundWindow(FindWindow(nil,'Glove on Fight'));
 hw:=FindWindow(nil,'Glove on Fight');
 sendmessage(hw,WM_IME_KEYUP,90, 0);//90='z'
Возникло предположение, что может просто не то окно, есть дочернее окно. Посмотрел по WinSpy++, Microsoft Spy ++, пробовал даже на другие хэндлы у него. Но в целом, по свойствам видно, что отправляется нажатие на главное окно.

В чем ошибка, почему нормально срабатывает эмуляции нажатия клавиши для "Блокнота", Notepad++ и для других некотрых программ, а здесь не работает.

Что подскажите?

P.S. Или может уже есть готовые программы, в которых выбираешь нужный процесс из списка, и делаешь список нужных клавиш. Искал, но не нашел.
Ecosasha вне форума Ответить с цитированием
Старый 23.12.2011, 17:40   #2
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

читай про хуки.
Человек_Борща вне форума Ответить с цитированием
Старый 23.12.2011, 18:07   #3
Ecosasha
Форумчанин
 
Регистрация: 22.05.2009
Сообщений: 248
По умолчанию

Цитата:
Сообщение от Человек_Борща Посмотреть сообщение
читай про хуки.
Про хуки смотрел,
и такая конструкция, подсмотренная на одном из сайтов, вроде бы должна сработать, но опять же для "notepad" работает, а для данной проги нет.
При нажатии на F11 - происходит нажатие "z".
Код:
var
 hKeyHook: HHOOK;
//запускаем сначала хук
procedure TFMain.Button1Click(Sender: TObject);
begin
  hKeyHook:=SetWindowsHookEx(13,@KeyEvent,GetModuleHandle(nil),0);   
  //13 =WH_KEYBOARD_LL
  //2=WH_KEYBOARD
end;

//останавливаем хук
procedure TFMain.Button4Click(Sender: TObject);
begin
   UnhookWindowsHookEx(hKeyHook);
end;

function KeyEvent(nCode: Integer; wParam, lParam: Longint): LongInt; stdcall;
begin
  Result:=CallNextHookEx(hKeyHook,nCode,wParam,lParam);
  if ((nCode = HC_ACTION) and (wParam = WM_KEYDOWN)) and (PKBDLLHOOKSTRUCT(lParam).vkCode=VK_F11) then 
begin
      //Зажимаем клавишу  z
      keybd_event(ORD('Z'), MapVirtualkey(ord('Z'), 0 ), 0, 0);
      // Отпускаем клавишу z
      keybd_event(ord('Z'), MapVirtualkey(ord('Z'), 0 ), KEYEVENTF_KEYUP, 0);

//     FMain.clickkey(90);

  end;

procedure TFMain.clickkey(key:word);
begin
 keybd_event(key,0,0,0);
 keybd_event(key,0,KEYEVENTF_KEYUP,0);
end;
Вроде бы простой пример, менял значения для SetWindowsHookEx, на 2 и 13 и другие даже, но нет реакции.
Может быть ошибка кроется в передаче клавиши, то есть она воспринимается как символ или как-то конвертируется внутри данной "японской проги"?
Прилагаю скрины от MS Spy++ Messages при нажатии клавиши "z" в данной проге.

Или что-то не учитываю?
В целом, есть предположение? что может реакции нет из-за того, что операционная Windows 7 x64?
Изображения
Тип файла: jpg Screen.jpg (33.3 Кб, 119 просмотров)
Тип файла: jpg Screen2.jpg (215.2 Кб, 120 просмотров)

Последний раз редактировалось Ecosasha; 23.12.2011 в 18:10.
Ecosasha вне форума Ответить с цитированием
Старый 23.12.2011, 18:15   #4
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Глобальный хук системы нужен. Там перехватываешь нажатие, смотришь куда адресовано нажатие, если в нужную программу, то делаешь замену.
Человек_Борща вне форума Ответить с цитированием
Старый 25.12.2011, 14:07   #5
Aliens_wolfs
Форумчанин
 
Регистрация: 16.12.2009
Сообщений: 902
По умолчанию

Для глобального Хука могут быть проблемы со всеми клавишами, например остальные клавиши которые не эмулируются уже не будут работать их нужно будет прорписывать для эмуляции.
Вот вариант для захвата определенных клавиш

Код:
  private
    procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

//Если известен хендл окна то работай по сообщениям нажатия в самом окне
procedure SetKeyMessage(Handle: HWND; Key: DWORD);
begin
SendMessage(Handle, WM_KEYDOWN, Key, 0);
SendMessage(Handle, WM_KEYUP, Key, 0);
end;

//Эмуляция клавиши
procedure SetKey(Key: DWORD);
begin
  keybd_event(Key, 0, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);
  keybd_event(Key, 0, KEYEVENTF_EXTENDEDKEY, 0);
  keybd_event(Key, 0, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
//Захватываем клавиши
RegisterHotKey(handle, ord('Z'), 0, ord('Z'));
RegisterHotKey(handle, ord('X'), 0, ord('X'));
RegisterHotKey(handle, ord('C'), 0, ord('C'));

RegisterHotKey(handle, 37, 0, 37); //стрелка в лево
RegisterHotKey(handle, 39, 0, 39); //стрелка в право
RegisterHotKey(handle, 39, 0, 38); //стрелка в верх
RegisterHotKey(handle, 39, 0, 40); //стрелка в низ
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
//Освобождаем клавиши
UnRegisterHotKey(handle, ord('Z'));
UnRegisterHotKey(handle, ord('X'));
UnRegisterHotKey(handle, ord('C'));

UnRegisterHotKey(handle, 37);
UnRegisterHotKey(handle, 39);
UnRegisterHotKey(handle, 38);
UnRegisterHotKey(handle, 40);
end;

//Ловим нажатие клавиш и эмулируем нажатие других клавиш.
procedure TForm1.WMHotKey(var Msg: TWMHotKey);
begin
Case Msg.HotKey  of
ord('Z'): SetKey(Ord(J)); //или если хендел окна игры известен то SetKeyMessag(Хендел игны, Ord(J));
ord('X'): SetKey(Ord(K));
ord('C'): SetKey(Ord(L));

37: SetKey(Ord(A));
39: SetKey(Ord(D));
38: SetKey(Ord(W));
38: SetKey(Ord(S));
end;
end;

Последний раз редактировалось Aliens_wolfs; 25.12.2011 в 15:23.
Aliens_wolfs вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как сделать чтобы программа не закрывалась при нажатии клавиш alt+f4 (Delphi) zig1 Помощь студентам 1 12.12.2011 06:18
Клик в чужом приложении SunnyDay Общие вопросы Delphi 5 31.10.2011 15:12
при нажатии цифр поменять значение буквенных клавиш местами(Assembler) lexa123 Помощь студентам 1 16.12.2010 20:29
Open GL. при нажатии клавиш Left, Ridth, Up и Down точка должна двигаться по форме Roof Gamedev - cоздание игр: Unity, OpenGL, DirectX 27 16.11.2007 01:33