feat: 添加监听系统聚焦窗口变化
This commit is contained in:
@@ -32,12 +32,15 @@ add_subdirectory(ElaWidgetTools)
|
|||||||
# 导出src下的cpp文件
|
# 导出src下的cpp文件
|
||||||
file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS src/*.cpp src/UI/*.cpp)
|
file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS src/*.cpp src/UI/*.cpp)
|
||||||
|
|
||||||
qt_add_executable(cbh
|
qt_add_executable(${PROJECT_NAME}
|
||||||
MANUAL_FINALIZATION
|
MANUAL_FINALIZATION
|
||||||
${SRC_FILES}
|
${SRC_FILES}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(cbh PRIVATE
|
# 添加宏定义,输出日志所处文件位置
|
||||||
|
target_compile_definitions(${PROJECT_NAME} PRIVATE QT_MESSAGELOGCONTEXT)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||||
Qt6::Widgets
|
Qt6::Widgets
|
||||||
Qt6::Core
|
Qt6::Core
|
||||||
Qt6::Gui
|
Qt6::Gui
|
||||||
@@ -50,7 +53,7 @@ set(cbh_resource_files
|
|||||||
"assets/icon.png"
|
"assets/icon.png"
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_add_resources(cbh "cbh"
|
qt_add_resources(${PROJECT_NAME} "cbh"
|
||||||
PREFIX
|
PREFIX
|
||||||
"/"
|
"/"
|
||||||
FILES
|
FILES
|
||||||
@@ -63,7 +66,7 @@ qt_add_resources(cbh "cbh"
|
|||||||
if(${QT_VERSION} VERSION_LESS 6.1.0)
|
if(${QT_VERSION} VERSION_LESS 6.1.0)
|
||||||
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.cbh)
|
set(BUNDLE_ID_OPTION MACOSX_BUNDLE_GUI_IDENTIFIER com.example.cbh)
|
||||||
endif()
|
endif()
|
||||||
set_target_properties(cbh PROPERTIES
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
${BUNDLE_ID_OPTION}
|
${BUNDLE_ID_OPTION}
|
||||||
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
|
||||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
|
||||||
@@ -72,10 +75,10 @@ set_target_properties(cbh PROPERTIES
|
|||||||
)
|
)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
install(TARGETS cbh
|
install(TARGETS ${PROJECT_NAME}
|
||||||
BUNDLE DESTINATION .
|
BUNDLE DESTINATION .
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_finalize_executable(cbh)
|
qt_finalize_executable(${PROJECT_NAME})
|
||||||
|
|||||||
16
src/main.cpp
16
src/main.cpp
@@ -1,15 +1,25 @@
|
|||||||
#include "ElaApplication.h"
|
#include "ElaApplication.h"
|
||||||
#include <QScreen>
|
|
||||||
#include <QApplication>
|
|
||||||
#include "window.h"
|
|
||||||
#include "clipboard.h"
|
#include "clipboard.h"
|
||||||
|
#include "winSpy.h"
|
||||||
|
#include "window.h"
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QScreen>
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
QApplication a(argc, argv);
|
QApplication a(argc, argv);
|
||||||
|
// 设置消息模式:输出时间、类型、文件、行号和消息本身
|
||||||
|
#ifdef QT_MESSAGELOGCONTEXT
|
||||||
|
qSetMessagePattern("[%{time yyyy-MM-dd HH:mm:ss.zzz}] [%{type}] %{file}:%{line} - %{message}");
|
||||||
|
#else
|
||||||
|
qSetMessagePattern("[%{time yyyy-MM-dd HH:mm:ss.zzz}] [%{type}] - %{message}");
|
||||||
|
#endif
|
||||||
|
// 设置监听剪贴板
|
||||||
ClipboardMonitor cbm(&a);
|
ClipboardMonitor cbm(&a);
|
||||||
|
// 设置监听系统窗口焦点变化
|
||||||
|
WinSpy spy;
|
||||||
eApp->init();
|
eApp->init();
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
w.show();
|
w.show();
|
||||||
|
|||||||
103
src/winSpy.cpp
Normal file
103
src/winSpy.cpp
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
#include <QDebug.h>
|
||||||
|
#include <QString>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "winSpy.h"
|
||||||
|
|
||||||
|
// 全局变量,保存钩子句柄
|
||||||
|
static HWINEVENTHOOK hook = NULL;
|
||||||
|
|
||||||
|
// 获取窗口标题的辅助函数
|
||||||
|
QString GetWindowTitle(HWND hwnd) {
|
||||||
|
char title[256];
|
||||||
|
if (GetWindowTextA(hwnd, title, sizeof(title))) {
|
||||||
|
return QString(title);
|
||||||
|
}
|
||||||
|
return "Untitled";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取窗口所属进程名的辅助函数
|
||||||
|
QString GetWindowProcessName(HWND hwnd) {
|
||||||
|
DWORD processId;
|
||||||
|
GetWindowThreadProcessId(hwnd, &processId);
|
||||||
|
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
|
||||||
|
if (hProcess) {
|
||||||
|
char processName[MAX_PATH];
|
||||||
|
DWORD size = sizeof(processName);
|
||||||
|
if (QueryFullProcessImageNameA(hProcess, 0, processName, &size)) {
|
||||||
|
CloseHandle(hProcess);
|
||||||
|
QString fullPath(processName);
|
||||||
|
// 只返回可执行文件名称
|
||||||
|
qsizetype lastSlash = fullPath.lastIndexOf("\\");
|
||||||
|
if (lastSlash != -1) {
|
||||||
|
return fullPath.mid(lastSlash + 1);
|
||||||
|
}
|
||||||
|
return fullPath;
|
||||||
|
}
|
||||||
|
CloseHandle(hProcess);
|
||||||
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 事件回调函数
|
||||||
|
void CALLBACK WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread,
|
||||||
|
DWORD dwmsEventTime) {
|
||||||
|
|
||||||
|
// 确保事件对象是窗口且事件是前台窗口改变
|
||||||
|
if (idObject != OBJID_WINDOW || idChild != CHILDID_SELF) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == EVENT_SYSTEM_FOREGROUND) {
|
||||||
|
HWND foregroundWindow = GetForegroundWindow(); // 获取当前前景窗口
|
||||||
|
if (foregroundWindow) {
|
||||||
|
QString title = GetWindowTitle(foregroundWindow);
|
||||||
|
QString processName = GetWindowProcessName(foregroundWindow);
|
||||||
|
// 记录信息,这里示例为输出到控制台
|
||||||
|
qDebug() << "Foreground Window Changed:";
|
||||||
|
qDebug() << " Handle: " << foregroundWindow;
|
||||||
|
qDebug() << " Title: " << title;
|
||||||
|
qDebug() << " Process: " << processName;
|
||||||
|
qDebug() << "----------------------------------------";
|
||||||
|
// TODO: 处理窗口数据保存
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinSpy::setHook() {
|
||||||
|
if (hook) {
|
||||||
|
qDebug() << "Already monitoring.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 设置事件钩子,监听前台窗口变化事件
|
||||||
|
hook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, // 最小事件值
|
||||||
|
EVENT_SYSTEM_FOREGROUND, // 最大事件值
|
||||||
|
NULL, // 钩子函数所在的DLL句柄(NULL表示当前进程)
|
||||||
|
WinEventProc, // 事件回调函数指针
|
||||||
|
0, // 感兴趣的进程ID(0表示所有进程)
|
||||||
|
0, // 感兴趣的线程ID(0表示所有线程)
|
||||||
|
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS // 标志:上下文外,跳过自身进程事件
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!hook) {
|
||||||
|
qWarning() << "Failed to set win event hook!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qDebug() << "Start monitoring foreground window changes";
|
||||||
|
// // 消息循环是必须的,否则回调函数不会被调用
|
||||||
|
// MSG msg;
|
||||||
|
// while (GetMessage(&msg, NULL, 0, 0)) {
|
||||||
|
// TranslateMessage(&msg);
|
||||||
|
// DispatchMessage(&msg);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void WinSpy::freeHook() {
|
||||||
|
// 程序退出前卸载钩子
|
||||||
|
if (hook) {
|
||||||
|
UnhookWinEvent(hook);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WinSpy::WinSpy() { setHook(); }
|
||||||
|
WinSpy::~WinSpy() { freeHook(); }
|
||||||
13
src/winSpy.h
Normal file
13
src/winSpy.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
class WinSpy {
|
||||||
|
public:
|
||||||
|
WinSpy();
|
||||||
|
~WinSpy();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setHook();
|
||||||
|
void freeHook();
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user