Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
mahuifa
QMDemo
提交
1cc5afe1
Q
QMDemo
项目概览
mahuifa
/
QMDemo
通知
1
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
QMDemo
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
1cc5afe1
编写于
12月 01, 2022
作者:
mahuifa
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'Dev'
上级
3522f475
177b16ab
变更
14
展开全部
隐藏空白更改
内联
并排
Showing
14 changed file
with
960 addition
and
84 deletion
+960
-84
FunctionalModule/FunctionalModule.md
FunctionalModule/FunctionalModule.md
+15
-1
FunctionalModule/MouseKeyEvent/GlobalMouseKey/GlobalMouseKey.pri
...nalModule/MouseKeyEvent/GlobalMouseKey/GlobalMouseKey.pri
+21
-0
FunctionalModule/MouseKeyEvent/GlobalMouseKey/globalkeyevent.h
...ionalModule/MouseKeyEvent/GlobalMouseKey/globalkeyevent.h
+34
-0
FunctionalModule/MouseKeyEvent/GlobalMouseKey/globalkeyevent_win.cpp
...odule/MouseKeyEvent/GlobalMouseKey/globalkeyevent_win.cpp
+517
-0
FunctionalModule/MouseKeyEvent/GlobalMouseKey/globalkeyevent_x11.cpp
...odule/MouseKeyEvent/GlobalMouseKey/globalkeyevent_x11.cpp
+198
-0
FunctionalModule/MouseKeyEvent/GlobalMouseKey/globalmouseevent.h
...nalModule/MouseKeyEvent/GlobalMouseKey/globalmouseevent.h
+9
-1
FunctionalModule/MouseKeyEvent/GlobalMouseKey/globalmouseevent_win.cpp
...ule/MouseKeyEvent/GlobalMouseKey/globalmouseevent_win.cpp
+6
-7
FunctionalModule/MouseKeyEvent/GlobalMouseKey/globalmouseevent_x11.cpp
...ule/MouseKeyEvent/GlobalMouseKey/globalmouseevent_x11.cpp
+15
-14
FunctionalModule/MouseKeyEvent/MouseKeyEvent.pro
FunctionalModule/MouseKeyEvent/MouseKeyEvent.pro
+4
-2
FunctionalModule/MouseKeyEvent/widget.cpp
FunctionalModule/MouseKeyEvent/widget.cpp
+69
-22
FunctionalModule/MouseKeyEvent/widget.h
FunctionalModule/MouseKeyEvent/widget.h
+7
-1
FunctionalModule/MouseKeyEvent/widget.ui
FunctionalModule/MouseKeyEvent/widget.ui
+58
-28
QSqlDemo/QSqlDemo.pro
QSqlDemo/QSqlDemo.pro
+6
-7
QSqlDemo/RelationalTableModel/main.cpp
QSqlDemo/RelationalTableModel/main.cpp
+1
-1
未找到文件。
FunctionalModule/FunctionalModule.md
浏览文件 @
1cc5afe1
...
...
@@ -17,6 +17,7 @@
| WindowRect | 框选鼠标当前位置窗口范围(类似窗口截图) | Windows、Linux |
| MouseKeyEvent | Qt实现自定义全局鼠标键盘事件监听器Demo | Windows |
| SnippingTool | Qt实现截图工具 | Windows、Linux |
| MouseKeyEvent | Qt全局鼠标、键盘事件监听器 | Windows、Linux |
...
...
@@ -166,4 +167,17 @@ Qt自身的鼠标事件、事件过滤器一般当鼠标移出窗口或者遇见
> 5. 使用自定义全局 鼠标事件监听器解决截图时窗口透明导致的鼠标穿透而无法捕捉到鼠标事件问题。
> 6. Windows下使用user32获取鼠标所在位置窗口大小,Linux下使用x11获取鼠标所在位置窗口大小。
![
image-20221121125725058
](
FunctionalModule.assets/image-20221121125725058.png
)
\ No newline at end of file
![
image-20221121125725058
](
FunctionalModule.assets/image-20221121125725058.png
)
### 1.10 MouseKeyEvent
> 1. windows下使用鼠标钩子实现全局鼠标监听功能;
> 2. 通过封装将Windows鼠标信号转换成Qt鼠标信号;
> 3. Linux下使用X11实现全局鼠标事件监听功能;
> 4. 通过封装将X11鼠标信号转换为Qt鼠标信号(功能比Windows鼠标钩子强);
> 5. Windows下实现全局键盘事件监听器功能;
> 6. Linux下通过x11 API获取到全局键盘事件,但是无法将x11键盘事件映射为QKeyEvent。
![
MouseKeyEvent
](
FunctionalModule.assets/MouseKeyEvent.gif
)
\ No newline at end of file
FunctionalModule/MouseKeyEvent/GlobalMouseKey/GlobalMouseKey.pri
浏览文件 @
1cc5afe1
#---------------------------------------------------------------------------------------
# @功能: 封装的跨平台Qt全局鼠标、键盘事件监听器类
# | 功能 | 系统 | 是否实现 | 实现方式 |
# | 全局鼠标事件监听器 | Windows | 已实现 | user32鼠标钩子 |
# | 全局鼠标事件监听器 | Linux | 已实现 | x11 API |
# | 全局键盘事件监听器 | Windows | 已实现 | user32键盘钩子 |
# | 全局键盘事件监听器 | Linux | 未实现 | |
#
# @编译器: Desktop Qt 5.12.5 MSVC2017 64bit(也支持其它编译器)
# @Qt IDE: D:/Qt/Qt5.12.5/Tools/QtCreator/share/qtcreator
#
# @开发者 mhf
# @邮箱 1603291350@qq.com
# @时间 2022-12-01 15:31:51
# @备注 Linux下全局键盘事件监听器通过使用X11 API已经获取到了全局键盘事件,但是不知道怎么将
# X11键盘事件映射为QKeyEvent,通过阅读Qt源码,发现Qt使用的是xcb将xkb映射为QKeyEvent,后续有时间在继续研究。
# Qt源码位置:D:\Qt\Qt5.12.5\5.12.5\Src\qtbase\src\plugins\platforms\xcb\qxcbkeyboard.cpp
#---------------------------------------------------------------------------------------
QT += concurrent
HEADERS += \
$$PWD/globalkeyevent.h \ # 全局键盘事件监听器类头文件
$$PWD/globalmouseevent.h # 全局鼠标事件监听类头文件
SOURCES += \
$$PWD/globalkeyevent_win.cpp \ # Windows全局键盘事件监听器
$$PWD/globalkeyevent_x11.cpp \ # Linux全局键盘事件监听器(未实现)
$$PWD/globalmouseevent_win.cpp \ # windows全局鼠标事件监听器
$$PWD/globalmouseevent_x11.cpp # linux全局鼠标事件监听器
...
...
FunctionalModule/MouseKeyEvent/GlobalMouseKey/globalkeyevent.h
0 → 100644
浏览文件 @
1cc5afe1
#ifndef GLOBALKEYEVENT_H
#define GLOBALKEYEVENT_H
#include <QObject>
class
QKeyEvent
;
/**
* 全局鼠标事件单例信号类
*/
class
GlobalKeyEvent
:
public
QObject
{
Q_OBJECT
public:
static
GlobalKeyEvent
*
getInstance
()
{
static
GlobalKeyEvent
keyEvent
;
return
&
keyEvent
;
}
static
bool
installKeyEvent
();
// 安装全局键盘事件监听器
static
bool
removeKeyEvent
();
// 卸载全局键盘事件监听器
signals:
/**
* @brief 由于传递的是指针,为了保证不会出现内存泄露,需要在槽函数中delete。
* 建议此信号只绑定一次,因为如果绑定多次可能会出现一个槽函数里把信号delete了,另外一个槽函数还在使用,出现野指针,或者多个槽函数多次delete
*/
void
keyEvent
(
QKeyEvent
*
event
);
private:
GlobalKeyEvent
(){}
};
#endif // GLOBALKEYEVENT_H
FunctionalModule/MouseKeyEvent/GlobalMouseKey/globalkeyevent_win.cpp
0 → 100644
浏览文件 @
1cc5afe1
此差异已折叠。
点击以展开。
FunctionalModule/MouseKeyEvent/GlobalMouseKey/globalkeyevent_x11.cpp
0 → 100644
浏览文件 @
1cc5afe1
#include "globalkeyevent.h"
#if defined(Q_OS_LINUX)
#include <QtConcurrent>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/extensions/record.h> // 如果找不到可以安装sudo apt-get install xorg-dev
#include <X11/Xlibint.h>
#if 0
//#include <xcb/xcb_keysyms.h> // sudo apt install libxcb-keysyms1-dev
//#include <xcb/xinput.h> // sudo apt install libxcb-xinput-dev
#include <xkbcommon/xkbcommon.h> // sudo apt install libxkbcommon-dev
#include <xkbcommon/xkbcommon-keysyms.h>
#endif
static
XRecordContext
g_context
=
0
;
static
Display
*
g_display
=
nullptr
;
static
bool
init
()
{
g_display
=
XOpenDisplay
(
nullptr
);
// 打开与控制显示器的X服务器的连接,详细说明看【https://tronche.com/gui/x/xlib/display/opening.html】
if
(
!
g_display
)
{
qWarning
()
<<
"连接X服务失败!"
;
return
false
;
}
XRecordClientSpec
clients
=
XRecordAllClients
;
// 初始化 XRecordCreateContext 所需的 XRecordClientSpec 参数,XRecordAllClients 的意思是 "记录所有 X Client" 的事件
XRecordRange
*
range
=
XRecordAllocRange
();
// 创建 XRecordRange 变量,用于控制记录事件的范围
if
(
!
range
)
{
qDebug
()
<<
"无法分配XRecordRange"
;
return
false
;
}
// 会监听到 first - last之间并包含first和last的所有类型的事件
memset
(
range
,
0
,
sizeof
(
XRecordRange
));
range
->
device_events
.
first
=
KeyPress
;
range
->
device_events
.
last
=
KeyRelease
;
// 根据上面的记录客户端类型和记录事件范围来创建 “记录上下文”
// 然后把 XRecordContext 传递给 XRecordEnableContext 函数来开启事件记录循环
g_context
=
XRecordCreateContext
(
g_display
,
0
,
&
clients
,
1
,
&
range
,
1
);
XFree
(
range
);
if
(
g_context
==
0
)
{
qWarning
()
<<
"创建事件记录上下文失败!"
;
return
false
;
}
XSync
(
g_display
,
false
);
// XSync 的作用就是把上面的X 代码立即发给 X Server,这样 X Server 接受到事件以后会立即发送给 XRecord 的 Client 连接 True
return
true
;
}
/**
* @brief 处理鼠标事件的回调函数,将X11鼠标事件转换为Qt鼠标事件,通过单例类MouseEvent发送出去
* @param ptr
* @param data
*/
static
void
callback
(
XPointer
ptr
,
XRecordInterceptData
*
data
)
{
Q_UNUSED
(
ptr
)
if
(
data
->
category
==
XRecordFromServer
)
{
xEvent
*
event
=
reinterpret_cast
<
xEvent
*>
(
data
->
data
);
// qDebug() << QString("鼠标坐标:[%1, %2]").arg(event->u.keyButtonPointer.rootX).arg(event->u.keyButtonPointer.rootY); // 获取鼠标坐标
switch
(
event
->
u
.
u
.
type
)
// 动作类型
{
case
KeyPress
:
// 键盘按下
{
// QPoint point = QCursor::pos(); // 获取鼠标当前位置
qDebug
()
<<
event
->
u
.
u
.
detail
;
switch
(
event
->
u
.
u
.
detail
)
// 按键类型
{
case
Button1
:
// 左键按下
{
// emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonPress, point, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
break
;
}
case
Button2
:
// 中键按下
{
// emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonPress, point, Qt::MiddleButton, Qt::MiddleButton, Qt::NoModifier));
break
;
}
case
Button3
:
// 右键按下
{
// emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonPress, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier));
break
;
}
case
Button4
:
// 向前滚动
{
// emit GlobalMouseEvent::getInstance()->wheelEvent(new QWheelEvent(point, 120, Qt::MiddleButton, Qt::NoModifier));
break
;
}
case
Button5
:
// 向后滚动
{
// emit GlobalMouseEvent::getInstance()->wheelEvent(new QWheelEvent(point, -120, Qt::MiddleButton, Qt::NoModifier));
break
;
}
default:
{
qDebug
()
<<
QString
(
"未定义的按键:%1"
).
arg
(
event
->
u
.
u
.
detail
);
// 比如很多鼠标边上会多几个键
break
;
}
}
break
;
}
case
KeyRelease
:
// 键盘释放
{
// QPoint point = QCursor::pos(); // 获取鼠标当前位置
switch
(
event
->
u
.
u
.
detail
)
// 按键类型
{
case
Button1
:
// 左键释放
{
// emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonRelease, point, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier));
break
;
}
case
Button2
:
// 中键释放
{
// emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonRelease, point, Qt::MiddleButton, Qt::MiddleButton, Qt::NoModifier));
break
;
}
case
Button3
:
// 右键释放
{
// emit GlobalMouseEvent::getInstance()->mouseEvent(new QMouseEvent(QEvent::MouseButtonRelease, point, Qt::RightButton, Qt::RightButton, Qt::NoModifier));
break
;
}
case
Button4
:
// 向前滚动
{
break
;
}
case
Button5
:
// 向后滚动
{
break
;
}
default:
{
// qDebug() << QString("未定义的按键:%1").arg(event->u.u.detail); // 比如很多鼠标边上会多几个键
}
}
break
;
}
default:
break
;
}
}
XRecordFreeData
(
data
);
}
/**
* 调用 XRecordEnableContext 函数建立 XRecord 上下文
* X Server 事件一旦发生就传递给事件处理回调函数
* XRecordEnableContext 函数一旦调用就开始进入堵塞时的事件循环,直到线程或所属进程结束
*/
static
void
enableContext
()
{
Status
ret
=
XRecordEnableContext
(
g_display
,
g_context
,
callback
,
nullptr
);
XCloseDisplay
(
g_display
);
// 关闭连接
g_display
=
nullptr
;
qDebug
()
<<
QString
(
"退出键盘事件监听:%1"
).
arg
(
ret
);
}
/**
* @brief 安装全局键盘事件监听器
* @return
*/
bool
GlobalKeyEvent
::
installKeyEvent
()
{
bool
ret
=
init
();
if
(
!
ret
)
return
false
;
QtConcurrent
::
run
(
enableContext
);
// 由于XRecordEnableContext会一直阻塞,所以需要在线程中调用
return
true
;
}
/**
* @brief 卸载全局键盘事件监听器
* @return
*/
bool
GlobalKeyEvent
::
removeKeyEvent
()
{
if
(
g_context
==
0
)
return
false
;
Display
*
display
=
XOpenDisplay
(
nullptr
);
// 这里需要单独建立一个连接来关闭监听,否则XRecordEnableContext不会退出
if
(
!
display
)
{
qWarning
()
<<
"连接X服务失败!"
;
return
false
;
}
XRecordDisableContext
(
display
,
g_context
);
XFlush
(
display
);
XSync
(
display
,
false
);
XRecordFreeContext
(
display
,
g_context
);
// 释放监听上下文,否则XRecordEnableContext不会退出
g_context
=
0
;
XCloseDisplay
(
display
);
return
true
;
}
#endif
FunctionalModule/MouseKeyEvent/GlobalMouseKey/globalmouseevent.h
浏览文件 @
1cc5afe1
...
...
@@ -12,6 +12,9 @@
#include <QObject>
class
QMouseEvent
;
class
QWheelEvent
;
/**
* 全局鼠标事件单例信号类
*/
...
...
@@ -29,7 +32,12 @@ public:
static
bool
removeMouseEvent
();
// 卸载全局鼠标事件监听器
signals:
void
mouseSignal
(
QEvent
*
event
);
/**
* @brief 由于传递的是指针,为了保证不会出现内存泄露,需要在槽函数中delete。
* 建议此信号只绑定一次,因为如果绑定多次可能会出现一个槽函数里把信号delete了,另外一个槽函数还在使用,出现野指针,或者多个槽函数多次delete
*/
void
mouseEvent
(
QMouseEvent
*
event
);
void
wheelEvent
(
QWheelEvent
*
event
);
private:
GlobalMouseEvent
(){}
...
...
FunctionalModule/MouseKeyEvent/GlobalMouseKey/globalmouseevent_win.cpp
浏览文件 @
1cc5afe1
...
...
@@ -19,30 +19,29 @@ static HHOOK g_hook = nullptr;
LRESULT
CALLBACK
LowLevelMouseProc
(
int
nCode
,
WPARAM
wParam
,
LPARAM
lParam
)
{
QPoint
point
=
QCursor
::
pos
();
// 获取鼠标当前位置
qDebug
()
<<
wParam
;
switch
(
wParam
)
{
case
WM_LBUTTONDOWN
:
// 鼠标左键按下
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Signal
(
new
QMouseEvent
(
QEvent
::
MouseButtonPress
,
point
,
Qt
::
LeftButton
,
Qt
::
LeftButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Event
(
new
QMouseEvent
(
QEvent
::
MouseButtonPress
,
point
,
Qt
::
LeftButton
,
Qt
::
LeftButton
,
Qt
::
NoModifier
));
break
;
case
WM_MOUSEMOVE
:
// 鼠标移动
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Signal
(
new
QMouseEvent
(
QEvent
::
MouseMove
,
point
,
Qt
::
NoButton
,
Qt
::
NoButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Event
(
new
QMouseEvent
(
QEvent
::
MouseMove
,
point
,
Qt
::
NoButton
,
Qt
::
NoButton
,
Qt
::
NoModifier
));
break
;
case
WM_RBUTTONDOWN
:
// 鼠标右键按下
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Signal
(
new
QMouseEvent
(
QEvent
::
MouseButtonPress
,
point
,
Qt
::
RightButton
,
Qt
::
RightButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Event
(
new
QMouseEvent
(
QEvent
::
MouseButtonPress
,
point
,
Qt
::
RightButton
,
Qt
::
RightButton
,
Qt
::
NoModifier
));
break
;
case
WM_RBUTTONUP
:
// 鼠标右键抬起
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Signal
(
new
QMouseEvent
(
QEvent
::
MouseButtonRelease
,
point
,
Qt
::
LeftButton
,
Qt
::
LeftButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Event
(
new
QMouseEvent
(
QEvent
::
MouseButtonRelease
,
point
,
Qt
::
LeftButton
,
Qt
::
LeftButton
,
Qt
::
NoModifier
));
break
;
case
WM_LBUTTONUP
:
// 鼠标左键抬起
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Signal
(
new
QMouseEvent
(
QEvent
::
MouseButtonRelease
,
point
,
Qt
::
RightButton
,
Qt
::
RightButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Event
(
new
QMouseEvent
(
QEvent
::
MouseButtonRelease
,
point
,
Qt
::
RightButton
,
Qt
::
RightButton
,
Qt
::
NoModifier
));
break
;
case
WM_MOUSEWHEEL
:
// 鼠标滚轮
{
MSLLHOOKSTRUCT
*
msll
=
reinterpret_cast
<
MSLLHOOKSTRUCT
*>
(
lParam
);
// qDebug() << QString("坐标:(%1, %2)").arg(msll->pt.x).arg(msll->pt.y); // 获取鼠标坐标
int
delta
=
GET_WHEEL_DELTA_WPARAM
(
msll
->
mouseData
);
// 获取滚轮状态,向前:120,向后-120
emit
GlobalMouseEvent
::
getInstance
()
->
mouseSignal
(
new
QWheelEvent
(
point
,
delta
,
Qt
::
MiddleButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
wheelEvent
(
new
QWheelEvent
(
point
,
delta
,
Qt
::
MiddleButton
,
Qt
::
NoModifier
));
break
;
}
default:
...
...
FunctionalModule/MouseKeyEvent/GlobalMouseKey/globalmouseevent_x11.cpp
浏览文件 @
1cc5afe1
...
...
@@ -106,10 +106,11 @@ void MouseEventX11()
}
#else
XRecordContext
g_context
=
0
;
Display
*
g_display
=
nullptr
;
// 使用static修饰全局函数和全局变量:只能在本源文件使用
static
XRecordContext
g_context
=
0
;
static
Display
*
g_display
=
nullptr
;
bool
init
()
static
bool
init
()
{
g_display
=
XOpenDisplay
(
nullptr
);
// 打开与控制显示器的X服务器的连接,详细说明看【https://tronche.com/gui/x/xlib/display/opening.html】
if
(
!
g_display
)
...
...
@@ -148,7 +149,7 @@ bool init()
* @param ptr
* @param data
*/
void
callback
(
XPointer
ptr
,
XRecordInterceptData
*
data
)
static
void
callback
(
XPointer
ptr
,
XRecordInterceptData
*
data
)
{
Q_UNUSED
(
ptr
)
...
...
@@ -165,27 +166,27 @@ void callback(XPointer ptr, XRecordInterceptData* data)
{
case
Button1
:
// 左键按下
{
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Signal
(
new
QMouseEvent
(
QEvent
::
MouseButtonPress
,
point
,
Qt
::
LeftButton
,
Qt
::
LeftButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Event
(
new
QMouseEvent
(
QEvent
::
MouseButtonPress
,
point
,
Qt
::
LeftButton
,
Qt
::
LeftButton
,
Qt
::
NoModifier
));
break
;
}
case
Button2
:
// 中键按下
{
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Signal
(
new
QMouseEvent
(
QEvent
::
MouseButtonPress
,
point
,
Qt
::
MiddleButton
,
Qt
::
MiddleButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Event
(
new
QMouseEvent
(
QEvent
::
MouseButtonPress
,
point
,
Qt
::
MiddleButton
,
Qt
::
MiddleButton
,
Qt
::
NoModifier
));
break
;
}
case
Button3
:
// 右键按下
{
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Signal
(
new
QMouseEvent
(
QEvent
::
MouseButtonPress
,
point
,
Qt
::
RightButton
,
Qt
::
RightButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Event
(
new
QMouseEvent
(
QEvent
::
MouseButtonPress
,
point
,
Qt
::
RightButton
,
Qt
::
RightButton
,
Qt
::
NoModifier
));
break
;
}
case
Button4
:
// 向前滚动
{
emit
GlobalMouseEvent
::
getInstance
()
->
mouseSignal
(
new
QWheelEvent
(
point
,
120
,
Qt
::
MiddleButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
wheelEvent
(
new
QWheelEvent
(
point
,
120
,
Qt
::
MiddleButton
,
Qt
::
NoModifier
));
break
;
}
case
Button5
:
// 向后滚动
{
emit
GlobalMouseEvent
::
getInstance
()
->
mouseSignal
(
new
QWheelEvent
(
point
,
-
120
,
Qt
::
MiddleButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
wheelEvent
(
new
QWheelEvent
(
point
,
-
120
,
Qt
::
MiddleButton
,
Qt
::
NoModifier
));
break
;
}
default:
...
...
@@ -198,7 +199,7 @@ void callback(XPointer ptr, XRecordInterceptData* data)
}
case
MotionNotify
:
// 鼠标移动
{
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Signal
(
new
QMouseEvent
(
QEvent
::
MouseMove
,
QCursor
::
pos
(),
Qt
::
NoButton
,
Qt
::
NoButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Event
(
new
QMouseEvent
(
QEvent
::
MouseMove
,
QCursor
::
pos
(),
Qt
::
NoButton
,
Qt
::
NoButton
,
Qt
::
NoModifier
));
}
case
ButtonRelease
:
// 鼠标释放
{
...
...
@@ -207,17 +208,17 @@ void callback(XPointer ptr, XRecordInterceptData* data)
{
case
Button1
:
// 左键释放
{
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Signal
(
new
QMouseEvent
(
QEvent
::
MouseButtonRelease
,
point
,
Qt
::
LeftButton
,
Qt
::
LeftButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Event
(
new
QMouseEvent
(
QEvent
::
MouseButtonRelease
,
point
,
Qt
::
LeftButton
,
Qt
::
LeftButton
,
Qt
::
NoModifier
));
break
;
}
case
Button2
:
// 中键释放
{
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Signal
(
new
QMouseEvent
(
QEvent
::
MouseButtonRelease
,
point
,
Qt
::
MiddleButton
,
Qt
::
MiddleButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Event
(
new
QMouseEvent
(
QEvent
::
MouseButtonRelease
,
point
,
Qt
::
MiddleButton
,
Qt
::
MiddleButton
,
Qt
::
NoModifier
));
break
;
}
case
Button3
:
// 右键释放
{
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Signal
(
new
QMouseEvent
(
QEvent
::
MouseButtonRelease
,
point
,
Qt
::
RightButton
,
Qt
::
RightButton
,
Qt
::
NoModifier
));
emit
GlobalMouseEvent
::
getInstance
()
->
mouse
Event
(
new
QMouseEvent
(
QEvent
::
MouseButtonRelease
,
point
,
Qt
::
RightButton
,
Qt
::
RightButton
,
Qt
::
NoModifier
));
break
;
}
case
Button4
:
// 向前滚动
...
...
@@ -248,7 +249,7 @@ void callback(XPointer ptr, XRecordInterceptData* data)
* X Server 事件一旦发生就传递给事件处理回调函数
* XRecordEnableContext 函数一旦调用就开始进入堵塞时的事件循环,直到线程或所属进程结束
*/
void
enableContext
()
static
void
enableContext
()
{
Status
ret
=
XRecordEnableContext
(
g_display
,
g_context
,
callback
,
nullptr
);
XCloseDisplay
(
g_display
);
// 关闭连接
...
...
FunctionalModule/MouseKeyEvent/MouseKeyEvent.pro
浏览文件 @
1cc5afe1
...
...
@@ -4,6 +4,8 @@
#
2
、通过封装将
Windows
鼠标信号转换成
Qt
鼠标信号;
#
3
、
Linux
下使用
X11
实现全局鼠标事件监听功能;
#
4
、通过封装将
X11
鼠标信号转换为
Qt
鼠标信号(功能比
Windows
鼠标钩子强);
#
5
、
Windows
下实现全局键盘事件监听器功能;
#
6
、
Linux
下通过
x11
API
获取到全局键盘事件,但是无法将
x11键盘事件映射为QKeyEvent
。
#
@
编译器:
Desktop
Qt
5.12
.
5
MSVC2017
64
bit
(也支持其它编译器)
#
@
Qt
IDE
:
D
:/
Qt
/
Qt5
.
12.5
/
Tools
/
QtCreator
/
share
/
qtcreator
#
...
...
@@ -12,7 +14,7 @@
#
@
时间
2022
-
11
-
13
22
:
23
:
08
#
@
备注
#---------------------------------------------------------------------------------------
QT
+=
core
gui
concurrent
QT
+=
core
gui
greaterThan
(
QT_MAJOR_VERSION
,
4
)
:
QT
+=
widgets
CONFIG
+=
c
++
11
...
...
@@ -36,7 +38,7 @@ else: unix:!android: target.path = /opt/$${TARGET}/bin
!
isEmpty
(
target
.
path
)
:
INSTALLS
+=
target
#
定义程序版本号
VERSION
=
1.
3
.
0
VERSION
=
1.
6
.
0
DEFINES
+=
APP_VERSION
=
\\\
"$$VERSION\\\"
contains
(
QT_ARCH
,
i386
){
#
使用
32
位编译器
...
...
FunctionalModule/MouseKeyEvent/widget.cpp
浏览文件 @
1cc5afe1
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include "globalmouseevent.h"
#include <QMetaEnum>
#include <globalmouseevent.h>
#include "globalkeyevent.h"
Widget
::
Widget
(
QWidget
*
parent
)
:
QWidget
(
parent
)
...
...
@@ -10,28 +11,33 @@ Widget::Widget(QWidget *parent)
{
ui
->
setupUi
(
this
);
this
->
setWindowTitle
(
QString
(
"Qt-自定义全局鼠标监听Demo - V%1"
).
arg
(
APP_VERSION
));
connect
(
GlobalMouseEvent
::
getInstance
(),
&
GlobalMouseEvent
::
mouseSignal
,
this
,
&
Widget
::
on_mouseSignal
);
this
->
setWindowTitle
(
QString
(
"Qt-自定义全局鼠标键盘事件监听Demo - V%1"
).
arg
(
APP_VERSION
));
connect
(
GlobalMouseEvent
::
getInstance
(),
&
GlobalMouseEvent
::
mouseEvent
,
this
,
&
Widget
::
on_mouseEvent
);
connect
(
GlobalMouseEvent
::
getInstance
(),
&
GlobalMouseEvent
::
wheelEvent
,
this
,
&
Widget
::
on_wheelEvent
);
connect
(
GlobalKeyEvent
::
getInstance
(),
&
GlobalKeyEvent
::
keyEvent
,
this
,
&
Widget
::
on_keyEvent
);
}
Widget
::~
Widget
()
{
#if defined(Q_OS_LINUX)
GlobalMouseEvent
::
removeMouseEvent
();
GlobalKeyEvent
::
removeKeyEvent
();
#endif
delete
ui
;
}
/**
* @brief
获取
全局鼠标事件
* @brief 全局鼠标事件
* @param event
*/
void
Widget
::
on_mouse
Signal
(
Q
Event
*
event
)
void
Widget
::
on_mouse
Event
(
QMouse
Event
*
event
)
{
QMouseEvent
*
me
=
dynamic_cast
<
QMouseEvent
*>
(
event
);
switch
(
event
->
type
())
{
case
QEvent
::
MouseButtonPress
:
// 鼠标按下
{
QString
but
;
switch
(
me
->
button
())
switch
(
event
->
button
())
{
case
Qt
::
LeftButton
:
{
...
...
@@ -54,20 +60,20 @@ void Widget::on_mouseSignal(QEvent* event)
break
;
}
}
QString
str
=
QString
(
"鼠标%1按下:(x:%2, y:%3)"
).
arg
(
but
).
arg
(
me
->
x
()).
arg
(
me
->
y
());
QString
str
=
QString
(
"鼠标%1按下:(x:%2, y:%3)"
).
arg
(
but
).
arg
(
event
->
x
()).
arg
(
event
->
y
());
ui
->
textEdit
->
append
(
str
);
break
;
}
case
QEvent
::
MouseMove
:
// 鼠标移动
{
QString
str
=
QString
(
"鼠标移动:(x:%1, y:%2)"
).
arg
(
me
->
x
()).
arg
(
me
->
y
());
QString
str
=
QString
(
"鼠标移动:(x:%1, y:%2)"
).
arg
(
event
->
x
()).
arg
(
event
->
y
());
ui
->
textEdit
->
append
(
str
);
break
;
}
case
QEvent
::
MouseButtonRelease
:
// 鼠标右键抬起
{
QString
but
;
switch
(
me
->
button
())
switch
(
event
->
button
())
{
case
Qt
::
LeftButton
:
{
...
...
@@ -90,26 +96,29 @@ void Widget::on_mouseSignal(QEvent* event)
break
;
}
}
QString
str
=
QString
(
"鼠标%1释放:(x:%2, y:%3)"
).
arg
(
but
).
arg
(
me
->
x
()).
arg
(
me
->
y
());
ui
->
textEdit
->
append
(
str
);
break
;
}
case
QEvent
::
Wheel
:
// 鼠标滚轮
{
QWheelEvent
*
we
=
dynamic_cast
<
QWheelEvent
*>
(
event
);
QString
str
=
QString
(
"鼠标滚轮:%1,(x:%2, y:%3)"
).
arg
(
we
->
delta
()
>
0
?
"向前"
:
"向后"
).
arg
(
we
->
x
()).
arg
(
we
->
y
());
QString
str
=
QString
(
"鼠标%1释放:(x:%2, y:%3)"
).
arg
(
but
).
arg
(
event
->
x
()).
arg
(
event
->
y
());
ui
->
textEdit
->
append
(
str
);
break
;
}
default:
break
;
}
delete
event
;
// 使用完成后记得delete
}
delete
event
;
/**
* @brief 全局鼠标滚轮事件
* @param event
*/
void
Widget
::
on_wheelEvent
(
QWheelEvent
*
event
)
{
QString
str
=
QString
(
"鼠标滚轮:%1,(x:%2, y:%3)"
).
arg
(
event
->
delta
()
>
0
?
"向前"
:
"向后"
).
arg
(
event
->
x
()).
arg
(
event
->
y
());
ui
->
textEdit
->
append
(
str
);
delete
event
;
// 使用完成后记得delete
}
/**
* @brief 安装全局鼠标
钩子
* @brief 安装全局鼠标
事件监听器
*/
void
Widget
::
on_but_mouseI_clicked
()
{
...
...
@@ -118,10 +127,48 @@ void Widget::on_but_mouseI_clicked()
}
/**
* @brief 卸载
鼠标钩子
* @brief 卸载
全局鼠标事件监听器
*/
void
Widget
::
on_but_mouser_clicked
()
{
bool
ret
=
GlobalMouseEvent
::
removeMouseEvent
();
ui
->
textEdit
->
append
(
QString
(
"<<<<<<<<<< 全局鼠标事件监听器卸载%1 >>>>>>>>>>"
).
arg
(
ret
?
"成功"
:
"失败"
));
}
/**
* @brief 全局键盘事件
* @param event
*/
void
Widget
::
on_keyEvent
(
QKeyEvent
*
event
)
{
QMetaEnum
type
=
QMetaEnum
::
fromType
<
QEvent
::
Type
>
();
QMetaEnum
key
=
QMetaEnum
::
fromType
<
Qt
::
Key
>
();
QMetaEnum
keyboard
=
QMetaEnum
::
fromType
<
Qt
::
KeyboardModifiers
>
();
QString
str
=
QString
(
"状态:[%1]
\t
按键:[%2]
\t
修饰:[%3]]"
).
arg
(
type
.
valueToKey
(
event
->
type
()))
.
arg
(
key
.
valueToKey
(
event
->
key
()))
.
arg
(
QString
(
keyboard
.
valueToKeys
(
int
(
event
->
modifiers
()))));
if
(
!
event
->
text
().
isEmpty
())
{
str
+=
QString
(
"
\t
字符:[%1]"
).
arg
(
event
->
text
());
}
ui
->
textEdit
->
append
(
str
);
delete
event
;
// 使用完成后记得delete
}
/**
* @brief 安装全局键盘事件监听器
*/
void
Widget
::
on_but_keyI_clicked
()
{
bool
ret
=
GlobalKeyEvent
::
installKeyEvent
();
ui
->
textEdit
->
append
(
QString
(
"<<<<<<<<<< 全局键盘事件监听器安装%1 >>>>>>>>>>"
).
arg
(
ret
?
"成功"
:
"失败"
));
}
/**
* @brief 卸载全局键盘事件监听器
*/
void
Widget
::
on_but_KeyR_clicked
()
{
bool
ret
=
GlobalKeyEvent
::
removeKeyEvent
();
ui
->
textEdit
->
append
(
QString
(
"<<<<<<<<<< 全局键盘事件监听器卸载%1 >>>>>>>>>>"
).
arg
(
ret
?
"成功"
:
"失败"
));
}
FunctionalModule/MouseKeyEvent/widget.h
浏览文件 @
1cc5afe1
...
...
@@ -16,11 +16,17 @@ public:
~
Widget
();
private
slots
:
void
on_mouseSignal
(
QEvent
*
event
);
void
on_mouseEvent
(
QMouseEvent
*
event
);
void
on_wheelEvent
(
QWheelEvent
*
event
);
void
on_keyEvent
(
QKeyEvent
*
event
);
void
on_but_mouseI_clicked
();
void
on_but_mouser_clicked
();
void
on_but_keyI_clicked
();
void
on_but_KeyR_clicked
();
private:
Ui
::
Widget
*
ui
;
};
...
...
FunctionalModule/MouseKeyEvent/widget.ui
浏览文件 @
1cc5afe1
...
...
@@ -6,8 +6,8 @@
<rect>
<x>
0
</x>
<y>
0
</y>
<width>
581
</width>
<height>
5
05
</height>
<width>
742
</width>
<height>
5
30
</height>
</rect>
</property>
<property
name=
"font"
>
...
...
@@ -20,35 +20,65 @@
<string>
Widget
</string>
</property>
<layout
class=
"QGridLayout"
name=
"gridLayout"
>
<item
row=
"1"
column=
"2"
>
<widget
class=
"QPushButton"
name=
"but_mouser"
>
<property
name=
"text"
>
<string>
卸载鼠标钩子
</string>
</property>
</widget>
</item>
<item
row=
"0"
column=
"0"
colspan=
"3"
>
<property
name=
"leftMargin"
>
<number>
1
</number>
</property>
<property
name=
"topMargin"
>
<number>
1
</number>
</property>
<property
name=
"rightMargin"
>
<number>
1
</number>
</property>
<property
name=
"bottomMargin"
>
<number>
3
</number>
</property>
<item
row=
"0"
column=
"0"
>
<widget
class=
"QTextEdit"
name=
"textEdit"
/>
</item>
<item
row=
"1"
column=
"0"
>
<widget
class=
"QPushButton"
name=
"but_mouseI"
>
<property
name=
"text"
>
<string>
安装鼠标钩子
</string>
</property>
</widget>
</item>
<item
row=
"1"
column=
"1"
>
<spacer
name=
"horizontalSpacer"
>
<property
name=
"orientation"
>
<enum>
Qt::Horizontal
</enum>
</property>
<property
name=
"sizeHint"
stdset=
"0"
>
<size>
<width>
40
</width>
<height>
20
</height>
</size>
</property>
</spacer>
<layout
class=
"QHBoxLayout"
name=
"horizontalLayout"
>
<item>
<widget
class=
"QPushButton"
name=
"but_mouseI"
>
<property
name=
"text"
>
<string>
安装全局鼠标监听器
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QPushButton"
name=
"but_mouser"
>
<property
name=
"text"
>
<string>
卸载全局鼠标监听器
</string>
</property>
</widget>
</item>
<item>
<spacer
name=
"horizontalSpacer"
>
<property
name=
"orientation"
>
<enum>
Qt::Horizontal
</enum>
</property>
<property
name=
"sizeHint"
stdset=
"0"
>
<size>
<width>
40
</width>
<height>
20
</height>
</size>
</property>
</spacer>
</item>
<item>
<widget
class=
"QPushButton"
name=
"but_keyI"
>
<property
name=
"text"
>
<string>
安装全局键盘监听器
</string>
</property>
</widget>
</item>
<item>
<widget
class=
"QPushButton"
name=
"but_KeyR"
>
<property
name=
"text"
>
<string>
卸载全局键盘监听器
</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
...
...
QSqlDemo/QSqlDemo.pro
浏览文件 @
1cc5afe1
TEMPLATE
=
subdirs
SUBDIRS
+=
\
CachedTable
\
#
通过
QSqlTableModel
显示和修改数据,通过按键保存修改内容和恢复修改内容
RelationalTableModel
\
#
本示例展示了如何使用
QSqlRelationalTableModel
(关系表模型)来可视化数据库中
[
外键
]
的使用。
SqlWidgetMapper
\
#
通过
QDataWidgetMapper
将数据库数据映射到小部件
TableModel
\
#
这个
Demo
中展示了如何使用具有表视图的专用
SQL
表模型(
QSqlTableModel
)来编辑数据库中的信息。
TableModel2
\
#
这个
Demo
中展示了如何使用具有表视图的专用
SQL
表模型(
QSqlTableModel
)来编辑数据库中的信息,实现创建空白数据行、自增
key
SignIn
#
使用
QSqlite
数据库实现用户登录、后台管理用户功能
SUBDIRS
+=
TableModel
\
#
(
1
)
这个
Demo
中展示了如何使用具有表视图的专用
SQL
表模型(
QSqlTableModel
)来编辑数据库中的信息。
SUBDIRS
+=
TableModel2
\
#
(
2
)
这个
Demo
中展示了如何使用具有表视图的专用
SQL
表模型(
QSqlTableModel
)来编辑数据库中的信息,实现创建空白数据行、自增
key
SUBDIRS
+=
CachedTable
\
#
(
3
)
通过
QSqlTableModel
显示和修改数据,通过按键保存修改内容和恢复修改内容
SUBDIRS
+=
RelationalTableModel
\
#
(
4
)
本示例展示了如何使用
QSqlRelationalTableModel
(关系表模型)来可视化数据库中
[
外键
]
的使用。
SUBDIRS
+=
SqlWidgetMapper
\
#
()
通过
QDataWidgetMapper
将数据库数据映射到小部件
SUBDIRS
+=
SignIn
#
()
使用
QSqlite
数据库实现用户登录、后台管理用户功能
QSqlDemo/RelationalTableModel/main.cpp
浏览文件 @
1cc5afe1
...
...
@@ -14,7 +14,7 @@ bool createConnection()
{
QSqlDatabase
db
=
QSqlDatabase
::
addDatabase
(
"QSQLITE"
);
// 使用数据库驱动(Qsqlite)和默认连接名称(qt_sql_default_connection)添加一个数据库
// qDebug() << QSqlDatabase::defaultConnection; // 打印默认数据库连接名称
#if
0
#if
1
db
.
setDatabaseName
(
"test.db"
);
// 使用文件数据库(可生成数据库文件,数据一直有效)
#else
db
.
setDatabaseName
(
":memory:"
);
// 使用内存数据库(不会生成数据库文件,所有数据都在内存中进行操作,性能强,程序退出后数据丢失)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录