Qt實現(xiàn)進(jìn)程界面之間的鼠標(biāo)焦點切換
本文實例為大家分享了Qt實現(xiàn)進(jìn)程界面之間鼠標(biāo)焦點切換的具體代碼,供大家參考,具體內(nèi)容如下
需求
有三個軟件A、B、C。A是主要軟件,B、C是輔助軟件。
⑴ 在使用A的過程中,按N鍵可以呼出軟件B,按M鍵可以呼出軟件C。再次按下可以隱藏它們。
⑵ 在軟件B、C都存在的條件下,按J鍵可以實現(xiàn)鼠標(biāo)焦點以A->B->C的順序在軟件之間切換。
分析
需求(1)
在按鍵事件中對M或N鍵做處理,當(dāng)對應(yīng)鍵按下時,首先判斷B.exe或C.exe是否存在,如果不存在則執(zhí)行對應(yīng)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 : 目標(biāo)主機(jī)端口 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;
設(shè)計通信報文
寫一個報文基類,包含消息類型、發(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]; };
焦點切換
焦點切換按以下幾步進(jìn)行:
//獲取自身窗口句柄并置前 HWND hwnd = ::FindWindow(NULL, L"compass"); ::SetForegroundWindow(hwnd); //獲取置前窗口句柄(該步驟可省略,直接用上一步獲得的句柄) HWND hForeWnd = ::GetForegroundWindow(); //獲取當(dāng)前工作線程ID DWORD dcurid = ::GetCurrentThreadId(); //獲取置前窗口的線程ID DWORD dfoid = ::GetWindowThreadProcessId(hForeWnd, NULL); //依附 ::AttachThreadInput(dcurid, dfoid, TRUE); //設(shè)置鼠標(biāo)位置 QRect rect = this->geometry(); SetCursorPos(rect.left() + 200, rect.top() + 200);
依附的步驟是必要的,因為如果不依附,就算鼠標(biāo)位置從A移到B了,此時的鍵盤輸入焦點還在A。按J鍵只會進(jìn)入A的鍵盤事件,除非手動點擊一下B再按J。
整體流程梳理
以從MainDlg切往compass為例,此時三個軟件都已經(jīng)打開并顯示在桌面。
1 按J鍵進(jìn)入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; }
進(jìn)入槽函數(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的運(yùn)用,還有就是設(shè)計好三者之間切換的流程。即將焦點切換的動作交給目標(biāo)進(jìn)程來做,自身進(jìn)程只負(fù)責(zé)發(fā)消息,避免邏輯混亂。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
一篇文章帶你用C語言玩轉(zhuǎn)結(jié)構(gòu)體
本文主要介紹C語言 結(jié)構(gòu)體的知識,學(xué)習(xí)C語言肯定需要學(xué)習(xí)結(jié)構(gòu)體,這里詳細(xì)說明了結(jié)構(gòu)體并附示例代碼,供大家參考學(xué)習(xí),有需要的小伙伴可以參考下2021-09-09內(nèi)聯(lián)函數(shù)inline與宏定義深入解析
類的內(nèi)斂函數(shù)是一個真正的函數(shù)。使用內(nèi)聯(lián)函數(shù)inline可以完全取代表達(dá)式形式的宏定義2013-09-09C++ LeetCode1805字符串不同整數(shù)數(shù)目
這篇文章主要為大家介紹了C++ LeetCode1805字符串不同整數(shù)數(shù)目,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12C++實現(xiàn)簡單的希爾排序Shell Sort實例
這篇文章主要介紹了C++實現(xiàn)簡單的希爾排序Shell Sort實例,對于正在學(xué)習(xí)算法的朋友很有借鑒價值,需要的朋友可以參考下2014-07-07