Qt實現(xiàn)進程界面之間的鼠標焦點切換
本文實例為大家分享了Qt實現(xiàn)進程界面之間鼠標焦點切換的具體代碼,供大家參考,具體內(nèi)容如下
需求
有三個軟件A、B、C。A是主要軟件,B、C是輔助軟件。
⑴ 在使用A的過程中,按N鍵可以呼出軟件B,按M鍵可以呼出軟件C。再次按下可以隱藏它們。
⑵ 在軟件B、C都存在的條件下,按J鍵可以實現(xiàn)鼠標焦點以A->B->C的順序在軟件之間切換。
分析
需求(1)
在按鍵事件中對M或N鍵做處理,當對應鍵按下時,首先判斷B.exe或C.exe是否存在,如果不存在則執(zhí)行對應exe,否則顯示或隱藏它們。這里不再贅述。
需求(2)
以從A切到B為例,由A通過UDP發(fā)消息給B,B收到消息后將焦點切到自身。其他類似。
定義通用變量
主要定義軟件端口、消息類型、發(fā)送者類型。后面將建立三個Qt工程,MainDlg代表軟件A,compass代表軟件B,chatlist代表軟件C。定義如下:
/*****************************************************
Author: 張志浩
Mail: 791745123@qq.com
Time: 2019-1-5
Function:
通用變量、宏定義頭文件
DESTPORT : 目標主機端口
SENDERTYPE : 發(fā)送者類型
MSGTYPE : 消息類型
Version: v 1.0
*****************************************************/
#pragma once
typedef enum
{
PORT_MAINDLG = 8000,
PORT_COMPASS,
PORT_CHATLIST
}DESTPORT;
typedef enum
{
PROCESS_NONE = 100,
PROCESS_MAINDLG,
PROCESS_COMPASS,
PROCESS_CHATLIST
}SENDERTYPE;
typedef enum
{
MSG_NONE = 10,
MSG_CHANGEMOUSEPOS
}MSGTYPE;
設計通信報文
寫一個報文基類,包含消息類型、發(fā)送者、附加消息三類信息。后期可以繼承它來豐富信息種類。實現(xiàn)如下:
/*****************************************************
Author: 張志浩
Mail: 791745123@qq.com
Time: 2019-1-5
Function:
報文基類
Version: v 1.0
*****************************************************/
#pragma once
#include "commonType.h"
#include <memory>
#define BUFF_LENGTH 128
class CInfoBase
{
public:
CInfoBase():infoType(0), senderType(0)
{
memset(addMsg, 0, BUFF_LENGTH);
}
bool InputAddMsg(const char* buff, int length)
{
if (length < BUFF_LENGTH && length > 0)
{
memcpy(addMsg, buff, length);
return true;
}
return false;
}
public:
//消息類型
int infoType;
//發(fā)送者
int senderType;
//附加消息
char addMsg[BUFF_LENGTH];
};
焦點切換
焦點切換按以下幾步進行:
//獲取自身窗口句柄并置前 HWND hwnd = ::FindWindow(NULL, L"compass"); ::SetForegroundWindow(hwnd); //獲取置前窗口句柄(該步驟可省略,直接用上一步獲得的句柄) HWND hForeWnd = ::GetForegroundWindow(); //獲取當前工作線程ID DWORD dcurid = ::GetCurrentThreadId(); //獲取置前窗口的線程ID DWORD dfoid = ::GetWindowThreadProcessId(hForeWnd, NULL); //依附 ::AttachThreadInput(dcurid, dfoid, TRUE); //設置鼠標位置 QRect rect = this->geometry(); SetCursorPos(rect.left() + 200, rect.top() + 200);
依附的步驟是必要的,因為如果不依附,就算鼠標位置從A移到B了,此時的鍵盤輸入焦點還在A。按J鍵只會進入A的鍵盤事件,除非手動點擊一下B再按J。
整體流程梳理
以從MainDlg切往compass為例,此時三個軟件都已經(jīng)打開并顯示在桌面。
1 按J鍵進入MainDlg鍵盤事件,發(fā)送消息到compass
void MainDlg::keyPressEvent(QKeyEvent * event)
{
switch(event->key())
{
case Qt::Key_J:
{
CInfoBase m_sendMsg;
m_sendMsg.infoType = MSG_CHANGEMOUSEPOS;
m_sendMsg.senderType = PROCESS_MAINDLG;
m_myudp.SendData((char*)&m_sendMsg, sizeof(m_sendMsg), PORT_COMPASS, "127.0.0.1");
break;
}
default:
{
}
}
}
2 compass收到UDP消息,切換焦點
void CUdpMsgBase::DataHanding(const char* data)
{
int msgType = MSG_NONE;
::memcpy(&msgType, data, sizeof(int));
if (msgType == MSG_NONE)
{
}
if (msgType == MSG_CHANGEMOUSEPOS)
{
emit changepos();
}
return;
}
進入槽函數(shù)
void MainDlg::changePos()
{
HWND hwnd = ::FindWindow(NULL, L"MainDlg");
::SetForegroundWindow(hwnd);
HWND hForeWnd = ::GetForegroundWindow();
DWORD dcurid = ::GetCurrentThreadId();
DWORD dfoid = ::GetWindowThreadProcessId(hForeWnd, NULL);
::AttachThreadInput(dcurid, dfoid, TRUE);
QRect rect = this->geometry();
SetCursorPos(rect.left() + 200, rect.top() + 200);
}
效果

總結(jié)
主要考察到對AttachThreadInput的運用,還有就是設計好三者之間切換的流程。即將焦點切換的動作交給目標進程來做,自身進程只負責發(fā)消息,避免邏輯混亂。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
C++調(diào)用C函數(shù)報錯無法解析的外部命令/無法解析的外部符號問題
這篇文章主要介紹了C++調(diào)用C函數(shù)報錯無法解析的外部命令/無法解析的外部符號問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-08-08
C++類成員構(gòu)造函數(shù)和析構(gòu)函數(shù)順序示例詳細講解
這篇文章主要介紹了C++類成員構(gòu)造和析構(gòu)順序示例,看了這個例子大家就可以明白c++構(gòu)造析構(gòu)的奧秘2013-11-11
c++實現(xiàn)一個簡易的網(wǎng)絡緩沖區(qū)的實踐
這篇文章主要介紹了c++實現(xiàn)一個簡易的網(wǎng)絡緩沖區(qū)的實踐,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12

