На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
  
> C\C++ Эмуляция нажатия клавиш в свернутом окне на уровне драйвера
    Есть dx 3d приложение, нужно чтобы окно захватывалось не по названию, а по id (окно не активно, окон с одинаковым названием несколько, нужно только одно). И в этом окне эмулировалось нажатие клавиш на уровне драйвера (т.е. чтобы приложение «думало» что это команды с клавиатуры, а не от программы).

    Скажите пожалуйста где можно об этом прочитать (все вместе или отдельно про захват окна и эмуляцию нажатий). У меня ничего найти не получилось, может в учебнике каком-то есть об этом.

    Заранее благодарю.
      Качаешь DDK, там в исходниках есть пример драйвера клавы. Выкидывашь лишнего, допиливаешь своего...
      Цитата TheMachine @
      т.е. в общем случае вы правы конечно, а мне надо спать больше а пить меньше
        Цитата mafusaill @
        т.е. чтобы приложение «думало» что это команды с клавиатуры, а не от программы

        Оно может так думать и от использования SendInput
        const char *out = "|*0>78-,+<|"; size_t cc = char_traits<char>::length(out);
        for (size_t i=0;i<cc;i++){cout<<static_cast<char>((out[i]^89));}cout<<endl;

        Чат Исходников в DiscordЧат Исходников в Telegram
          Цитата B.V. @

          Возможно, но я чайник) Слабо разбираюсь в том, как все работает.
          Просто есть такие программы как "Frost" и "FireGuard" которые сканируют ОЗУ (и вроде не только озу), как мне объяснили, они могут обнаружить SendInput, по этому нужно посылать команды на уровне драйвера.

          И еще очень интересует, как захватить нужное окно?

          Добавлено
          Я вот сейчас представляю как глупо и даже кощунственно смотрятся мои посты)
          Прошу прощения у все участников форума)) Я пытаюсь учиться))
            Нашел вот такую статью
            http://msdn.microsoft.com/en-us/library/wi...v=vs.85%29.aspx

            Я так понимаю INPUT_HARDWARE это как раз то, что мне нужно?
            Помогите пожалуйста разобраться с синтаксисом. Можно пример нажатия любой кнопки?
              Цитата mafusaill @
              Нашел вот такую статью
              http://msdn.microsoft.com/en-us/library/wi...v=vs.85%29.aspx

              Я так понимаю INPUT_HARDWARE это как раз то, что мне нужно?
              Помогите пожалуйста разобраться с синтаксисом. Можно пример нажатия любой кнопки?

              Нет это для генерации событий отличных от мыши и клавиатуры !!!
              Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал"("Yоur bunnу wrоte")
                Нашел вот такой код, все работает, даже окно ищет (правда не по ID), помогите разобраться как в нем все работает, не хочется бездумно использовать, хочется понять. По подробнее пожалуйста если можно)

                ExpandedWrap disabled
                  #include <cstdlib>
                  #include <iostream>
                  #include <math.h>
                  #include <fstream>
                  #include <Windows.h>
                  #include <winuser.h>
                  #include <winable.h> /* Dev-C++ specific */
                  using namespace std;
                   
                  /* HWND = "Window Handle" */
                  HWND GameWindow = FindWindow(0, "Google - Mozilla Firefox");
                   
                  /* This is a function to simplify usage of sending keys */
                  void GenerateKey(int vk, BOOL bExtended) {
                   
                      KEYBDINPUT  kb = {0};
                      INPUT       Input = {0};
                   
                      /* Generate a "key down" */
                      if (bExtended) { kb.dwFlags  = KEYEVENTF_EXTENDEDKEY; }
                      kb.wVk  = vk;
                      Input.type  = INPUT_KEYBOARD;
                      Input.ki  = kb;
                      SendInput(1, &Input, sizeof(Input));
                   
                      /* Generate a "key up" */
                      ZeroMemory(&kb, sizeof(KEYBDINPUT));
                      ZeroMemory(&Input, sizeof(INPUT));
                      kb.dwFlags  =  KEYEVENTF_KEYUP;
                      if (bExtended) { kb.dwFlags |= KEYEVENTF_EXTENDEDKEY; }
                      kb.wVk = vk;
                      Input.type = INPUT_KEYBOARD;
                      Input.ki = kb;
                      SendInput(1, &Input, sizeof(Input));
                   
                      return;
                  }
                   
                  int main() {
                   
                      /*
                         SetForegroundWindow will give the window focus for the
                         keyboard/mouse! In other words, you don't have to have
                         the game opened upfront in order to emulate key/mouse
                         presses, it's very helpful if it's a game that runs
                         in fullscreen mode, like StarCraft: Brood War does
                      */
                   
                      SetForegroundWindow(GameWindow);
                   
                      GenerateKey(VK_CAPITAL, TRUE);
                      GenerateKey('I', FALSE);
                      GenerateKey(' ', FALSE);
                   
                      GenerateKey(VK_CAPITAL, TRUE);
                      GenerateKey('A', FALSE);
                      GenerateKey('M', FALSE);
                      GenerateKey(' ', FALSE);
                   
                      GenerateKey('C', FALSE);
                      GenerateKey('O', FALSE);
                      GenerateKey('O', FALSE);
                      GenerateKey('L', FALSE);
                      GenerateKey('E', FALSE);
                      GenerateKey('R', FALSE);
                      GenerateKey(' ', FALSE);
                   
                      GenerateKey('T', FALSE);
                      GenerateKey('H', FALSE);
                      GenerateKey('A', FALSE);
                      GenerateKey('N', FALSE);
                      GenerateKey(' ', FALSE);
                   
                      GenerateKey('Y', FALSE);
                      GenerateKey('O', FALSE);
                      GenerateKey('U', FALSE);
                      GenerateKey(' ', FALSE);
                      
                      GenerateKey('W', FALSE);
                      GenerateKey('I', FALSE);
                      GenerateKey('L', FALSE);
                      GenerateKey('L', FALSE);
                      GenerateKey(' ', FALSE);
                   
                      GenerateKey('E', FALSE);
                      GenerateKey('V', FALSE);
                      GenerateKey('E', FALSE);
                      GenerateKey('R', FALSE);
                      GenerateKey(' ', FALSE);
                   
                      GenerateKey('B', FALSE);
                      GenerateKey('E', FALSE);
                      GenerateKey('n', FALSE);
                      GenerateKey(' ', FALSE);
                   
                      GenerateKey(0x3A, FALSE); /* period key */
                      GenerateKey(0x0D, FALSE); /* enter key */
                   
                      return 0;
                  }


                Добавлено
                В общем-то мне не понятно как работает только этот кусок:
                ExpandedWrap disabled
                  /* This is a function to simplify usage of sending keys */
                  void GenerateKey(int vk, BOOL bExtended) {
                   
                      KEYBDINPUT  kb = {0};
                      INPUT       Input = {0};
                   
                      /* Generate a "key down" */
                      if (bExtended) { kb.dwFlags  = KEYEVENTF_EXTENDEDKEY; }
                      kb.wVk  = vk;
                      Input.type  = INPUT_KEYBOARD;
                      Input.ki  = kb;
                      SendInput(1, &Input, sizeof(Input));
                   
                      /* Generate a "key up" */
                      ZeroMemory(&kb, sizeof(KEYBDINPUT));
                      ZeroMemory(&Input, sizeof(INPUT));
                      kb.dwFlags  =  KEYEVENTF_KEYUP;
                      if (bExtended) { kb.dwFlags |= KEYEVENTF_EXTENDEDKEY; }
                      kb.wVk = vk;
                      Input.type = INPUT_KEYBOARD;
                      Input.ki = kb;
                      SendInput(1, &Input, sizeof(Input));
                   
                      return;
                  }


                Добавлено
                Вот еще один код, как я понимаю от отличается от предыдущего тем, что в первом есть нажатие клавиши и отжатие, а тут все в одном?
                ExpandedWrap disabled
                  #include <cstdlib>
                  #include <iostream>
                  #include <math.h>
                  #include <fstream>
                  #include <Windows.h>
                  #include <winuser.h>
                  #include <winable.h> /* Dev-C++ specific */
                  using namespace std;
                   
                  /* HWND = "Window Handle" */
                  HWND hWnd = FindWindow(0, "Google - Mozilla Firefox");
                   
                  void GenerateKey(BYTE vk) {
                   
                      INPUT Input;
                      ZeroMemory(&Input, sizeof(Input));
                      Input.type = INPUT_KEYBOARD;
                      Input.ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
                      Input.ki.wVk = vk;
                      SendInput(1, &Input, sizeof(INPUT));
                   
                      return;
                  }
                   
                  int main() {
                   
                      SetForegroundWindow(hWnd);
                   
                      GenerateKey((UCHAR)VkKeyScan('C'));
                      GenerateKey((UCHAR)VkKeyScan('o'));
                      GenerateKey((UCHAR)VkKeyScan('d'));
                      GenerateKey((UCHAR)VkKeyScan('i'));
                      GenerateKey((UCHAR)VkKeyScan('n'));
                      GenerateKey((UCHAR)VkKeyScan('g'));
                      GenerateKey((UCHAR)VkKeyScan(' '));
                      
                      GenerateKey((UCHAR)VkKeyScan('i'));
                      GenerateKey((UCHAR)VkKeyScan('s'));
                      GenerateKey((UCHAR)VkKeyScan(' '));
                      
                      GenerateKey((UCHAR)VkKeyScan('f'));
                      GenerateKey((UCHAR)VkKeyScan('u'));
                      GenerateKey((UCHAR)VkKeyScan('n'));
                      GenerateKey((UCHAR)VkKeyScan('.'));
                      GenerateKey((UCHAR)VkKeyScan('\n')); /* enter key */
                   
                      return 0;
                  }
                  Это программная генерация нажатий, а не "на уровне драйвера". Соотв-но и детектируется это элементарно - см.соседнюю тему
                    А вот это работает в неактивном окне:
                    ExpandedWrap disabled
                      #include <cstdlib>
                      #include <iostream>
                      #include <math.h>
                      #include <fstream>
                      #include <Windows.h>
                      #include <winuser.h>
                      #include <winable.h> /* Dev-C++ specific */
                      using namespace std;
                       
                      /* HWND = "Window Handle" */
                      HWND hwnd = FindWindow(0, "Google - Mozilla Firefox");
                       
                      void PressButton(HWND hwnd, BYTE vk)  {
                       
                          SendMessage(hwnd, vk, WM_KEYDOWN, 0);
                       
                          /* Due to Blizzard's latest patch, I had to change this to PostMessage */
                          PostMessage(hwnd, WM_CHAR, vk, 0);
                          SendMessage(hwnd, vk, WM_KEYUP, 0);
                      }
                       
                      void TypeText(HWND hwnd, char String[]) {
                       
                          /* You could filter text in here if you wanted :) */
                          for (int x = 0; String[x] != 0; x++) { PressButton(hwnd, String[x]); }
                      }
                       
                      void DrawBox() {
                       
                          TypeText(hwnd, "\n      /-----\\     \n");
                          Sleep(25);
                          TypeText(hwnd, "\n      |     |     \n");
                          Sleep(25);
                          TypeText(hwnd, "\n      \\-----/     \n");
                       
                          return;
                      }
                       
                      int main() {
                       
                          TypeText(hwnd, "\nThis is a really cool example! :)\n");
                          Sleep(25); /* You must pause to give StarCraft time to respond */
                          TypeText(hwnd, "\nUnfortuantly with Brood War, it only works while in-game... :(\n");
                       
                          Sleep(10000); /* Paused for a while so you can alt + tab to SC: BW and watch it be drawn */
                       
                          /* Here's an ideal ASCII art! */
                          DrawBox();
                       
                          return 0;
                      }


                    Какие строчки отвечают за работу в активном\не активном окне?


                    Помогите пожалуйста))

                    Добавлено
                    Ну просто выше написали что нет разницы, на уровне драйвера или SendInput
                      Цитата mafusaill @
                      Вот еще один код, как я понимаю от отличается от предыдущего тем, что в первом есть нажатие клавиши и отжатие, а тут все в одном?

                      Тут только нажатия без отжатий, и это не правильно. Если нужно, "чтобы приложение «думало» что это команды с клавиатуры", то нужны и нажатия и отжатия, причем с задержкой в 50-100 мс

                      Цитата mafusaill @
                      Какие строчки отвечают за работу в активном\не активном окне?

                      Использование ф-й SendInput или keybd_event лишь имитирует нажатие клавиш на клавиатуре, и затем уже ОС решает, какое окно активно, чтобы послать ему сообщения WM_KEYDOWN, WM_KEYUP, соответствующие этим нажатиям.
                      Если же ты сам шлешь эти сообщения через SendMessage или PostMessage определенному окну, то неважно активно, оно или нет. Хотя некоторые проги для защиты от ботов могут сами проверять активно ли окно и игнорировать обработку этих сообщений (а при использовании SendMessage определить "подделку" вообще элементарно по InSendMessage).

                      Добавлено
                      Цитата mafusaill @
                      Ну просто выше написали что нет разницы, на уровне драйвера или SendInput

                      Нет разницы, если в проге нет защиты от программных нажатий. Иначе придется повозиться
                        2leo Спасибо огромное за столь распространенные ответы, надеюсь Вас не затруднит ответить еще на несколько вопросов?

                        Как вообще можно реализовать нажатие клавиш на уровне драйвера? И если все же использовать SendInput, то как можно посылать команды в неактивное окно (при условии того, что сигналы с физической клавиатуры будут идти в другое окно, активное)? В принципе можно просто запускать второе окно с программой на виртуальной машине, там оно и будет активно, но все же хочется сделать все красиво, чтобы программа работала без лишнего шаманства.

                        Добавлено
                        И как можно в первом примере между нажатием и отжатием добавить слипы? Я вот просто, что-то не получается, скорее всего просто не там их ставлю.
                          Цитата mafusaill @
                          надеюсь Вас не затруднит ответить еще на несколько вопросов?

                          Затруднит, поскольку это всё те же самые вопросы. Если нужно имитировать нажатия в неактивном окне, то SendInput и тем более драйвер тут вообще ни к селу, т.к. тут рулят обычные Send\PostMessage, а сработают они или нет зависит от наличия или отсутствия элементарной защиты в программе. В виндовый блокнот, как и в любой стандартный эдит-контрол, можно забить текст элементарными WM_CHAR (без всяких WM_KEYDOWN\UP) независимо от того, активно окно или нет. С другими прогами (типа MS Word, различными браузерами и т.п.) дела могут обстоять посложнее. А с игрушками, напичканными всевозможными защитами от ботов, ва-аще "сливай вода" - тут те и проверки на foreground и GetFocus, на InSendMessage, GetAsyncKeyState и еще куча всего, вплоть до контроля задержек между событиями, плавности перемещения мыши и т.п.
                          Лучше скажи, почему тебе нужно работать именно с неактивным окном? Может проще временно переключить фокус ввода (если обычные Send\PostMessage не прокатывают)?

                          PS: В DX вместо обычных клавиатурных сообщений WM_KEY..\WM_CHAR может использоваться RawInput с обработкой WM_INPUT, который просто так через Send\PostMessage не пошлешь - только через SendInput (или драйвер)

                          Добавлено
                          Цитата mafusaill @
                          И как можно в первом примере между нажатием и отжатием добавить слипы?

                          При использовании SendInput можно задавать время события в поле time - первому нажатию ставишь текущее значение GetTickCount, а отжатию (и последующим нажатиям\отжатиям, если они есть) на некоторую дельту больше
                            Для неактивного окна можно воспользоваться
                            AttachThreadInput()
                            http://www.vsokovikov.narod.ru/New_MSDN_AP...threadinput.htm

                            Сообщения были разделены в тему "Нужна программа для размещения объявлений на сайте"
                            Американские программисты долго не могли понять, почему русские при зависании Windоws всё время повторяют "Твой зайка написал"("Yоur bunnу wrоte")
                              Что касается "И в этом окне эмулировалось нажатие клавиш на уровне драйвера (т.е. чтобы приложение «думало» что это команды с клавиатуры, а не от программы)." - то уже реализована аппаратная эмуляция usb-hid клавиатуры и мыши. <cut>

                              M
                              п. 1.5 правил форума!
                              Сообщение отредактировано: B.V. -
                              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                              0 пользователей:


                              Рейтинг@Mail.ru
                              [ Script Execution time: 0,1373 ]   [ 16 queries used ]   [ Generated: 1.12.20, 20:35 GMT ]