前段时间,受朋友委托,需要做一个能够获取别人软件文本框中内容的助手。当然这需要调用win api来解决问题。一开始,我想都没想,就用getWindowText()。。。。居然没用,好郁闷。于是查msdn。。发现关于返回值,是这样写的

Return Values

The length, in characters, of the copied string, not including the terminating null character, indicates success. Zero indicates that the window has no title bar or text, if the title bar is empty, or if the window or control handle is invalid. To get extended error information, call GetLastError.

This function cannot retrieve the text of an edit control in another application.

原来是不能跨线程获取数据。。。。。。好吧。。那没办法。接着用SendMessage发送WM_GETTEXT。。。测试记事本是完全没有问题的。。。但是对那个软件却不起作用。。。。。于是各种百度。。无果。。好吧。。暂时搁一搁。。后来,同学在用vb弄文本框时发现了EM_GETLINECOUNT和  EM_GETLINE  。至此,这个问题算是解决了。

啰嗦了那么多,进入主题吧。接下来,我们先实现这个助手。spy++这个大同小异。无非就是多了几个api的调用和线程处理问题。好了。先看下这个助手的最终效果图。。

按住那个放大镜后  鼠标的样式会自动改变  然后获取鼠标所在位置的窗口句柄。。选择模式 尝试获取数据。  如果有填写发送数据的目的地信息。。还可以直接发送数据。

好了。我们来重点说说以下几点 :

1) 获取窗口句柄      所用API函数为:  HWNDWindowFromPoint( POINTPoint);  只有获取句柄后我们才能调用SendMessage来获取信息

2)Qt修改鼠标样式  首先,要修改鼠标样式,我们就应该对存放图片的便签进行事件处理 鼠标按下,切换切换label背景图片。同时修改鼠标样式。。代码如下

  1. bool MainWindow::eventFilter(QObject *obj, QEvent *event)
  2. {
  3. if (event->type() == QEvent::MouseButtonPress) {
  4. if (obj == ui->lab_MouseStyle) {
  5. QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
  6. if (mouseEvent->button() == Qt::LeftButton) {
  7. ui->lab_MouseStyle->setPixmap(QPixmap("://image/wait.png"));
  8. // 设置鼠标样式
  9. QCursor cursor ;
  10. QPixmap pixmap("://image/searchMouse.png") ;
  11. cursor = QCursor(pixmap,-1,-1);
  12. setCursor(cursor) ;
  13. // 修改标志
  14. m_IsMouseStyleChanged = true;
  15. // 开启计时器 300 毫秒刷新一次
  16. m_pTimer->start(300);
  17. return true;
  18. }
  19. }
  20. }
  21. return QWidget::eventFilter(obj, event);
  22. }

其中lab_MouseStyle就是软件截图中,存放放大镜的label。。。

同时,当用户松开鼠标时。我们需要还原鼠标样式,并且切换label背景.   这个时候,就要对整个程序进行事件拦截了。而不是对label处理事件了。具体代码如下

  1. bool MainWindow::event(QEvent *event)
  2. {
  3. if (event->type() == QEvent::MouseButtonRelease) {
  4. if (m_IsMouseStyleChanged == true) {
  5. // 当用户松开鼠标时, 恢复鼠标样式并且重新给鼠标样式标签设置图标
  6. setCursor(Qt::ArrowCursor);
  7. ui->lab_MouseStyle->setPixmap(QPixmap("://image/searchMouse.png").scaled(QSize(48,48), Qt::KeepAspectRatio));
  8. m_IsMouseStyleChanged = false;
  9. // 停止计时器
  10. m_pTimer->stop();
  11. return true;
  12. }
  13. }
  14. return QWidget::event(event);
  15. }

计时器的做用时通知绘图  绘制窗口的黑色边框。。具体的可以看源码部分。。(绘图部分参考于网络,并非原创。。太久不用gdi了。。有点生疏哈)

3) 通过句柄获取数据   这里只是谈谈消息的使用   同时有个新问题。怎么处理字符编码问题。。 代码如下(  部分 )

  1. // 模式一 : 通过直接发送WM_GETTEXT
  2. TCHAR lpRes[20000] = L"";
  3. int len = ::SendMessage(m_DesHwnd,  WM_GETTEXT  , (WPARAM)10000, (LPARAM)lpRes);
  4. char str[40240] = "";
  5. int iLength = <span style="color:#ff0000;">WideCharToMultiByte</span>(CP_ACP, 0, lpRes, -1, NULL, 0, NULL, NULL);
  6. <span style="color:#ff0000;">WideCharToMultiByte</span>(CP_ACP, 0, lpRes, -1,str , iLength, NULL, NULL);
  7. ui->textEdit_Handle->setText(QString::fromAscii(str));

利用WideCharToMultiByte函数再结合QString::fromAscii我们可以很轻松的转换编码。。。 那么问题来了? QString又该怎么便捷的转换为TCHAR呢??

  1. // 此函数实现通过句柄获取富文本数据
  2. QString MainWindow::getDataFromHwnd(HWND hWnd)
  3. {
  4. // 先获取总行数  然后读取数据
  5. int lineCount= ::SendMessage(hWnd, EM_GETLINECOUNT, 0, 0);
  6. if (lineCount >0) {
  7. TCHAR strRes[102400] = L""; // 使用宽字符
  8. int  count = 0; // 用来记录总共获取了多少字符
  9. for (int i = 0; i< lineCount;++i) {
  10. TCHAR szBuffer[200] = L"";
  11. ((WORD*) szBuffer)[0] = 200;
  12. int len = ::SendMessage(hWnd,  EM_GETLINE  ,(WPARAM)i, (LPARAM)szBuffer);
  13. ((WORD*) szBuffer)[len] = '\0';
  14. for  (int j= 0; j< len;++j)
  15. strRes[count++] = szBuffer[j];
  16. strRes[count++] = '\n';
  17. }
  18. // 将宽字符转换为ASCII码字符
  19. char str[30240] = "";
  20. int iLength = WideCharToMultiByte(CP_ACP, 0, strRes, -1, NULL, 0, NULL, NULL);
  21. WideCharToMultiByte(CP_ACP, 0, strRes, -1,str , iLength, NULL, NULL);
  22. return QString::fromAscii(str);
  23. }
  24. return QString("");
  25. }

这个主要是针对文本框的处理!思路很简单: 先获取文本框中的行数,然后循环获取每一行数据。。不过此代码中没有采用动态开辟数组。。这个如有需要,自行修改。

4)到此基本的就实现了。我们讲讲题外话。。怎么实现开机启动的功能。   代码如下

  1. //设置为开机启动
  2. static void AutoRunWithSystem(bool IsAutoRun) {
  3. QSettings *reg = new QSettings(
  4. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
  5. QSettings::NativeFormat);
  6. QString AppPath = QApplication::applicationFilePath();
  7. QString AppName = QApplication::applicationName();
  8. if (IsAutoRun) {
  9. reg->setValue(AppName, AppPath.replace("/","\\"));
  10. } else {
  11. reg->setValue(AppName, "");
  12. }
  13. }

此代码并非原创。参考与游龙大神的代码。有修改。源代码测试有问题。问题出在windows系统注册表的‘\’符号问题。。必须先修改相应的符号。。

好了。最后附上已打包的软件和源码。。。仅供学习与交流。,不用于商业用途。 有不足之处,欢迎指出。谢谢。

可执行文件下载地址: http://download.csdn.net/detail/wu5151/8939661

源码文件下载地址:   http://download.csdn.net/detail/wu5151/8939673

本博客地址: http://blog.csdn.net/wu5151

http://blog.csdn.net/wu5151/article/details/47101201

Qt实战之开发软件数据获取助手(eventFilter处理鼠标按下,event处理鼠标松开)的更多相关文章

  1. Qt实战之开发CSDN下载助手 (3)(结束篇)

    再次申明下,开发这款助手,主要是用来学习交流,并不是用来开发什么刷积分的软件. 好了,言归正传,这次,主要的分析下CSDN的下载,评论,验证码获取机制等等. 好,回到第二篇,当我们成功登陆时,CSDN ...

  2. Qt实战之开发CSDN下载助手 (2)

    现在,我们正式开工啦.这一篇主要学习下基本的抓包分析.学会协议登录CSDN并制作登陆界面. 准备工具: 一款http抓包工具. 可以是FireBug或者fiddler.这里我们用httpWatch. ...

  3. WPF学习开发客户端软件-任务助手(下 2015年2月4日代码更新)

    时光如梭,距离第一次写的 WPF学习开发客户端软件-任务助手(已上传源码)  已有三个多月,期间我断断续续地对该项目做了优化.完善等等工作,现在重新向大家介绍一下,希望各位可以使用,本软件以实用性为主 ...

  4. 【Qt编程】基于Qt的词典开发系列<一>--词典框架设计及成品展示

    去年暑假的时候,作为学习Qt的实战,我写了一个名为<我爱查词典>的词典软件.后来由于导师项目及上课等原因,时间不足,所以该软件的部分功能欠缺,性能有待改善.这学期重新拿出来看时,又有很多东 ...

  5. Qt for Android 开发大坑

    Qt for Android 开发大坑 作者: qyvlik Qt 5.5.1 这里说一说比較常见的 Qt 开发安卓的大坑. 希望同学们不要做无谓的挣扎,跳过这些坑. 输入框 首当其冲的是输入框,Qt ...

  6. 《Qt 实战一二三》

    简介 "我们来自Qt分享&&交流,我们来自Qt Quick分享&&交流",不管你是笑了,还是笑了,反正我们是认真的.我们就是要找寻一种Hold不住的 ...

  7. 【Qt编程】基于Qt的词典开发系列--后序

    从去年八月份到现在,总算完成了词典的编写以及相关技术文档的编辑工作.从整个过程来说,文档的编写比程序的实现耗费的时间更多.基于Qt的词典开发系列文章,大致包含了在编写词典软件过程中遇到的技术重点与难点 ...

  8. 【Qt编程】基于Qt的词典开发系列<六>--界面美化设计

    本文讲一讲界面设计,作品要面向用户,界面设计的好坏直接影响到用户的体验.现在的窗口设计基本都是扁平化的,你可以从window XP与window 8的窗口可以明显感觉出来.当然除了窗口本身的效果,窗口 ...

  9. 【Qt编程】基于Qt的词典开发系列<三>--开始菜单的设计

    这篇文章讲讲如何实现开始菜单(或者称为主菜单)的设计.什么是开始菜单呢?我们拿常用的软件来用图例说明,大多数软件的开始菜单在左下角,如下图: 1.window 7的开始菜单 2.有道词典的主菜单 3. ...

随机推荐

  1. 散列表的实现 -- 数据结构与算法的javascript描述 第八章

    散列表(哈希表 散列是一种常用的数据存储技术,散列后的数据可以快速地插入或取用. 散列表需要一个散列值(key)来存储指定数据,取数据也是依靠此. 散列值可以依靠计算数据的 ASCII码来获得,但是这 ...

  2. java获取当前路径的几种方法

    1.利用System.getProperty()函数获取当前路径: System.out.println(System.getProperty("user.dir"));//use ...

  3. Android UI高级交互设计Demo

    首先:是google的新标准 Google Material design 开源项目 1.直接拿来用!十大Material Design开源项目 2.收集android上开源的酷炫的交互动画和视觉效果 ...

  4. 使用astyle格式化代码【脚本】

    astyle使用基础教程 http://cppblog.com/jokes000/articles/158838.html steps: (1) apt-get install astyle 或者去主 ...

  5. As Easy As A+B

    Problem Description These days, I am thinking about a question, how can I get a problem as easy as A ...

  6. SGU 310. Hippopotamus( 状压dp )

    题目大意:给N块板, 有A,B2种类型的板, 要求任意M块连续的板中至少有K块B板.1≤n≤60,1≤m≤15,0≤k≤m≤n. dp(x, s)表示第x块板, x前M块板的状态为s, 然后合法状态转 ...

  7. 阿里云ECS每天一件事D9:nginx1.7整合tomcat8.0

    仅通过8080端口访问jsp显然不是一算是一个太好的方法,可以使用nginx的proxy_pass子模块,实现nginx转发jsp请求至tomcat. 典型的配置如下: server { listen ...

  8. android网络通讯数据封装之 json

    Demo程序包括客户端和服务端 客户端按json数据格式封装数据传至服务端. 服务端为简单的servlet程序,负责接收客户端传到json数据,然后按原数据返回客户端. 实例代码如下: public ...

  9. css table 布局

    使用CSS表格 CSS表格能够解决所有那些我们在使用绝对定位和浮动定位进行多列布局时所遇到的问题.例如,“display:table;”的CSS声明能够让一个HTML元素和它的子节点像table元素一 ...

  10. Codeforces 430B Balls Game(Two Pointers)

    [题目链接] http://codeforces.com/contest/430/problem/B [题目大意] 祖玛游戏,给出一个序列,表示祖玛球的颜色序列,三个或者以上的球碰在一起就会发生消除, ...