Жестурь / Gestureo

Тема в разделе "WASM.PROJECTS", создана пользователем Paguo_86PK, 27 июл 2017.

  1. Paguo_86PK

    Paguo_86PK Руслан

    Публикаций:
    0
    Регистрация:
    8 окт 2007
    Сообщения:
    911
    Адрес:
    Ташкент
    Делo было несколько лет тому назад…
    Моему брату его друг дал свою беспроводную мышь, так как её заклинило и перекосило - поменялись местами горизонталь с вертикалью в движениях. Из гугла я узнал, что такой глюк достаточно нередко встречается у некоторых производителей.
    Попробовал сам попользоваться ею - крайне неудобно. Ковырял настройки и драйверы - толку мало…

    Решил приспособить тогда эту мышь для дистанционного управления компьютером. В частности, пользоваться ею как джойстиком. Ведь у моей беспроводной всего три кнопки. А у этой глюкнутой - ещё две сбоку для управления навигацией в браузере.
    (Надо сказать, мы с братом терпеть не можем подобные опциональные кнопки у мышей: Чуть неловко тронешь - бац и страница переключилась)
    Стал искать готовые программы, чтобы превратить лишние мышки в своеобразные ПДУ. Однако, то ли искал плохо, то ли нету такой экзотики…

    Сел писать сам. Скачал пару примеров с RawInput и как попало накидал код, чтобы лишь бы работал…

    Как пользоваться
    Слева выводятся все флажки виртуально нажимаемых кнопок.
    Большие кнопки East/North/SouthWest срабатывают при перемещении мышек в соответственном направлении. Стоит просто поводить мышью, понаживать кнопки и покрутить ролики, чтобы быстро разобраться.
    Справа находится насыщенная таблица с флажками для управления постулатами срабатывания.
    Каждая колонка имеет свою букву, соответсвующую первой букве виртуальных кнопок слева.
    Причём, левые 13 столбцов закреплены за основной мышью, а правые - за вспомогательной.
    Первый клик по пустой клетке ставит там заглавную букву, второй - меняет её на строчную, третий - очищает.
    Отличие заглавных и строчных флажком в том, что заглавные держатся, пока мышь остаётся в нужном состоянии. Тогда как строчные срабатывают один раз.
    Последний столбец со значком "@" указывает, будет ли событие срабатывать в режиме игры или в обычном режиме.
    Триггер Scroll Lock управляет этим самым режимом.
    А вот Num Lock управляет режимом активного расширения кнопок мыши (появился недавно).
    Чтобы назначить строчке таблицы клавишу, достаточно нажать нажную клавише, заранее строчку выделив, кликнув по ней.
    Если попытаться задать строчке клавишу Caps Lock, то вместо клавиши в стоке запомнится экранная позиция курсора, куда будет производится виртуальный клик.
    (Полезно в некоторых туповатых онлайн плеерах, которые понимают лишь клики по гламурным кнопками своей физиономии.)
    Клавиша Tab позволяет ввести название/описание профиля, закрепляя их нажатием клавиши Ввод.
    В меню можно выбрать профиль или сохранить его в реестре для последующего использования.
    (На данный момент что-то в коде я поломал и с чтением/сохранением профиля наблюдается сплошной баг)

    P.S.: Вот «страничка проекта».
    Важно: Если у Вас всего одна единственная мышь, можете даже не пробовать программу…
    После запуска она ожидает активности вспомогательной мыши, а затем уже основной. В противном случае основная мышь тупо застрянет до выхода из этой утилиты.
    Если же очень хочется, можете включить режим управления указателем мыши с клавиатуры и сразу после запуска утилиты сместить её клавиатурой. Потом смело двигайте основной.
    Почему такие фокусы? Выше уже сказал, что писал быстро и как попало. Теперь самого раздражает, но основательно переделать - руки не доходят.
    Ещё есть глюки с реестром: Профили сохраняются/читаются глючно и после перезапуска утилиты нужно настраивать всё вновь…
     
    yashechka нравится это.
  2. Paguo_86PK

    Paguo_86PK Руслан

    Публикаций:
    0
    Регистрация:
    8 окт 2007
    Сообщения:
    911
    Адрес:
    Ташкент
    Зa весь этот период времени удалось поднаворотить свою «Жестурь»…

    Теперь программа:
    • Поддерживает до девяти мышек (игнорируя избыточные)
    • Позволяет выбрать свой указатель для каждой мышки
    • Устанавливает масштаб указателя и скорость движения отдельной мышки
    • Поддерживает до 32 клавиш и четыре режима работы
    • Добавляется в трей и имеет «горячие клавиши»
    Тем самым, функциональность увеличилась в разы…
    Имеется не мало глюков и утечек памяти в непонятных местах.
    В частности, сегодня программа проработала 12 часов с утра с четырьмя указателями. Диспетчер программ показал, что за 12 часов система ей уделила около 60 минут машинного времени и 1024кб памяти. К моему удивлению, никаких «утечек» не возникло, хотя в прошлый раз они были (уже через 10 минут работы исказилась панель задач и остальные окна «стрёмно» отрисовивались), но особых модификаций кода не делал, так как не нашёл мест утечки…

    Все курсоры являются отдельными окнами с анимированными регионами, как персонажи «Офиса». Анимация отрисовывается только DrawIconEx - никаких GDI+ и сторонних библиотек. Под Windows'8 файлы *.ani не имеют ограничений в размерах и код отрисовывает их как есть: Взял несколько персонажей игр (видно из видео) и сконвертировал gif в ani с сохранением размеров - работает!
    А вот под Windows'XP происходит ошибка и меню выбора указателей просто не отображается (хотя давным-давно читал же, что в XP сняты ограничения на размеры курсоров/иконок).
    Во всяком случае, на видео выше видна работа ещё не опубликованного кода. Тот код - уже история GitHub…
    Текущая версия включает уже 2455 строк. Подгружает до 100 *.ani/*.cur-указателей из отдельной папки.

    P.S.: Раньше не понимал, почему разработчики программ (WinAmp в частности) требуют купить его за нехилую (для карманов наших регионов) сумму…
    А теперь осознал, что будь у меня лишние деньги, купил бы все девять новых мышек с кучей кнопок и роликов, чтобы как следует отладить свой код…
    Пока же, у меня одна беспроводная мышь и три проводные с мелкими неисправностями. У какой-то - ролик не реагирует, у другой - средняя кнопка, у третьей - левая кнопка не всегда срабатывает.
    Да и в сети нашёлся лишь один человек, который решил протестировать. Однако, мышь у него одна и ему было нужно просто боковыми кнопками управлять системной громкостью. Готовых утилит для этих целей море. Моя же - слишком сложна в настройках и использовании…
     
    yashechka нравится это.
  3. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.348
    Потому что gdi-хендлы не закрываешь и они в системе закончились.
     
  4. Paguo_86PK

    Paguo_86PK Руслан

    Публикаций:
    0
    Регистрация:
    8 окт 2007
    Сообщения:
    911
    Адрес:
    Ташкент
    Дa, не сказал бы…
    За те 10 минут я перебрал всю сотню указателей, что запускает регенерацию регионов анимации. И возникла утечка, не пойму где. Ошибка где-то здесь была:
    Код (Text):
    1. #define ICON_SIZE_MAX   128
    2.  
    3. HRGN    RgnFromIcon(HRGN *phRgn, HICON hIcon, int size = 32) {
    4.     HRGN    hRgn;
    5.     HRGN    hRgnPt;
    6.     HDC     hBmpDC = CreateCompatibleDC(0);
    7.     int     pBmp[ICON_SIZE_MAX][ICON_SIZE_MAX];
    8.     HBITMAP hBmp;
    9.     int     i, x, y, z;
    10.  
    11.     for(y = 0; y < ICON_SIZE_MAX; ++ y)
    12.         for(x = 0; x < ICON_SIZE_MAX; ++ x)
    13.             pBmp[y][x] = -1;
    14.    
    15.     hBmp = CreateBitmap(ICON_SIZE_MAX, ICON_SIZE_MAX, 1, 32, pBmp);
    16.     SelectObject(hBmpDC, hBmp);
    17.     for(i = 0; i < 256; ++ i)
    18.         if(!!DrawIconEx(hBmpDC, 0, 0, hIcon, size, size, i, NULL, DI_MASK | DI_DEFAULTSIZE*0)) {
    19.             DeleteObject(phRgn[i]);
    20.             phRgn[i] = CreateRectRgn(0, 0, size, size);
    21.             GetBitmapBits(hBmp, ICON_SIZE_MAX * ICON_SIZE_MAX * 4, &pBmp);
    22.             for(y = 0; y < ICON_SIZE_MAX; ++ y) {
    23.                 x = 0;
    24.                 while(x < ICON_SIZE_MAX) {
    25.                     z = x;
    26.                     while((x < ICON_SIZE_MAX) && (pBmp[y][x] != 0))
    27.                         pBmp[y][x ++] = -1;
    28.                     if(x < ICON_SIZE_MAX)
    29.                         pBmp[y][x] = -1;
    30.                     if(x > z) {
    31.                         hRgnPt = CreateRectRgn(z, y, x, y + 1);
    32.                         CombineRgn(phRgn[i], phRgn[i], hRgnPt, RGN_DIFF);
    33.                         DeleteObject(hRgnPt);
    34.                     }
    35.                     ++ x;
    36.                 }
    37.             }
    38.             SetBitmapBits(hBmp, ICON_SIZE_MAX * ICON_SIZE_MAX * 4, pBmp);
    39.         } else
    40.             break;
    41.     while(i < 256 && !!phRgn[i]) {
    42.         DeleteObject(phRgn[i]);
    43.         phRgn[i ++] = NULL;
    44.     }
    45.     DeleteDC(hBmpDC);
    46.     DeleteObject(hBmp);
    47.  
    48.     return hRgn;
    49. }
    Самое неприятное то, что в Debug-варианте под Win'XP отрисовывают и все гигантские анимашки, и меню их выбора выскакивает. А вот Release-вариант работает только в Windows'8, а под Win'XP ни меню, ни курсоров вообще не выводится…
    Это уже не первый мой случай, когда мой код работает только под нагрузкой отладочной информации и механизмов. Видимо, где-то структуры не »пронуляю » что ли…

    P.S.: Сейчас никак разобраться не могу с перемещением указателя…
    После запуска программы мышка начинает двигаться заметно резче.
    Добавил SystemParametersInfo(SPI_GETMOUSESPEED…), но не совсем понятно, как это применить… В RAMINPUT-обработчике все способы перебрал - всё равно анимашки не двигаются с реальным курсором 1 в 1…
    И сам курсор за пределами окна утилиты движется иначе, чем в её пределах: Чтобы избежать зависаний, в пределах окна хук-мышки вызывает CallNextHookEx(0, iCode, wParam, lParam). За пределами - обходит.
    И никак не могу выгуглить базовые алгоритмы координатного перемещения мышки и с учётом флажка «повышения точности позиционирования указателя».
    P.P.S.: Не менее раздражительно то, что RawInput работает не через callback-хук, а посылкой WM_INPUT в окно… Что местами занимает заметное процессорное время.
     
  5. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.348
    А вот добавь в диспетчере задач колонку "Объекты GDI" и посмотри.
     
  6. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.348
    Руки тряслись? :)
     
  7. Paguo_86PK

    Paguo_86PK Руслан

    Публикаций:
    0
    Регистрация:
    8 окт 2007
    Сообщения:
    911
    Адрес:
    Ташкент
    Оказалoсь, GetIconInfo подвела:
    Как-то не обратил внимания… Теперь понятно, почему сутками программа на экране анимашками прыгала без каких-либо утечек. А стоило мышками пошевелить как следует, так через 5-10 минут всё искажается: У меня на событие движения окна персонажа как раз GetIconInfo и стоит просто для чтения «горячей точки» указателя.
    Код (Text):
    1.  if(!!DrawIconEx…
    2. while(i < 256 && !!phRgn[i]…
    Это у меня привычка появилась после JavaScript - явное преобразование к типу Boolean…
    Алгоритмически же видно, что логически не может быть «if(!DrawIconEx…»! Хотя можно и «if(DrawIconEx…», но мне «!!» уже больше нравится, чем «!=0»…

    P.S.: При старте программа стабильно держит 1484 объектов GDI… А каждая очередная мышь увеличивает их число на 7.
    (Сейчас шевелю всеми четырьмя мышками - число объектов стабильно выше 1515 не растёт…)
     
  8. Paguo_86PK

    Paguo_86PK Руслан

    Публикаций:
    0
    Регистрация:
    8 окт 2007
    Сообщения:
    911
    Адрес:
    Ташкент
    Итaк, как у программистов модно говорить - «запускаете программу на свой страх и риск!»…
    Данный релиз заметно проблемно проходит тест в VirusTotal, что насторожило меня самого: Вдруг моя система поражена тем реальным вирусом?
    По-этому, буду рад любым сведениям с анализом файла с Вашей стороны.
    (Очень надеюсь, паника Ikarus'а вся из-за того, что программа перехватывает контроль над устройством ввода - мышью. Раз так, надо бы найти пути обхода подобных «паник»)

    Теперь о хорошем. Собственно, о программе…
    После запуска выводится таблица из 32 строк. Каждая строка отвечает за виртуальное нажатие заданной клавиши, если установленные постулаты справедливы для конкретного события.
    Т.е., в таблице «Volume-Up»/«Volume-Down» сразу закрепляются за дополнительными кнопками мышек #1 и #2 через флажки «B» и «F». Так как в колонках «Ext»/«Safe»/«Game» имеются прочерки, значит события будут срабатывать в любом режиме.
    Из «Help/About» можно заметить, что режимов всего четыре:
    1. «Ctrl+Shift+D» - Обычный режим
    2. «Ctrl+Shift+E» - Расширенный режим
    3. «Ctrl+Shift+F» - Безопасный режим «заморозки»
    4. «Ctrl+Shift+G» - Игровой режим
    Режимами можно управлять и правым кликом по значку в трее.

    После первой активности любой из мышек (когда их несколько) через клик или перемещение, в окне появляется индивидуальная закладка индивидуальных настроек конкретной мышки.
    Так, в группе «Active status» отображается состояние конкретной мышки через флажки в виде виртуальных кнопок. Перемещая мышь, кликая её кнопками и прокручивая колёсики можно легко разобраться, какой флажок отвечает за конкретное действие, что поможет верно выставить нужные флажки в строках таблицы…
    Группа «Properties» отвечает за управление политикой оперативности мышки. Здесь любой флажок нажимается левым кликом, а снимается - правым. Изначально все флажки там вжаты, кроме «Side buttons», что означает отключение срабатывания боковых (дополнительных) кнопок во всех программах. Так как в таблице уже стоят флажки «B» и «F» для управления общей громкостью боковыми кнопками мышки, то разумно их и отключить во всех остальных программах.
    Управлять можно всем. В частности, если нужно, отключить среднюю кнопку мышки или колёсико. Например, сменив управление громкостью с боковых кнопок на вращение колёсиком. Для этого достаточно в нужных строчках таблицы снять флаги «B» и «F», заменив их соответственно на флаги «y» и «v». Причём, флаги должны быть именно строчными буквами. Поэкспериментируйте и поймёте, почему…
    (Внимание! В активном окне программы никакие клавиши таблицы срабатывать не будут! Откройте, хотя бы, окно диалога «Help/About» или переключитесь в «Блокнот», чтобы проверить работу настроек в действии…)
    (Внимание!!! Очень опасно снимать флаги кнопки «Left» или «Moving». За пределами утилиты, соответственно, левая кнопка мышки прекратит работать или даже перещение указателя станет невозможным…)
    Спиннер управляет скоростью перемещения конкретного указателя. Скорость устанавливается только очередным нажатием по флажку «Moving». Причём, проверить скорость можно только активировав другое окно. Например, всё тот же «Блокнот»…
    Флажки «Extended»/«Gaming»/«Freezing» просто выбирают все те режимы, при которых иконка указателя будет отображаться в остальных программах тоже.
    Группа «Pointer» просто служит для просмотра конкретной иконки и выбора её размера спиннером, где 10 - 100%, а 40 - 400% размера соответственно. Правым кликом можно вызвать меню выбора нужного изображения указателя с его новым выбранным размером.

    В меню указателей можно найти весь системный набор, а также цифры, пару государственных флагов и нашего Винни Пуха!
    (Нужно сказать, что в интернете крайне мало персонажей наших мультиков с прозрачным фоном. Пришлось повозиться и в каждом кадре удалить вручную весь фон за медвежёнком…)
    Заметил один глюк с иконками флагов: Они отображаются, почему-то, мерцающими и с артефактами. Скачивал с одного сайта специально весь набор флагов всех государств. И все они выводятся моей программой с артефактами. Если кто-то знает причину - откройте тайну пожалуйста!
    (Флаг России я немного отредактировал и он отображается не так глючно…)
    Причём все остальные указатели с других сайтов и анимашки, сконвертированные из gif в ani, как видно, не имеют артефактов…

    P.S.: В общем, сделал всё как мог. Работает и утечек памяти не заметил…
    Желательно программу не сворачивать в трей, если не уверены в своих настройках.
    Меня, в частности, «вдохновляла» утилита SlyControl, которая тоже не так легка в настройке, если пользовались.
    Следующим шагом по развитию программы будет прикрутка к ней «Белочки», которая стабильно уж 4 года в режиме 24/7/365 обрабатывает 25 раз в секунду сценарий в моей самопальной DVR-оболочке. Тем самым, имея опыт с обработкой каждого кадра и глушением многих помех (от мухи в объективе до сбоя синхронизации аналоговой камеры от стартёров ламп дневного света), будет легче заменить сложную таблицу первой закладки на текстовое окошко с редактированием сценария.
    Думаю, можно будет описывать сценарии простых игр с использованием нескольких мышек и динамическим преобразованием иконок курсоров с выявлением их столкновений на экране…
    (Когда в квартире обитают карапузы, хочется и обезопасить систему, и угодить им, вручив каждому по мышке! Пусть развлекаются!)
    P.P.S.: Раньше я коллекционировал прикольные программки с персонажами бегающими и прыгающими по всему экрану… Теперь, спустя 15 лет, даже и не верится, что написал нечто подобное, да ещё и утилитарное (в опытных руках)…
    Когда будут устранены всякие мелкие (и не очень) недочёты, исходный текст выложу на страничку проекта, где он сразу станет историей, так как я начну его переделывать под «Белочку»…
     

    Вложения:

    • Gestureo.zip
      Размер файла:
      553,3 КБ
      Просмотров:
      397
    Последнее редактирование: 14 авг 2017