Ya Zaregalsya
28.12.2020, 13:02
Приобрёл мышь с кучей кнопок (ЛКМ, ПКМ, СКМ и пять дополнительных). Так сложилось, что для нормального её использования мне необходимо переставить левый и правый клики на 3-ю и 4-ю доп. кнопки мыши. Так сейчас выглядят настройки драйвера:
https://i.yapx.ru/KSB6M.png
Button 4-8 — это те самые доп. кнопки (далее будем называть их X/XBUTTON), всего их пять. Button 4 — это X1; Button 8 — это X5. Необходимо назначить клики именно на X3 и X4, ни одна другая для этой задачи не подходит. Собственно, в настройках это и сделано.
Но вот проблема. Как оказалось, Windows полноценно поддерживает не более двух дополнительных кнопок. Из-за этого X1 и X2 работают во всех приложениях, а X3, X4 и X5 работают только в половине, остальные их игнорируют.
Задача: Поймать нажатия этих кнопок в GTA SA. Хотелось бы конечно заставить их работать во всех приложениях, но если бы это было так легко, то это сделал бы производитель.
Препятствия: У меня почти нет опыта в работе с API Windows и драйверами, а решение проблемы находится за стенами интерфейсов, с которыми я имел дело. Вот есть список кодов клавиш, там есть X1 и X2, но нет X3, X4, X5. И всё, тут лоб врезается в стену.
https://forum.antichat.xyz/attachments/27634778/
Надежда: Как минимум в ГТА это точно возможно сделать. Очень много приложений работают с этими кнопками без нареканий. Далее несколько примеров.
Доп. кнопки поддерживаются: блокнот, раб. стол, Google Chrome, Visual Studio, Blender (https://www.blast.hk/redirect/aHR0cHM6Ly9kZXZlbG9wZXIuYmxlbmRlci5vcmcvZGlmZnVzaW 9uL0Iv), NotePad++ (https://github.com/notepad-plus-plus/notepad-plus-plus), MagicTXD (https://github.com/quiret/magic-txd).
Доп. кнопки не поддерживаются: диспетчер задач, редактор реестра, SciTe4AutoHotKey, клиент SAMP, GTA SA.
Код некоторых из них размещён в открытом доступе. Моих знаний, увы, пока недостаточно, чтобы быстро разобраться, за счёт чего они это делают. Но если более опытный разработчик взглянет на эти примеры, то наверно сможет выяснить ответ, MagicTXD — наиболее легковесный и близкий к ГТА образец. А пока что вместо мыши кирпич.
Ya Zaregalsya
29.12.2020, 14:15
Прогресс:
• Граф. интерфейс пользователя в MagicTXD реализован не голыми руками через какой-нибудь OpenGL, а через всем известный фреймворк Qt.
• У Qt есть своя вики, находим там страницу, где описаны все идентификаторы основного пространства имён. Первым делом внимание падает на перечисление MouseButton (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xdC5odG1sI01vdXNlQn V0dG9uLWVudW0). Там указаны заветные дополнительные кнопки. Здесь уже прослеживается описанная выше логика: из всех доп. кнопок первые две — особенные.
• Там же указаны ExtraButton3 и ExtraButton4. Пока оставим в стороне почему третья кнопка имеет дополнительное название, но это неожиданно.
• Тут вступает в дело нехватка моей квалификации. Я никогда не работал с указателями в виде литералов, только под видом переменных. Пока предположу, что они обозначают смещение от какого-то другого адреса: XAddress + 0x00000020 = ExtraButton 3. Дальше нужно искать XAddress.
Ya Zaregalsya
29.12.2020, 15:44
• Исходники Qt опубликованы на ГитХабе (https://github.com/qt/qtbase/tree/dev/src). Файлы по искомой теме:
qwindow.cpp (https://www.blast.hk/redirect/aHR0cHM6Ly9jb2RlLndvYm9xLm9yZy9xdDUvcXRiYXNlL3NyYy 9ndWkva2VybmVsL3F3aW5kb3cuY3BwLmh0bWw)/.h;
qeventloop.cpp (https://www.blast.hk/redirect/aHR0cHM6Ly9jb2RlLndvYm9xLm9yZy9xdDUvcXRiYXNlL3NyYy 9jb3JlbGliL2tlcm5lbC9xZXZlbnRsb29wLmNwcC5odG1s)/.h;
qabstracteventdistatcher.cpp (https://www.blast.hk/redirect/aHR0cHM6Ly9jb2RlLndvYm9xLm9yZy9xdDUvcXRiYXNlL3NyYy 9jb3JlbGliL2tlcm5lbC9xYWJzdHJhY3RldmVudGRpc3BhdGNo ZXIuY3BwLmh0bWw)/.h;
qcoreapplication.cpp (https://www.blast.hk/redirect/aHR0cHM6Ly9jb2RlLndvYm9xLm9yZy9xdDUvcXRiYXNlL3NyYy 9jb3JlbGliL2tlcm5lbC9xY29yZWFwcGxpY2F0aW9uLmNwcC5o dG1s)/.h (https://github.com/qt/qtbase/blob/dev/src/corelib/kernel/qcoreapplication.h);
qguiapplication.cpp (https://github.com/qt/qtbase/blob/dev/src/gui/kernel/qguiapplication.cpp)/.h (https://github.com/qt/qtbase/blob/dev/src/gui/kernel/qguiapplication.h);
qwindowsysteminterface.cpp (https://www.blast.hk/redirect/aHR0cHM6Ly9jb2RlLndvYm9xLm9yZy9xdDUvcXRiYXNlL3NyYy 9ndWkva2VybmVsL3F3aW5kb3dzeXN0ZW1pbnRlcmZhY2UuY3Bw Lmh0bWw)/.h/_p.h (https://www.blast.hk/redirect/aHR0cHM6Ly9jb2RlLndvYm9xLm9yZy9xdDUvcXRiYXNlL3NyYy 9ndWkva2VybmVsL3F3aW5kb3dzeXN0ZW1pbnRlcmZhY2VfcC5o Lmh0bWw)(судя по всему, здесь Qt захватывает события из Windows);
qcoreevent.cpp (https://github.com/qt/qtbase/blob/dev/src/corelib/kernel/qcoreevent.cpp)/.h (https://github.com/qt/qtbase/blob/dev/src/corelib/kernel/qcoreevent.h) (здесь реализован класс QEvent);
qevent.cpp (https://github.com/qt/qtbase/blob/dev/src/gui/kernel/qevent.cpp)/.h (https://github.com/qt/qtbase/blob/dev/src/gui/kernel/qevent.h) (QInputEvent, QMouseEvent);
qinputdevice.cpp (https://github.com/qt/qtbase/blob/dev/src/gui/kernel/qinputdevice.cpp)/.h (https://github.com/qt/qtbase/blob/dev/src/gui/kernel/qinputdevice.h);
qwindowsmousehandler.cpp (https://www.blast.hk/redirect/aHR0cHM6Ly9jb2RlLndvYm9xLm9yZy9xdDUvcXRiYXNlL3NyYy 9wbHVnaW5zL3BsYXRmb3Jtcy93aW5kb3dzL3F3aW5kb3dzbW91 c2VoYW5kbGVyLmNwcC5odG1s)/.h (https://www.blast.hk/redirect/aHR0cHM6Ly9jb2RlLndvYm9xLm9yZy9xdDUvcXRiYXNlL3NyYy 9wbHVnaW5zL3BsYXRmb3Jtcy93aW5kb3dzL3F3aW5kb3dzbW91 c2VoYW5kbGVyLmguaHRtbA);
https://code.woboq.org/qt5/qtbase/s...entLoop4execE6QFlagsINS_17ProcessEventsFlagEE (https://www.blast.hk/redirect/aHR0cHM6Ly9jb2RlLndvYm9xLm9yZy9xdDUvcXRiYXNlL3NyYy 9jb3JlbGliL2tlcm5lbC9xZXZlbnRsb29wLmNwcC5odG1sI19a TjEwUUV2ZW50TG9vcDRleGVjRTZRRmxhZ3NJTlNfMTdQcm9jZX NzRXZlbnRzRmxhZ0VF)
https://code.woboq.org/qt5/qtbase/src/gui/kernel/qguiapplication.cpp.html#1896 (https://www.blast.hk/redirect/aHR0cHM6Ly9jb2RlLndvYm9xLm9yZy9xdDUvcXRiYXNlL3NyYy 9ndWkva2VybmVsL3FndWlhcHBsaWNhdGlvbi5jcHAuaHRtbCMx ODk2)(а здесь Qt уже разбирает события Windows);
https://code.woboq.org/qt5/qtbase/s...SystemInterfacePrivate::WindowSystemEventList (https://www.blast.hk/redirect/aHR0cHM6Ly9jb2RlLndvYm9xLm9yZy9xdDUvcXRiYXNlL3NyYy 9ndWkva2VybmVsL3F3aW5kb3dzeXN0ZW1pbnRlcmZhY2VfcC5o Lmh0bWwjUVdpbmRvd1N5c3RlbUludGVyZmFjZVByaXZhdGU6Ol dpbmRvd1N5c3RlbUV2ZW50TGlzdA)
https://code.woboq.org/qt5/qtbase/s...dowSystemInterfacePrivate17WindowSystemEventE (https://www.blast.hk/redirect/aHR0cHM6Ly9jb2RlLndvYm9xLm9yZy9xdDUvcXRiYXNlL3NyYy 9ndWkva2VybmVsL3FndWlhcHBsaWNhdGlvbi5jcHAuaHRtbCNf Wk4yMlFHdWlBcHBsaWNhdGlvblByaXZhdGUyNHByb2Nlc3NXaW 5kb3dTeXN0ZW1FdmVudEVQTjI5UVdpbmRvd1N5c3RlbUludGVy ZmFjZVByaXZhdGUxN1dpbmRvd1N5c3RlbUV2ZW50RQ)
QEvent
|
QInputEvent
|
QPointerEvent
|
QSinglePointEvent
|
QMouseEvent
/*!
\class QEvent
\inmodule QtCore
\brief The QEvent class is the base class of all
event classes. Event objects contain event parameters.
\ingroup events
Qt's main event loop (QCoreApplication::exec()) fetches native
window system events from the event queue, translates them into
QEvents, and sends the translated events to \l{QObject}s.
In general, events come from the underlying window system
(spontaneous() returns \c true), but it is also possible to manually
send events using QCoreApplication::sendEvent() and
QCoreApplication::postEvent() (spontaneous() returns \c false).
\l {QObject}{QObjects} receive events by having their QObject::event() function
called. The function can be reimplemented in subclasses to
customize event handling and add additional event types;
QWidget::event() is a notable example. By default, events are
dispatched to event handlers like QObject::timerEvent() and
QWidget::mouseMoveEvent(). QObject::installEventFilter() allows an
object to intercept events destined for another object.
The basic QEvent contains only an event type parameter and an
"accept" flag. The accept flag set with accept(), and cleared
with ignore(). It is set by default, but don't rely on this as
subclasses may choose to clear it in their constructor.
Subclasses of QEvent contain additional parameters that describe
the particular event.
\sa QObject::event(), QObject::installEventFilter(),
QCoreApplication::sendEvent(),
QCoreApplication::postEvent(), QCoreApplication::processEvents()
*/
Detailed DescriptionThis class is used by non-GUI applications to provide their event loop. For non-GUI application that uses Qt, there should be exactly one QCoreApplication object. For GUI applications, seeQGuiApplication (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xZ3VpYXBwbGljYXRpb2 4uaHRtbA). For applications that use the Qt Widgets module, see QApplication (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xYXBwbGljYXRpb24uaH RtbA).
QCoreApplication contains the main event loop, where all events from the operating system (e.g., timer and network events) and other sources are processed and dispatched. It also handles the application's initialization and finalization, as well as system-wide and application-wide settings.
The Event Loop and Event HandlingThe event loop is started with a call to exec (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xY29yZWFwcGxpY2F0aW 9uLmh0bWwjZXhlYw)(). Long-running operations can call processEvents (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xY29yZWFwcGxpY2F0aW 9uLmh0bWwjcHJvY2Vzc0V2ZW50cw)() to keep the application responsive.
In general, we recommend that you create a QCoreApplication, QGuiApplication (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xZ3VpYXBwbGljYXRpb2 4uaHRtbA) or a QApplication (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xYXBwbGljYXRpb24uaH RtbA) object in your main() function as early as possible. exec (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xY29yZWFwcGxpY2F0aW 9uLmh0bWwjZXhlYw)() will not return until the event loop exits; e.g., when quit (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xY29yZWFwcGxpY2F0aW 9uLmh0bWwjcXVpdA)() is called.
Several static convenience functions are also provided. The QCoreApplication object is available from instance (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xY29yZWFwcGxpY2F0aW 9uLmh0bWwjaW5zdGFuY2U)(). Events can be sent with sendEvent (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xY29yZWFwcGxpY2F0aW 9uLmh0bWwjc2VuZEV2ZW50)() or posted to an event queue with postEvent (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xY29yZWFwcGxpY2F0aW 9uLmh0bWwjcG9zdEV2ZW50)(). Pending events can be removed with removePostedEvents (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xY29yZWFwcGxpY2F0aW 9uLmh0bWwjcmVtb3ZlUG9zdGVkRXZlbnRz)() or dispatched with sendPostedEvents (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xY29yZWFwcGxpY2F0aW 9uLmh0bWwjc2VuZFBvc3RlZEV2ZW50cw)().
The class provides a quit (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xY29yZWFwcGxpY2F0aW 9uLmh0bWwjcXVpdA)() slot and an aboutToQuit (https://www.blast.hk/redirect/aHR0cHM6Ly9kb2MucXQuaW8vcXQtNS9xY29yZWFwcGxpY2F0aW 9uLmh0bWwjYWJvdXRUb1F1aXQ)() signal.
C++:
void
QGuiApplicationPrivate
::
processWindowSystemEvent
(
QWindowSystemInterfacePrivate
::
WindowSystemEvent
*
e
)
{
Q_TRACE_SCOPE
(
QGuiApplicationPrivate_processWindowSystemEvent
,
e
->
type
)
;
switch
(
e
->
type
)
{
case
QWindowSystemInterfacePrivate
::
Mouse
:
QGuiApplicationPrivate
::
processMouseEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
Wheel
:
QGuiApplicationPrivate
::
processWheelEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
Key
:
QGuiApplicationPrivate
::
processKeyEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
Touch
:
QGuiApplicationPrivate
::
processTouchEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
GeometryChange
:
QGuiApplicationPrivate
::
processGeometryChangeEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
Enter
:
QGuiApplicationPrivate
::
processEnterEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
Leave
:
QGuiApplicationPrivate
::
processLeaveEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
ActivatedWindow
:
QGuiApplicationPrivate
::
processActivatedEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
WindowStateChanged
:
QGuiApplicationPrivate
::
processWindowStateChangedEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
WindowScreenChanged
:
QGuiApplicationPrivate
::
processWindowScreenChangedEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
SafeAreaMarginsChanged
:
QGuiApplicationPrivate
::
processSafeAreaMarginsChangedEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
ApplicationStateChanged
:
{
QWindowSystemInterfacePrivate
::
ApplicationStateChangedEvent
*
changeEvent
=
static_cast
(
e
)
;
QGuiApplicationPrivate
::
setApplicationState
(
changeEvent
->
newState
,
changeEvent
->
forcePropagate
)
;
}
break
;
case
QWindowSystemInterfacePrivate
::
FlushEvents
:
{
QWindowSystemInterfacePrivate
::
FlushEventsEvent
*
flushEventsEvent
=
static_cast
(
e
)
;
QWindowSystemInterface
::
deferredFlushWindowSystemEvents
(
flushEventsEvent
->
flags
)
;
}
break
;
case
QWindowSystemInterfacePrivate
::
Close
:
QGuiApplicationPrivate
::
processCloseEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
ScreenOrientation
:
QGuiApplicationPrivate
::
processScreenOrientationChange
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
ScreenGeometry
:
QGuiApplicationPrivate
::
processScreenGeometryChange
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
ScreenLogicalDotsPerInch
:
QGuiApplicationPrivate
::
processScreenLogicalDotsPerInchChange
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
ScreenRefreshRate
:
QGuiApplicationPrivate
::
processScreenRefreshRateChange
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
ThemeChange
:
QGuiApplicationPrivate
::
processThemeChanged
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
Expose
:
QGuiApplicationPrivate
::
processExposeEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
Tablet
:
QGuiApplicationPrivate
::
processTabletEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
TabletEnterProximity
:
QGuiApplicationPrivate
::
processTabletEnterProximityEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
TabletLeaveProximity
:
QGuiApplicationPrivate
::
processTabletLeaveProximityEvent
(
static_cast
(
e
)
)
;
break
;
#ifndef QT_NO_GESTURES
case
QWindowSystemInterfacePrivate
::
Gesture
:
QGuiApplicationPrivate
::
processGestureEvent
(
static_cast
(
e
)
)
;
break
;
#endif
case
QWindowSystemInterfacePrivate
::
PlatformPanel
:
QGuiApplicationPrivate
::
processPlatformPanelEvent
(
static_cast
(
e
)
)
;
break
;
case
QWindowSystemInterfacePrivate
::
FileOpen
:
QGuiApplicationPrivate
::
processFileOpenEvent
(
static_cast
(
e
)
)
;
break
;
#ifndef QT_NO_CONTEXTMENU
case
QWindowSystemInterfacePrivate
::
ContextMenu
:
QGuiApplicationPrivate
::
processContextMenuEvent
(
static_cast
(
e
)
)
;
break
;
#endif
case
QWindowSystemInterfacePrivate
::
EnterWhatsThisMode
:
QGuiApplication
::
postEvent
(
QGuiApplication
::
instance
(
)
,
new
QEvent
(
QEvent
::
EnterWhatsThisMode
)
)
;
break
;
default
:
qWarning
(
)
type
;
break
;
}
}
C++:
void
QGuiApplicationPrivate
::
processMouseEvent
(
QWindowSystemInterfacePrivate
::
MouseEvent
*
e
)
{
QEvent
::
Type type
=
QEvent
::
None
;
Qt
::
MouseButton button
=
Qt
::
NoButton
;
QWindow
*
window
=
e
->
window
.
data
(
)
;
bool
positionChanged
=
QGuiApplicationPrivate
::
lastCursorPosition
!=
e
->
globalPos
;
bool
mouseMove
=
false
;
bool
mousePress
=
false
;
if
(
e
->
enhancedMouseEvent
(
)
)
{
type
=
e
->
buttonType
;
button
=
e
->
button
;
if
(
type
==
QEvent
::
NonClientAreaMouseMove
||
type
==
QEvent
::
MouseMove
)
mouseMove
=
true
;
else
if
(
type
==
QEvent
::
NonClientAreaMouseButtonPress
||
type
==
QEvent
::
MouseButtonPress
)
mousePress
=
true
;
if
(
!
mouseMove
&&
positionChanged
)
{
QWindowSystemInterfacePrivate
::
MouseEvent
moveEvent
(
window
,
e
->
timestamp
,
e
->
localPos
,
e
->
globalPos
,
e
->
buttons
^
button
,
e
->
modifiers
,
Qt
::
NoButton
,
e
->
nonClientArea
?
QEvent
::
NonClientAreaMouseMove
:
QEvent
::
MouseMove
,
e
->
source
,
e
->
nonClientArea
)
;
if
(
e
->
synthetic
(
)
)
moveEvent
.
flags
|=
QWindowSystemInterfacePrivate
::
WindowSystemEvent
::
Synthetic
;
processMouseEvent
(
&
moveEvent
)
;
// mouse move excluding state change
processMouseEvent
(
e
)
;
// the original mouse event
return
;
}
}
else
{
Qt
::
MouseButtons stateChange
=
e
->
buttons
^
mouse_buttons
;
if
(
positionChanged
&&
(
stateChange
!=
Qt
::
NoButton
)
)
{
QWindowSystemInterfacePrivate
::
MouseEvent
moveEvent
(
window
,
e
->
timestamp
,
e
->
localPos
,
e
->
globalPos
,
mouse_buttons
,
e
->
modifiers
,
Qt
::
NoButton
,
QEvent
::
None
,
e
->
source
,
e
->
nonClientArea
)
;
if
(
e
->
synthetic
(
)
)
moveEvent
.
flags
|=
QWindowSystemInterfacePrivate
::
WindowSystemEvent
::
Synthetic
;
processMouseEvent
(
&
moveEvent
)
;
// mouse move excluding state change
processMouseEvent
(
e
)
;
// the original mouse event
return
;
}
// In the compatibility path we deduce event type and button that caused the event
if
(
positionChanged
)
{
mouseMove
=
true
;
type
=
e
->
nonClientArea
?
QEvent
::
NonClientAreaMouseMove
:
QEvent
::
MouseMove
;
}
else
{
// Check to see if a new button has been pressed/released.
for
(
uint mask
=
Qt
::
LeftButton
;
mask
buttons
)
{
mousePress
=
true
;
type
=
e
->
nonClientArea
?
QEvent
::
NonClientAreaMouseButtonPress
:
QEvent
::
MouseButtonPress
;
}
else
{
type
=
e
->
nonClientArea
?
QEvent
::
NonClientAreaMouseButtonRelease
:
QEvent
::
MouseButtonRelease
;
}
}
}
modifier_buttons
=
e
->
modifiers
;
QPointF localPoint
=
e
->
localPos
;
QPointF globalPoint
=
e
->
globalPos
;
bool
doubleClick
=
false
;
if
(
mouseMove
)
{
QGuiApplicationPrivate
::
lastCursorPosition
=
globalPoint
;
const
auto
doubleClickDistance
=
e
->
source
==
Qt
::
MouseEventNotSynthesized
?
mouseDoubleClickDistance
:
touchDoubleTapDistance
;
if
(
qAbs
(
globalPoint
.
x
(
)
-
mousePressX
)
>
doubleClickDistance
||
qAbs
(
globalPoint
.
y
(
)
-
mousePressY
)
>
doubleClickDistance
)
mousePressButton
=
Qt
::
NoButton
;
}
else
{
mouse_buttons
=
e
->
buttons
;
if
(
mousePress
)
{
ulong doubleClickInterval
=
static_cast
(
QGuiApplication
::
styleHints
(
)
->
mouseDoubleClickInterval
(
)
)
;
doubleClick
=
e
->
timestamp
-
mousePressTime
timestamp
;
mousePressButton
=
button
;
const
QPoint point
=
QGuiApplicationPrivate
::
lastCursorPosition
.
toPoint
(
)
;
mousePressX
=
point
.
x
(
)
;
mousePressY
=
point
.
y
(
)
;
}
}
if
(
e
->
nullWindow
(
)
)
{
window
=
QGuiApplication
::
topLevelAt
(
globalPoint
.
toPoint
(
)
)
;
if
(
window
)
{
// Moves and the release following a press must go to the same
// window, even if the cursor has moved on over another window.
if
(
e
->
buttons
!=
Qt
::
NoButton
)
{
if
(
!
currentMousePressWindow
)
currentMousePressWindow
=
window
;
else
window
=
currentMousePressWindow
;
}
else
if
(
currentMousePressWindow
)
{
window
=
currentMousePressWindow
;
currentMousePressWindow
=
0
;
}
QPointF delta
=
globalPoint
-
globalPoint
.
toPoint
(
)
;
localPoint
=
window
->
mapFromGlobal
(
globalPoint
.
toPoint
(
)
)
+
delta
;
}
}
if
(
!
window
)
return
;
#ifndef QT_NO_CURSOR
if
(
!
e
->
synthetic
(
)
)
{
if
(
const
QScreen
*
screen
=
window
->
screen
(
)
)
if
(
QPlatformCursor
*
cursor
=
screen
->
handle
(
)
->
cursor
(
)
)
{
const
QPointF nativeLocalPoint
=
QHighDpi
::
toNativePixels
(
localPoint
,
screen
)
;
const
QPointF nativeGlobalPoint
=
QHighDpi
::
toNativePixels
(
globalPoint
,
screen
)
;
QMouseEvent
ev
(
type
,
nativeLocalPoint
,
nativeLocalPoint
,
nativeGlobalPoint
,
button
,
e
->
buttons
,
e
->
modifiers
,
e
->
source
)
;
ev
.
setTimestamp
(
e
->
timestamp
)
;
cursor
->
pointerEvent
(
ev
)
;
}
}
#endif
QMouseEvent
ev
(
type
,
localPoint
,
localPoint
,
globalPoint
,
button
,
e
->
buttons
,
e
->
modifiers
,
e
->
source
)
;
ev
.
setTimestamp
(
e
->
timestamp
)
;
if
(
window
->
d_func
(
)
->
blockedByModalWindow
&&
!
qApp
->
d_func
(
)
->
popupActive
(
)
)
{
// a modal window is blocking this window, don't allow mouse events through
return
;
}
if
(
doubleClick
&&
(
ev
.
type
(
)
==
QEvent
::
MouseButtonPress
)
)
{
// QtBUG-25831, used to suppress delivery in qwidgetwindow.cpp
setMouseEventFlags
(
&
ev
,
ev
.
flags
(
)
|
Qt
::
MouseEventCreatedDoubleClick
)
;
}
QGuiApplication
::
sendSpontaneousEvent
(
window
,
&
ev
)
;
e
->
eventAccepted
=
ev
.
isAccepted
(
)
;
if
(
!
e
->
synthetic
(
)
&&
!
ev
.
isAccepted
(
)
&&
!
e
->
nonClientArea
&&
qApp
->
testAttribute
(
Qt
::
AA_SynthesizeTouchForUnhandledMouseEvents
)
)
{
if
(
!
m_fakeTouchDevice
)
{
m_fakeTouchDevice
=
new
QTouchDevice
;
QWindowSystemInterface
::
registerTouchDevice
(
m_fakeTouchDevice
)
;
}
QList
points
;
QWindowSystemInterface
::
TouchPoint point
;
point
.
id
=
1
;
point
.
area
=
QRectF
(
globalPoint
.
x
(
)
-
2
,
globalPoint
.
y
(
)
-
2
,
4
,
4
)
;
// only translate left button related events to
// avoid strange touch event sequences when several
// buttons are pressed
if
(
type
==
QEvent
::
MouseButtonPress
&&
button
==
Qt
::
LeftButton
)
{
point
.
state
=
Qt
::
TouchPointPressed
;
}
else
if
(
type
==
QEvent
::
MouseButtonRelease
&&
button
==
Qt
::
LeftButton
)
{
point
.
state
=
Qt
::
TouchPointReleased
;
}
else
if
(
type
==
QEvent
::
MouseMove
&&
(
e
->
buttons
&
Qt
::
LeftButton
)
)
{
point
.
state
=
Qt
::
TouchPointMoved
;
}
else
{
return
;
}
points
touchPoints
=
QWindowSystemInterfacePrivate
::
fromNativeTouchPoints
(
points
,
window
,
QTouchDevicePrivate
::
get
(
m_fakeTouchDevice
)
->
id
,
&
type
)
;
QWindowSystemInterfacePrivate
::
TouchEvent
fake
(
window
,
e
->
timestamp
,
type
,
m_fakeTouchDevice
,
touchPoints
,
e
->
modifiers
)
;
fake
.
flags
|=
QWindowSystemInterfacePrivate
::
WindowSystemEvent
::
Synthetic
;
processTouchEvent
(
&
fake
)
;
}
if
(
doubleClick
)
{
mousePressButton
=
Qt
::
NoButton
;
if
(
!
e
->
window
.
isNull
(
)
||
e
->
nullWindow
(
)
)
{
// QTBUG-36364, check if window closed in response to press
const
QEvent
::
Type doubleClickType
=
e
->
nonClientArea
?
QEvent
::
NonClientAreaMouseButtonDblClick
:
QEvent
::
MouseButtonDblClick
;
QMouseEvent
dblClickEvent
(
doubleClickType
,
localPoint
,
localPoint
,
globalPoint
,
button
,
e
->
buttons
,
e
->
modifiers
,
e
->
source
)
;
dblClickEvent
.
setTimestamp
(
e
->
timestamp
)
;
QGuiApplication
::
sendSpontaneousEvent
(
window
,
&
dblClickEvent
)
;
}
}
}
Ya Zaregalsya
23.01.2021, 02:18
Я провозился с этими кнопками месяц, потратил 60-70 часов времени, разочаровался в IT, в человечестве, проклял всю Кремневую долину и японскую нацию, готовился изучать микроконтроллеры и писать драйвер с нуля.
Оказывается, нужно было всего лишь запустить софт для мыши от имени администратора (https://www.blast.hk/redirect/aHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMz QxMDkzNDUva2V5YmQtZXZlbnQtbm90LXdvcmtpbmctZm9yLXNv bWUtYXBwbGljYXRpb25z).
Спасибо всем специалистам Бластхака за неоценимую помощь!
vBulletin® v3.8.14, Copyright ©2000-2026, vBulletin Solutions, Inc. Перевод: zCarot