C++的进程间响应技术

                           C++的进程间响应技术

  吴小岭

在 Windows环境中,一个应用程序按指定方式响应另一个应用程序的解决方法一般是利用 DDE,这需要作出响应的一方提供DDE服务。但是,如果作出响应的一方没有这种服务,我们就没有别的办法了吗?当然有,那就是向应用程序发送消息,应用程序接收到标准的 Windows消息后,就会完成相应的操作。 
 
要向应用程序发送消息,首先要得到它的窗口句柄,这可以通过两个 API函数 GetWindow和 GetWindowText来实现。首先用GetWindow函数遍历所有的 Windows窗口,再用 GetWindowText函数得到每个窗口的标题,如果得到的标题和我们想要查找的窗口的标题一样,就得到我们想要的窗口句柄了。应用程序的窗口是一个树状结构,每一个子窗口下还可能有子窗口,要得到所有子窗口的句柄,就要遍历整个树,为了实现这一点,我们在程序中用了一个简单的堆栈操作。有了具体的窗口句柄后 ,就可以通过发送消息实现我们想实现的操作。本文举了几个简单的例子,实现了一些比较常用的操作,如修改按钮或文本框中的文字,实现从一个程序控制另一个应用程序中的按钮单击等。 
 
图 1是程序运行的主窗体画面:
 
 
下面是在 C++ Builder中实现的源程序部分代码: 
 
单元文件 Unit1.cpp 
 
# include <vcl.h>
 
# pragma hdrstop 
 
# include“ Unit1.h” 
 
# pragma package(smart_init) 
 
# pragma resource“* .dfm” 
 
TForm1* Form1; 
 
__fastcall TForm1::TForm1(TComponent* Owner): TForm(Owner) 
 

 

 
void __fastcall TForm1::btnSearchClick(TObject* Sender) 
 
{  
 
搜索标题和 txtTitle中的文本相符合的窗口,把搜索到的窗口句柄放到 h_Wnd中 ,并把它的所有子窗口的句柄放到数组hWndArray中 
 
char Search[128]; 
 
char ClassName[128]; 
 
HWND h_Child; 
 
int currPos; 
 
int cmpLen; 
 
currPos=0; 
 
lstClassName- >Clear(); 
 
lstControlText- >Clear(); 
 
memoReadWrite- >Clear(); 
 
h_Wnd=GetWindow(Form1- >Handle, 
 
GW_HWNDFIRST);  
 
遍历所有窗口 
 
while(h_Wnd){ 
 
GetWindowText(h_Wnd,Search,128); 
 
cmpLen=txtTitle- >Text.Length(); 
 
Search[cmpLen]=0; 
 
if(AnsiString(Search)== txtTitle- >Text){  
 
寻找窗口标题和我们输入到 txtTitle中的内容相符合的窗口 
 
lstClassName- >Items- >Add(AnsiString(Search)); 
 
lstControlText- >Items- >Add(AnsiString(Search)); 
 
sPush(h_Wnd); 
 
h_Child=GetWindow(h_Wnd,GW_CHILD);  
 
找出所有子窗口 ,把句柄放入数组 hWndArray中 
 
while(1){ 
 
hWndArray[currPos]=h_Child; 
 
GetClassName(h_Child,ClassName,128); 
 
SendMessage(h_Child,WM_GETTEXT,128,(LPARAM)Search);  
 
把找到的子窗口的类名和子窗口的序号放到列表框 lstClassName中 ,通过这些数据 ,我们可以确定对这些子窗口可以发送什么消息 
 
lstClassName- >Items- >Add(AnsiString(currPos)+“-- "+ AnsiString(ClassName));  
 
把找到的子窗口的文字信息放到列表框 lstControlText中,通过这些信息 ,我们能较准确地定位子窗口在主窗口的位置 
 
lstControlText- >Items- >Add(AnsiString(currPos)+“-- "+ AnsiString(Search)); 
 
currPos++ ; 
 
sPush(h_Child); 
 
h_Child=GetWindow(h_Child,GW_HWNDNEXT); 
 
if(!h_Child){ 
 
while (!h_Child&& stack_Top>0){ 
 
h_Child=sPop(); 
 
h_Child=GetWindow(h_Child,GW_CHILD); 
 

 
if(stack_Top== 0)break; 
 

 

 
break; 
 

 
else 
 
h_Wnd=GetWindow(h_Wnd,GW_HWNDNEXT); 
 

 
}  
 
下面是几个简单的操作例子 ,向指定的子窗口发送消息 ,完成规定的操作  
 
修改主窗口的标题 
 
void __fastcall TForm1::btnMainClick(TObject* Sender 
 

 
SetWindowText(h_Wnd,txtToValue- >Text.c_str()); }  
 
修改指定子窗口的文本 ,文本框 txtIndex的内容指定子窗体的索引号 ,用文本框 txtToValue中的内容替换子窗口的文本 
 
void __fastcall TForm1::btnChildClick(TObject* Sender) 
 

 
int ctlIndex; 
 
ctlIndex=txtIndex- >Text.ToInt(); 
 
SetWindowText(hWndArray[ctlIndex],txtToValue- >Text.c_str()); 
 
}  
 
获得类型为文本框的子窗口中的文本 ,将获得的文本放到 memoReadWrite中 
 
void __fastcall TForm1::btnGetClick(TObject* Sender) 
 

 
int ctlIndex; 
 
char theCopy[256]; 
 
memoReadWrite- >Clear(); 
 
ctlIndex=txtIndex- >Text.ToInt(); 
 
SendMessage(hWndArray[ctlIndex],WM_GETTEXT,256,(LPARAM)theCopy); 
 
memoReadWrite- >Lines- >Add(AnsiString(theCopy)); 
 
}
void __fastcall TForm1::btnExitClick(TObject* Sender){ 
 
Application- >Terminate(); 
 
}  
 
用指定的文本替换类型为文本框的子窗口中的文本 
 
void __fastcall TForm1::btnChangeClick(TObject* Sender) 
 

 
int ctlIndex; 
 
ctlIndex=txtIndex- >Text.ToInt(); 
 
SendMessage(hWndArray[ctlIndex],EM_SETSEL,0,1000); 
 
SendMessage(hWndArray[ctlIndex],EM_REPLACESEL, 
 
(WPARAM)true,(LPARAM)(txtToValue- >Text.c_str())); 
 
}  
 
向被操纵的应用程序中类型为按钮的子窗口发送 BM_CLICK,以实现按钮单击动作 
 
void __fastcall TForm1::btnCtlBTNClick(TObject* Sender) 
 

 
int ctlIndex; 
 
ctlIndex=txtIndex- >Text.ToInt(); 
 
SendMessage(hWndArray[ctlIndex],BM_CLICK,0,0); 
 
/*其实 ,如果不熟悉 Windows的消息结构 ,简单的 
 
鼠标和键盘消息同样可以实现大部分操作。例如,发送一个鼠标按下消息 ,再发送一个鼠标弹起消息 ,就可以模拟单击消息。

* /  
 
SendMessage(hWndArray[ctlIndex],WM_LBUTTONDOWN,0,0);  
 
SendMessage(hWndArray[ctlIndex],WM_LBUTTONUP,0,0); 
 

 
头文件 Unit1.h  
 
堆栈 
 
HWND AStack[100];  
 
堆栈指针 
 
int stack_Top;  
 
子窗口句柄数组和主窗口句柄 
 
HWND hWndArray[100],h_Wnd;  
 
入栈 
 
void sPush(HWND hWndValue) 
 

 
if(stack_Top<100) 
 

 
AStack[stack_Top]=hWndValue; 
 
stack_Top++ ; 
 

 
else 
 

 
MessageBox(NULL,“ Stack Overflow” ,“ Stack Error” ,0); 
 

 
}  
 
弹出 
 
HWND sPop() 
 

 
if(stack_Top >0) 
 

 
stack_Top-- ; 
 
return AStack[stack_Top]; 
 

 
else 
 

 
MessageBox(NULL,“ Stack Empty” ,“ Stack Error” ,0); 
 

 

 
# ifndef Unit1H 
 
# define Unit1H 
 
# include <Classes.hpp>
 
# include <Controls.hpp>
 
# include <StdCtrls.hpp>
 
# include <Forms.hpp>
 
# include <ExtCtrls.hpp>
 
# include <Graphics.hpp>
 
class TForm1 : public TForm 
 

 
__published: // IDE- managed Components 
 
TListBox* lstClassName; 
 
TListBox* lstControlText; 
 
TMemo* memoReadWrite; 
 
TEdit* txtTitle; 
 
TEdit* txtIndex; 
 
TEdit* txtToValue; 
 
TButton* btnSearch; 
 
TButton* btnMain; 
 
TButton* btnChild; 
 
TButton* btnGet; 
 
TButton* btnChange; 
 
TButton* btnExit; 
 
TLabel* Label1; 
 
TLabel* Label2; 
 
TLabel* Label3; 
 
TButton* btnCtlBTN; 
 
void__fastcall btnSearchClick(TObject* Sender); 
 
void__fastcall btnMainClick(TObject* Sender); 
 
void__fastcall btnChildClick(TObject* Sender); 
 
void__fastcall btnGetClick(TObject* Sender); 
 
void__fastcall btnExitClick(TObject* Sender); 
 
void__fastcall btnChangeClick(TObject* Sender); 
 
void__fastcall btnCtlBTNClick(TObject* Sender); 
 
private: 
 
public: 
 
__fastcall TForm1(TComponent* Owner); 
 
}; 
 
extern PACKAGE TForm1* Form1; 
 
# endif 
 
通过向作出响应的一方窗口发送 Windows消息,我们可以完成各种复杂的操作。在上面的例子中,“单击按钮”只是让响应窗体完成了按钮单击的动作,如果我们想一想办法,也许可以把按钮对应的窗口函数替换掉,有兴趣的读者可以自己研究一下。 
 
另外,我们可以用此技术做一个针对某一应用程序的 ActiveX控件,在控制程序中加入这个控件,再加入微软的脚本控件 (MSSCRIPT.OCX),通过在外部编写脚本,就可以实现控制的自动化和程序化。

 

 

  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论
<p> <br /> </p> <p> <span style="font-size:14px;color:#E53333;"><strong>#购课赠礼</strong></span> </p> <p> <span style="font-size:12px;">今日下单购课,即送价值98元《MySQL数据库速成宝典》https://edu.csdn.net/course/detail/32434</span> </p> <p> <br /> </p> <p> <span style="font-size:14px;color:#E53333;"><strong>#课程服务</strong></span> </p> <p> <strong>在线答疑</strong>:本课程设有专门讨论留言区,学习中遇到任何问题,直接给老师留言即可,老师都会及时进行回复。<br /> <strong>远程协助</strong>:如果遇到复杂问题,老师还可进行远程协助,这个一般可不是一两百元课程就能享受到。<br /> <strong>源码分享</strong>:为了让大家更好进行项目实战,老师还将课程中涉及到所有源码分享给学员,按照视频中提示进行下载即可。 </p> <p> <br /> </p> <p> 在CSDN分享C++ Qt开发知识已经有6年了,感谢众多博友对我支持,了解到很多人对Qt使用还是有些困扰,例如Qt环境搭建,Qt布局使用,如何使用Qt编写复杂界面,如何自定义非标控件,Qt如何和Web交互,Qt和后台接口如何交互等;经过这几年整理,我决定出这套<strong>《Qt高级开发视频教程》</strong>,带领大家学习Qt高级开发知识,学习如何使用Qt开发企业级别项目;通过本课程学习,大家将会达到企业招聘中高级要求。 </p> <p> <br /> </p> <p> 为了照顾零基础学员,本课程第一章会介绍Qt环境搭建、QtCreator / VS2019基本使用方法,Qt整体架构、Qt信号机制,Qt内存管理等知识。即使没有Qt开发学习经验,也能跟着课程顺利学习。 </p> <p> <span style="color:#666666;">课程核心知识点地图如下:</span> </p> <p> <img src="https://img-bss.csdnimg.cn/202209130826468642.png" alt="" /><br /> <strong>课程每章核心知识点介绍如下:</strong> </p> <p> <strong>第一章</strong>:介绍Qt环境搭建、QtCreator / VS2019基本使用方法,Qt整体架构、Qt信号机制,Qt内存管理等知识。 </p> <p> <strong>第二章</strong>:了解到很多学员对于Qt界面布局很不熟悉,将会详细介绍Qt设计器布局,以及如何C++代码手写布局,从常见企业级项目入手,带领大家学会各种布局实现,例如WPS、腾讯会议、优酷、迅雷等界面实现;界面布局会了,这是企业项目开发第一步,还有更重要无边框窗口,如何设计一个合理无边框窗口很重要,<br /> <br /> <strong>第三/四章</strong>:详细介绍如何实现一个无边框窗口,如何自定义标题栏,如何实现拖拽拉伸;第四章将会介绍如何自定义非标控件,优化Qt界面。<br /> <br /> <strong>第五章</strong>:介绍Qt web混合编程,一个商用项目,必然会涉及到web交互,这也是很多Qt开发者弱项,这一章讲详细介绍C++ Qt web混合开发。<br /> <br /> <strong>第六章</strong>:既然是做企业级项目,必然需要和后台交互,http编程也是必要,将详细介绍http编程,用户注册,登录,后台接口请求等知识;通过第五、六章学习,将会是你Qt开发技术更上一层楼。<br /> <br /> <strong>第七章</strong>:介绍Qt并发编程,耗时任务处理,进程调用等知识。<br /> <br /> <strong>第八、九章</strong>:讲解 Qt 比较重要知识,图形视图结构,以及MVD模式;通过这两章学习,大家会对图形视图有更好了解。<br /> <br /> <strong>第十章</strong>:本章是独立章节,主要介绍Qt中一些特殊技巧,项目编译,dpi适配、多语言等知识。<br /> <br /> <strong>第十一章</strong>:是我们企业级项目实战:实现一个视频会议客户端,本项目可以进行多人视频通话,直播,桌面分享等功能,本项目我会从零开始,进行项目搭建,功能调试,bug fixed, 带领大家做一个企业级项目。 </p> <p> <br /> </p> <p> 希望通过本课程学习,大家C++ Qt开发技术能有质飞越,能找到自己心仪工作。 </p> <p> <br /> </p> <p> 课程中如果讲不对地方,请大家指出,我及时修正,我也只是一个普通开发者,也不是所有技术都会,尽我所能,把我所会教给大家,让我们一起为Qt发展,尽一份绵薄之力。  </p> <p> <br /> </p> <p> <strong><span style="color:#E53333;">下面是本课程一些项目截图:</span></strong> </p> <p> 1 可以滑动设置界面 </p> <p> <img src="https://img-bss.csdnimg.cn/202206151216194138.png" alt="" /> </p> <p>         2 所有图形绘制 </p> <p> <img src="https://img-bss.csdnimg.cn/202206151218387064.png" alt="" /> </p> <p>       3 视频播放器 </p> <p> <img src="https://img-bss.csdnimg.cn/202206151216482230.png" alt="" /> </p> <p>          4 高仿youku界面 </p> <p> <img src="https://img-bss.csdnimg.cn/202206151255417939.png" alt="" /> </p> <p>         5 视频会议 </p> <p> <img src="https://img-bss.csdnimg.cn/202206151256348340.png" alt="" /> </p> <p>         相信通过本课程学习,大家有能力实现绝大部分客户端项目,从此用C++ Qt再也不会有难写界面。 </p>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

iBreathe

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值