C++的进程间响应技术

原创 2001年04月30日 09:47:00

                           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),通过在外部编写脚本,就可以实现控制的自动化和程序化。

 

 

Linux下的多进程间共享资源的互斥访问

把源代码运行一遍就知道了#include #include #include #include #include #include pthread_mutex_t*...
  • lanseshenhua
  • lanseshenhua
  • 2010年05月04日 19:21
  • 7960

C++中四种进程或线程同步互斥的控制方法

现在流行的进程线程同步互斥的控制机制,其实是由最原始最基本的4种方法实现的。由这4种方法组合优化就有了.Net和Java下灵活多变的,编程简便的线程进程控制手段。   这4种方法具体定义如下 在《操作...
  • educast
  • educast
  • 2014年01月21日 12:35
  • 6875

linux进程间同步

原文链接:http://www.jianshu.com/p/eba17ea42e78 为了能够有效的控制多个进程之间的沟通过程,OS必须提供一定的同步机制保证进程之间不会自说自话而是有效的协同工...
  • CrazyTeam
  • CrazyTeam
  • 2016年03月17日 14:30
  • 1329

C++进程间通信

C++进程间通信进程间通讯的四种方式:剪贴板、匿名管道、命名管道和邮槽剪切板//设置剪切板内容CString str; this->GetDlgItemText(IDC_EDIT1, str);Ope...
  • CHIHUN_LOVE
  • CHIHUN_LOVE
  • 2016年12月30日 16:22
  • 879

进程之间的数据传递

  随着我们开发的应用的日益复杂,像以往那样将所有功能坐在一个exe文件中情况越来越少,更多时候是整个应用由若干模块、甚至若干单独的exe文件组成,这就涉及到了模块或进程间的通讯交互问题,本文主要谈谈...
  • leikezhu1981
  • leikezhu1981
  • 2011年05月23日 17:12
  • 3161

C++进程间通信---自定义消息

在windows中消息分为两种,即系统消息和用户自定义消息,系统消息定义从0到0x3ff,可以使用0x400到0x7fff定义自己的消息。windows把0x400定义为WM_USER,如果想定义自己...
  • oLanSeFengYe1
  • oLanSeFengYe1
  • 2016年12月16日 15:19
  • 488

进程间共享互斥所

static pthread_mutex_t *mptr;   将互斥锁放在共享内存。 设置互斥锁的属性为PTHREAD_PROCESS_SHARED,并初始化互斥锁。 void my_loc...
  • wtewrw
  • wtewrw
  • 2014年09月28日 22:39
  • 1291

进程间共享变量

在php中可以实现在进程间共享信息的途径,并保证能快速地访问这些共享数据。有两种方式:shmop 和 System V这两种共享内存扩展方式。   shmop使用的例子: // create k...
  • u010437896
  • u010437896
  • 2013年05月02日 17:38
  • 1373

进程间交互的几种方式

# 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。 # 有名管道 (named pipe) : 有名管道也...
  • SHENNONGZHAIZHU
  • SHENNONGZHAIZHU
  • 2016年04月11日 21:27
  • 2704

进程间同步的方法

进程间同步的方法   2010-05-10 01:03:42|  分类: Linux|字号 订阅 进程间通讯(IPC)方法主要有以下几种:        管道/F...
  • jfkidear
  • jfkidear
  • 2012年07月09日 14:59
  • 11851
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++的进程间响应技术
举报原因:
原因补充:

(最多只允许输入30个字)