Qt实现进程界面之间的鼠标焦点切换

 更新时间:2020年09月24日 17:27:01   作者:zebra_zzh  
这篇文章主要为大家详细介绍了Qt实现进程界面之间的鼠标焦点切换,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了Qt实现进程界面之间鼠标焦点切换的具体代码,供大家参考,具体内容如下

需求

有三个软件A、B、C。A是主要软件,B、C是辅助软件。

⑴ 在使用A的过程中,按N键可以呼出软件B,按M键可以呼出软件C。再次按下可以隐藏它们。

⑵ 在软件B、C都存在的条件下,按J键可以实现鼠标焦点以A->B->C的顺序在软件之间切换。

分析

需求(1)

在按键事件中对M或N键做处理,当对应键按下时,首先判断B.exe或C.exe是否存在,如果不存在则执行对应exe,否则显示或隐藏它们。这里不再赘述。

需求(2)

以从A切到B为例,由A通过UDP发消息给B,B收到消息后将焦点切到自身。其他类似。

定义通用变量

主要定义软件端口、消息类型、发送者类型。后面将建立三个Qt工程,MainDlg代表软件A,compass代表软件B,chatlist代表软件C。定义如下:

/*****************************************************
 Author: 张志浩
 Mail: 791745123@qq.com
 Time: 2019-1-5
 Function:
 通用变量、宏定义头文件
 DESTPORT : 目标主机端口
 SENDERTYPE : 发送者类型
 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;

设计通信报文

写一个报文基类,包含消息类型、发送者、附加消息三类信息。后期可以继承它来丰富信息种类。实现如下:

/*****************************************************
 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;
 //发送者
 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为例,此时三个软件都已经打开并显示在桌面。

1 按J键进入MainDlg键盘事件,发送消息到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;
 
}

进入槽函数

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);
}

效果

总结

主要考察到对AttachThreadInput的运用,还有就是设计好三者之间切换的流程。即将焦点切换的动作交给目标进程来做,自身进程只负责发消息,避免逻辑混乱。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • C++调用C函数报错无法解析的外部命令/无法解析的外部符号问题

    C++调用C函数报错无法解析的外部命令/无法解析的外部符号问题

    这篇文章主要介绍了C++调用C函数报错无法解析的外部命令/无法解析的外部符号问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • MFC命名规则汇总

    MFC命名规则汇总

    这篇文章主要介绍了MFC命名规则,对于初学者而言需要牢固掌握这类规则,需要的朋友可以参考下
    2014-07-07
  • C++类成员构造函数和析构函数顺序示例详细讲解

    C++类成员构造函数和析构函数顺序示例详细讲解

    这篇文章主要介绍了C++类成员构造和析构顺序示例,看了这个例子大家就可以明白c++构造析构的奥秘
    2013-11-11
  • C语言操作符超详细讲解下篇

    C语言操作符超详细讲解下篇

    C 语言提供了丰富的操作符,有:算术操作符,移位操作符,位操作符,赋值操作符,单目操作符,关系操作符,逻辑操作符,条件操作符等。本篇为第二篇,让我们通读本篇来详细了解吧
    2022-04-04
  • C语言栈与队列相互实现详解

    C语言栈与队列相互实现详解

    栈和队列,严格意义上来说,也属于线性表,因为它们也都用于存储逻辑关系为 "一对一" 的数据,但由于它们比较特殊,本章讲解分别用队列实现栈与用栈实现队列
    2022-04-04
  • C++ DLL注入工具(完整源码)

    C++ DLL注入工具(完整源码)

    这篇文章主要介绍了C++ DLL注入工具的相关资料,并向大家分享了完整的源码,具有一定的参考价值,希望对正在工作或学习的你有所帮助
    2022-02-02
  • C语言函数栈帧详解

    C语言函数栈帧详解

    下面小编就为大家带来一篇浅谈C语言函数调用参数压栈的相关问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2021-10-10
  • C++中Covariant返回值类型详解

    C++中Covariant返回值类型详解

    这篇文章主要介绍了C++中Covariant返回值类型详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的朋友可以可以参考一下
    2022-09-09
  • c++实现一个简易的网络缓冲区的实践

    c++实现一个简易的网络缓冲区的实践

    这篇文章主要介绍了c++实现一个简易的网络缓冲区的实践,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • 内核线程优先级设置的方法介绍

    内核线程优先级设置的方法介绍

    本篇文章介绍了,内核线程优先级设置的方法。需要的朋友参考下
    2013-05-05

最新评论