如何控制其他程序窗体上的窗口控件:上

原创 2003年01月27日 10:10:00

如何控制其他程序窗体上的窗口控件:上

首先申明:我是菜鸟,我只不过想把困绕了我很长时间的问题的解决方案发表出来,免得以后我又忘记,同时给还不知道这些小知识的同僚一些帮助。各位不要笑我的浅薄。同时为了表示我的低级,我会很罗嗦的讲一些基本的东西,这些都是我的理解,很不准确。

用我的方法来控制其他程序窗体上的窗口控件,必须先了解什么是回调函数。我的理解是这样的:

回调函数写出来不是自己的程序去调用的,反而是让其他的东西去调用,比如windows操作系统,比如其他的程序等等之类的。但是什么时候被调用却不知道了。回调函数一般是按照调用者的要求定义好参数和返回值的类型,你向调用者提供你的回调函数的入口地址,然后调用者有什么事件发生的时候就可以随时按照你提供的地址调用这个函数通知你,并按照预先规定好的形式传递参数。所以很多人打比方,说回调函数还真有点像您随身带的BP机:告诉别人号码,在它有事情时Call您!

所以一个回调函数写出来之后,一定有个注册的动作,就是告诉调用者,你怎么样找到我写的函数。某些Windows API 函数会要求以回调函数地址作为其参数之一,例如SetTimer 、LineDDA 、EnumObjects,以及我们下面要用到的EnumWindows。

在Delphi里声明一个回调函数的格式很简单,例如:

function EnumWindowsProc(AhWnd:LongInt;lParam:LongInt):boolean;stdcall;

首先是函数名称可以随便乱取,但函数参数的类型一般不得乱来,其顺序,数据类型等都有规定的,因为这些都是让其他程序调用的,他们已经规定好了的,但参数名称可以随便乱叫。注意后面一定要带上“stdcall”,

stdcall是标准调用,也就是说采用标准windows参数传递方式来调用函数。

编写函数体就很简单了,利用传递过来的参数就可以了,只要记住,这些参数是别人送给你的,你只要知道这些参数代表了什么意思。

再看个向调用者注册回调函数入口地址的函数。
function EnumWindows(lpEnumFunc: TFNWndEnumProc; lParam: LPARAM): BOOL; stdcall;

TFNWndEnumProc其实就是指针类型。其中的lpEnumFunc就是回调函数的入口地址了。

下面是调用EnumWindows的格式:
EnumWindows(@EnumWindowsProc,0);

通过向系统注册回调函数的入口地址,系统就能在需要的时候,调用回调函数,传递参数给它,也许这些参数就是我们想要的。

EnumWindows函数的功能是:枚举屏幕上所有程序中的顶层窗口,将窗口句柄以参数的形式传递给回调函数。找到一个窗口,就调用一次回调函数。枚举结束的条件是:要么枚举完所有的窗口,要么回调函数返回False。

lParam: LPARAM参数是程序定义的值,这个值被传递到回调函数。

回过头来再看一下EnumWindowsProc:

function EnumWindowsProc(AhWnd:LongInt;lParam:LongInt):boolean;stdcall;

当系统找到了一个窗口后,就开始调用这个回调函数,将窗口的句柄作为第一个参数传递过来,将在EnumWindows中lParam: LPARAM这个程序定义的值作为第二个参数传递过来。

所以我们可以在EnumWindowsProc函数中利用传递过来的两个参数来做某些处理了。

下面我们新建一个程序列举系统中所有程序的顶层窗口,我们要得到窗口的标题,要得到窗口类名称。

得到窗口标题用:

function GetWindowText(hWnd: HWND; lpString: PChar; nMaxCount: Integer): Integer; stdcall;

该函数功能是将窗口句柄为hWnd的窗口的标题拷入到一个缓冲区lpString。nMaxCount是拷入缓冲区内的最大的字符数。

要得到窗口标题还可以发送消息:WM_GETTEXT,其实GetWindowText就是发送WM_GETTEXT消息的。

要得到窗口类名称用:

function GetClassName(hWnd: HWND; lpClassName: PChar; nMaxCount: Integer): Integer; stdcall;

其参数意义和上面的函数差不多。不详细解释了。

我们先编写回调函数:EnumWindowsProc。现在告诉自己,我们已经有了两个参数的值了。这两个参数是系统给我们的.

为了显示窗口标题和类名,我们用一个TMemo控件。

先在interface部分声明函数。

function EnumWindowsProc(AhWnd:LongInt;AForm:TForm1):boolean;stdcall;

注意我将第二个参数改了,不要紧,到时候调用的时候注意看。

然后在implementation部分定义函数:
function EnumWindowsProc(AhWnd:LongInt;AForm:TForm1):boolean;
var
  lpszClassName,lpszWindowText:array[0..254] of char;  //定义两个缓冲区。
begin
  GetWindowText(AhWnd,lpszWindowText,254); //得到窗口标题
  GetClassName(AhWnd,lpszClassName,254); //得到窗口类名。
  Aform.memo1.lines.add(StrPas(lpszWindowText));
  Aform.memo1.lines.add(StrPas(lpszClassName));
  Aform.memo1.lines.add('--------------------');
  Result:=True;
end;

接着需要做的就是调用EnumWindows函数,注册回调函数入口地址,让系统调用回调函数,列举窗口了。所以再添加一个TButton: btn_listwindow
procedure TForm1.btn_listwindowClick(Sender: TObject);
begin
  EnumWindows(@EnumWindowsProc,LongInt(self));
end;

程序清单如下:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    btn_listwindow: TButton;
    procedure btn_listwindowClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

  function EnumWindowsProc(AhWnd:LongInt;AForm:TForm1):boolean;stdcall;

implementation
{$R *.dfm}
function EnumWindowsProc(AhWnd:LongInt;AForm:TForm1):boolean;
var
  lpszClassName,lpszWindowText:array[0..254] of char;
begin
  GetWindowText(AhWnd,lpszWindowText,254);
  GetClassName(AhWnd,lpszClassName,254);
  Aform.memo1.lines.add(StrPas(lpszWindowText));
  Aform.memo1.lines.add(StrPas(lpszClassName));
  Aform.memo1.lines.add('--------------------');
  Result:=True;
end;

procedure TForm1.btn_listwindowClick(Sender: TObject);
begin
  EnumWindows(@EnumWindowsProc,LongInt(self));
end;

end.
F9,运行,看看结果。最好是F7单步跟踪调试一下,看看回调函数是怎么被调用的。

 

 


 

通过api获取句柄控制其他窗体

很多时候,编写程序模拟鼠标和键盘操作可以方便的实现你需要的功能,而不需要对方程序为你开放接口。比如,操作飞信定时发送短信等。我之前开发过飞信耗子,用的是对飞信协议进行抓包,然后分析协议,进而模拟协议的...
  • u010984552
  • u010984552
  • 2016年08月23日 15:19
  • 3992

C#将外部窗口嵌入到WPF控件当中

C#讲外部窗口嵌入到WPF控件当中本Markdown编辑器使用[StackEdit][6]修改而来,用它写博客,将会带来全新的体验哦: 可能会用到的API函数 public class Win...
  • hxfhq1314
  • hxfhq1314
  • 2017年01月13日 20:08
  • 1891

C#自定义控件:WinForm将其它应用程序窗体嵌入自己内部

http://www.cnblogs.com/bitzhuwei/archive/2012/05/24/SmileWei_EmbeddedApp.html 大家可以到(https:/...
  • y13156556538
  • y13156556538
  • 2016年11月10日 14:49
  • 2492

怎样控制其他程序窗体上的窗口控件

作者:摘自多个网站 用我的方法来控制其他程序窗体上的窗口控件,必须先了解什么是回调函数。我的理解是这样的: 回调函数写出来不是自己的程序去调用的,反而是让其他的东西去调用,比如windows操作系...
  • mahushen
  • mahushen
  • 2012年11月29日 12:52
  • 384

Qt中窗体控件按照比例缩放,自适应窗口大小进行布局

最近在做本科毕设,用到了Qt,无奈本人实在是太过于小白了,很多东西都进行了很久的探索,比如今天说到的窗体控件布局...一把辛酸泪     首先就是创建一个GUI文件,然后进行UI设计,这里就只需要从左...
  • sinat_36420785
  • sinat_36420785
  • 2017年03月11日 22:24
  • 8581

Qt Creator 窗体控件自适应窗口大小布局

常见的软件窗口大小改变(最大化、手动改变时)需要窗口的部件能够自适应布局,而在Qt的应用程序界面设计中,对于像我一样的初学者如何实现窗口自适应调整还是要绕点弯路的。网上百度了很多,多数说的很含糊,还有...
  • niepangu
  • niepangu
  • 2016年03月17日 20:48
  • 296

Qt Creator 窗体控件自适应窗口大小布局

常见的软件窗口大小改变(最大化、手动改变时)需要窗口的部件能够自适应布局,而在Qt的应用程序界面设计中,对于像我一样的初学者如何实现窗口自适应调整还是要绕点弯路的。网上百度了很多,多数说的很含糊,还有...
  • niepangu
  • niepangu
  • 2016年03月30日 18:04
  • 533

Qt Creator 窗体控件自适应窗口大小布局

转载自:http://www.cnblogs.com/emouse/archive/2013/05/19/3087708.html 常见的软件窗口大小改变(最大化、手动改变时)需要窗口的部件能够自适...
  • Andy_baby
  • Andy_baby
  • 2015年08月21日 10:42
  • 486

WebBrowser控件应用:弹出新窗体和关闭窗口 (转)

缘起:上次写了一个《WebBrowser控件的简单应用2》,提到了在NewWindow事件中打开新窗口的例子。有网友“队长 ”提出那个事件得到的参数是本页面的,而不是新页面的,经过测试,果然url参数...
  • charlie1190
  • charlie1190
  • 2011年01月04日 22:15
  • 935

CFormView随着窗口的变化,Control及OLE控件自动居中窗体

CFormView随着窗口的变化,Control及OLE控件自动调整位自动居中 //网上也没有找到,通过自己努力看原代码,本问题已经解决。现贡献自己的一点力量,有不宜之处,望凉解; //问题主...
  • wxinstudent
  • wxinstudent
  • 2012年06月03日 12:28
  • 543
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:如何控制其他程序窗体上的窗口控件:上
举报原因:
原因补充:

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