需要用到的知识点:6 E4 l, T1 Z: A8 A- ~
1.主要还是靠windows自带的api实现
2 N: a, W: k: p2 M" Y) Q2.用到了系统回调函数遍历窗口$ Y/ N) ^) X/ t/ M3 [. ?+ \
3.用到了剪贴板. {# _# P2 Z: P6 Y& R2 v1 V, Y! X* U
4.用到了窗口前后台链接、激活窗口及恢复窗口
2 h3 z. K% _( H
' `* P, j8 W& E
核心代码如下:
g! L- ]) S& @- q#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <Windows.h>
#pragma comment (lib, "User32.lib")
char m_Name[MAXBYTE];
char m_Title[MAXBYTE];
QList<HWND> gHwndLst;
WORD m_nNum=0;
BOOL CALLBACK enumAllWindow(HWND Hwnd, LPARAM IParm)//系统返还给你的窗口句柄,API调用进来的参数
{
//每次Hwnd返回回来,都需要获取他的类名和标题
GetClassNameA(Hwnd,m_Name,MAXBYTE);//获得指定窗口所属的类的类名
GetWindowTextA(Hwnd,m_Title,MAXBYTE);//查找标题
QString strName = QString::fromLocal8Bit(m_Name);
QString strTitle = QString::fromLocal8Bit(m_Title);
if(strName.contains("ChatWnd"))//找到所有微信窗口
{
//动态数组
// HWNDArray = (HWND*)realloc((HWND)HWNDArray,(m_nNum+1)*sizeof(DWORD_PTR));//动态给指针分配内存空间
// HWNDArray[m_nNum] = Hwnd;
gHwndLst.append(Hwnd);
m_nNum++;
qDebug()<<"ID:"<<m_nNum<<"窗口句柄:"<<Hwnd<<"窗口类名:"<<strName<<"窗口标题:"<<strTitle;
}
// return false;//枚举一次就不枚举了
return true;//枚举到完毕
}
HGLOBAL sysTarget = 0;//系统对象
HLOCAL sysWCHAR = 0;//系统对象WCHAR
void SetClipboard(CONST CHAR* pData,DWORD dLength)
{
GlobalUnlock(sysTarget);//释放锁定的内存
GlobalFree(sysTarget);//释放内存对象
if(dLength==0)
dLength = strlen(pData);
if(OpenClipboard(NULL))//打开粘贴板后不能再使用
{
EmptyClipboard();//清空粘贴板
sysTarget = GlobalAlloc(GMEM_MOVEABLE,dLength+1);//在全局分配空间
if(sysTarget)
{
LPSTR mem = (LPSTR)GlobalLock(sysTarget);//锁定系统对象且返回第一个字节的指针
memcpy(mem,pData,dLength+1);//复制内容到对象指针
mem[dLength] = (TCHAR)0;//字符结束符,只有CHAR可以使用
SetClipboardData(CF_TEXT,sysTarget);//内存中的护具放入剪贴板用于CHAR
}
else
{
qDebug()<<"系统分配对象错误"<<GetLastError()<<endl;
}
CloseClipboard();//关闭粘贴板之后才能使用粘贴板
}
else
{
qDebug()<<"打开粘贴板错误!"<<endl;
}
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButtonSendMes_released()
{
m_nNum =0;
gHwndLst.clear();
QByteArray ba = ui->textEdit->toPlainText().toLocal8Bit();
SetClipboard(ba.data(),ba.size());
EnumWindows(enumAllWindow,(LPARAM)"");
for(int i =0;i<m_nNum;i++)
{
//前景锁定超时值
DWORD dwTimeOut = -1;
SystemParametersInfoA(SPI_GETFOREGROUNDLOCKTIMEOUT,0,(LPVOID)&dwTimeOut,0);//他表示再系统禁止应用程序强行自己进入前台期间的时间量
if(dwTimeOut>=100)
{
SystemParametersInfoA(SPI_GETFOREGROUNDLOCKTIMEOUT,0,0,SPIF_SENDCHANGE|SPIF_UPDATEINIFILE);//更新系统设置,并且写入用户配置文件
}
HWND HwndCur = GetForegroundWindow();//获取当前窗口的句柄
SetWindowPos(HwndCur,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);//窗口置顶,但不改变大小和坐标
DWORD dOnlyFlag = GetCurrentThreadId();//获取系统中当前线程唯一标识
DWORD dMainThreadID = GetWindowThreadProcessId(HwndCur,NULL);//当前窗口主线程ID
AttachThreadInput(dOnlyFlag,dMainThreadID,TRUE);//当前窗口和后台窗口连接起来,连接线程
ShowWindow(gHwndLst[i],SW_SHOWNORMAL);//窗口可能被最小化,那么恢复
SetForegroundWindow(gHwndLst[i]);//激活
AttachThreadInput(dOnlyFlag,dMainThreadID,FALSE);//释放连接
// SendMessage(gHwndLst[i],WM_PASTE,0,0);//发送消息到窗口
keybd_event(VK_CONTROL,MapVirtualKeyA(VK_CONTROL,0),0,0);//按下ctrl键
Sleep(50);
keybd_event(86,MapVirtualKeyA(86,0),0,0);//按下v键
Sleep(50);
keybd_event(VK_CONTROL,MapVirtualKeyA(VK_CONTROL,0),KEYEVENTF_KEYUP,0);//抬起ctrl键
Sleep(50);
keybd_event(86,MapVirtualKeyA(86,0),KEYEVENTF_KEYUP,0);//抬起v键
Sleep(50);
keybd_event(VK_RETURN,MapVirtualKeyA(VK_RETURN,0),0,0);//按下enter键
Sleep(50);
keybd_event(VK_RETURN,MapVirtualKeyA(VK_RETURN,0),KEYEVENTF_KEYUP,0);//抬起enter键
SetForegroundWindow(HwndCur);//恢复当前窗口
SetWindowPos(HwndCur,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);
}
}
|