需要用到的知识点:7 C9 N' \' b/ |! ?: t8 i
1.主要还是靠windows自带的api实现
& D! J( @9 R+ v/ f2.用到了系统回调函数遍历窗口 }* b( E3 f* G3 ~
3.用到了剪贴板
8 o$ X+ | J2 W4.用到了窗口前后台链接、激活窗口及恢复窗口
{4 V) L! F! Z X% z
3 C" g& y7 c6 [, ~' S$ E& X核心代码如下:
! p3 W5 d3 B$ W5 H: |9 R+ _
- #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);
- }
- }
|