Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Эмуляция нажатия мультимедийных клавиш в Windows, Linux и Mac OS X

Anna | 24.06.2014 | нет комментариев
В перечислении Qt::Key для события QKeyEvent определены 15 типов клавиш управления мультимедиа (см. таблицу в конце статьи). Все они могут быть использованы в фильтре событий (installEventFilter) для обработки нажатия клавиш на мультимедийной клавиатуре (дозволяющей руководить аудиоустройством и воспроизведением).
В статье рассмотрена обратная задача — отправка в систему команд управления мультимедиа путем эмуляции нажатия соответствующих клавиш в Windows, Linux и MacOSX (операционные системы упорядочены по времени, потраченному на поиск решения). Представленный в статье материал может быть отправной точкой к последующему постижению вопроса кроссплатформенной отправки событий в цикл обработки системных сообщений.

Раньше чем перейти непринужденно к изложению начального кода давайте разглядим, где вообще может использоваться эмуляция мультимедийных клавиш, скажем:

  • создание виджетов управления воспроизведением аудио;
  • эмуляция пользовательского ввода при тестировании приложений;
  • создание приложения для удаленного управления аудиосистемой. В данном случае приложение на компьютере выступает в качестве сервера, а заказчиком является телефон. Такая связка дозволит руководить аудио/видео не вставая с дивана либо, скажем, механически ставить на паузу воспроизведение при поступлении входящего громка;
  • создание приложения, «расшаривающего» клавиатуру и мышь на два и больше компьютеров по сети (заранее дополнив представленный код до полного комплекта клавиш);
  • создание систем «разумный дом», новых человеко-машинных интерфейсов (управление голосовыми командами и др.).

Так как QEvent разрешает отправлять сообщение только определенному объекту «внутри» приложения, то стандартными средствами Qt эмулировать нажатия клавиш не получится. Для этого будем применять системные вызовы Api (в случае с Windows) либо соответствующие библиотеки (X Window System в Linux и ряд фреймворков в Mac OS X).
Для комфорта изложения примерно всю реализацию отправки сообщений поместим в функцииsendKeyEventToSystem(Qt::Key qtKey), которой передается код клавиши из перечисления Qt::Key. Данная функция и будет вызываться из слотов, скажем:

void playPauseToogle() {  //слот переключения между воспроизведением и паузой
	postKeyEventToSystem(Qt::Key_MediaTogglePlayPause);
}

Платформенно-зависимый код будем отделять директивами #ifdef OS_TYPE и #endif (еще часть кода на Objective-C перенесем в обособленный файл macx.mm, но об этом позднее).

Эмуляция нажатия клавиатуры в Windows

В данной операционной системе за отправку сообщений отвечает функция SendInput. Она разрешает отправлять сообщения с кодами, полный перечень которых представлен на странице MSDN Virtual-Key Codes.
Для применения этой функции нужно подключить заголовочный файл <Windows.h>.

#ifdef Q_OS_WIN32
    #define WINVER 0x0500
    #include <Windows.h>
#endif

Примеров применения данной функции в интернете много и ее использование не должно вызвать задач, следственно сразу привожу код (в части Windows):

sendKeyEventToSystem(Qt::Key qtKey) { //функция эмуляции нажатия клавиши. qtKey - тип клавиши
#ifdef Q_OS_WIN32
    INPUT ip; //устройство ввода
    ip.type = INPUT_KEYBOARD;
    ip.ki.wScan = 0;
    ip.ki.time = 0;
    ip.ki.dwExtraInfo = 0;
//в зависимости от типа клавиши
    switch (qtKey) {
    case Qt::Key_MediaPrevious:
        ip.ki.wVk = VK_MEDIA_PREV_TRACK; //предыдущий трек
        break;
    case Qt::Key_MediaTogglePlayPause:
        ip.ki.wVk = VK_MEDIA_PLAY_PAUSE; //для переключения режима воспроизведения
        break;
    case Qt::Key_MediaNext:
        ip.ki.wVk = VK_MEDIA_NEXT_TRACK; //следующий трек
        break;
    default:
        return;
        break;
    }
	//посылаем событие нажатия клавиши
    ip.ki.dwFlags = 0;
    SendInput(1, &ip, sizeof(INPUT));
    //а после этого отжатия клавиши
    ip.ki.dwFlags = KEYEVENTF_KEYUP;
    SendInput(1, &ip, sizeof(INPUT));
#endif
}

Тут и дальше в примерах будут применяться каждого 3 клавиши. В конце статьи приведена таблица соответствия кmasterPort, IOServiceMatching( kIOHIDSystemClass ), &iter ); check( KERN_SUCCESS == kr); service = IOIteratorNext( iter ); check( service ); kr = IOServiceOpen( service, mach_task_self(), kIOHIDParamConnectType, &sEventDrvrRef ); check( KERN_SUCCESS == kr ); IOObjectRelease( service ); IOObjectRelease( iter ); } return sEventDrvrRef; } void HIDPostAuxKey(const UInt8 auxKeyCode ) { NXEventData event; kern_return_t kr; IOGPoint loc = { 0, 0 }; // Сообщение о нажатии клавиши UInt32 evtInfo = auxKeyCode << 16 | NX_KEYDOWN << 8; bzero(&event, sizeof(NXEventData)); event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS; event.compound.misc.L[0] = evtInfo; kr = IOHIDPostEvent( get_event_driver(), NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE ); check( KERN_SUCCESS == kr ); // Сообщение о отжатии клавиши evtInfo = auxKeyCode << 16 | NX_KEYUP << 8; bzero(&event, sizeof(NXEventData)); event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS; event.compound.misc.L[0] = evtInfo; kr = IOHIDPostEvent( get_event_driver(), NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE ); check( KERN_SUCCESS == kr ); }

Завершение:

Для меня было немножко необычно, что до сих пор не существует открыто доступной кроссплатформенной библиотеки, разрешающей исполнять отправку сообщений (в том числе события клавиатуры, мыши и д.р.). Во каждом случае мне такую библиотеку так и не получилось обнаружить. Представленный код далек от совершенства (представляю, как разрастется switch-case последовательность при добавлении новых клавиш). Но тем не менее пускай это будет маленький взнос в всеобщую копилку базы познаний о написании кросплатформенных приложений.
В ходе работы над статьей было подмечено, что VirtualBox перехватывает нажатия мультимедийных клавиш(проверялось на Ubuntu — c «железа» все работало). Данного недостатка лишена WMWare (проверялось на Mac OS X).

Приложение: Перечень мультимедийных клавиш и их определений (с поддержкой #define).

Qt::Key Windows Linux Mac OS X
Qt::Key_VolumeDown VK_VOLUME_DOWN XF86AudioLowerVolume NX_KEYTYPE_SOUND_DOWN
Qt::Key_VolumeMute VK_VOLUME_MUTE XF86AudioMute NX_KEYTYPE_MUTE
Qt::Key_VolumeUp VK_VOLUME_UP XF86AudioRaiseVolume NX_KEYTYPE_SOUND_UP
Qt::Key_BassBoost
Qt::Key_BassUp
Qt::Key_BassDown
Qt::Key_TrebleUp
Qt::Key_TrebleDown
Qt::Key_MediaPlay VK_MEDIA_PLAY_PAUSE XF86AudioPlay NX_KEYTYPE_PLAY
Qt::Key_MediaStop VK_MEDIA_STOP XF86AudioStop
Qt::Key_MediaPrevious VK_MEDIA_PREV_TRACK XF86AudioPrev NX_KEYTYPE_PREVIOUS
Qt::Key_MediaNext VK_MEDIA_NEXT_TRACK XF86AudioNext NX_KEYTYPE_NEXT
Qt::Key_MediaRecord
Qt::Key_MediaPause XF86AudioPause
Qt::Key_MediaTogglePlayPause VK_MEDIA_PLAY_PAUSE XF86AudioPlay NX_KEYTYPE_PLAY

Ссылки по теме:
1. Существующие подходы к решению задачи: C (Qt) cross-platform library for simulating keyboard input, sendkeys, send kestrokes, etc
2. Изложение функции SendInput и перечень кодов клавиатуры на сайте MSDN.
3. Simulating Mediakey Presses in C & X11 — в статье описывается, как в Linux с поддержкой утилиты «xev» (в Ubuntu: «sudo apt-get install x11-utils») дозволено узнать коды клавиш, а также в дополнение статья с archlinux.org.
4. Эмуляция мультимедийных клавиш в MacOS X на языке программирования Python.

Источник: programmingmaster.ru

Оставить комментарий
БАЗА ЗНАНИЙ
СЛУЧАЙНАЯ СТАТЬЯ
СЛУЧАЙНЫЙ БЛОГ
СЛУЧАЙНЫЙ МОД
СЛУЧАЙНЫЙ СКИН
НОВЫЕ МОДЫ
НОВЫЕ СКИНЫ
НАКОПЛЕННЫЙ ОПЫТ
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB