Delphi中如何控制其他程序窗体上的窗口控件
回调函数一般是按照调用者的要求定义好参数和返回值的类型,你向调用者提供你的回调函数的入口地址,然后调用者有什么事件发生的时候就可以随时按照你提供的地址调用这个函数通知你,并按照预先规定好的形式传递参数。所以很多人打比方,说回调函数还真有点像您随身带的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[..] of char; //定义两个缓冲区。
begin
GetWindowText(AhWnd,lpszWindowText,); //得到窗口标题
GetClassName(AhWnd,lpszClassName,); //得到窗口类名。
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[..] of char;
begin
GetWindowText(AhWnd,lpszWindowText,);
GetClassName(AhWnd,lpszClassName,);
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单步跟踪调试一下,看看回调函数是怎么被调用的 本文来自Delphi之窗,原文地址:http://www.52delphi.com
Delphi中如何控制其他程序窗体上的窗口控件的更多相关文章
- Delphi 查找标题已知的窗口句柄,遍历窗口控件句柄(转)
用我的方法来控制其他程序窗体上的窗口控件,必须先了解什么是 回调函数.我的理解是这样的: 回 调函数写出来不是自己的程序去调用的,反而是让其他的东西去调用,比如windows操作系统,比如其他的程序等 ...
- Delphi 查找标题已知的窗口句柄,遍历窗口控件句柄
有了回调函数的概念及上面的例子,我们可以继续了.其实想要找到一个标题已知的窗口句柄,用一个API函数就可以了:FindWindow.其函数原形是:function FindWindow(lpClass ...
- delphi7 如何描述窗体上的全部控件
在delphi开发中,经常需要用到窗体中控件的name名来进行对象方法或属性的调用,所以如何对delphi窗体进行简洁,清楚,完整的描述就很重要.最好能不看界面也能进行界面编码,具体如下表所示: xx ...
- 在wpf窗体上添加用户控件
1.引用用户控件的命名控件 xmlns:my="clr-namespace:WpfApplicationDemo.Control" 2.把用户控件添加到窗体中 <my:Use ...
- C# 在窗体上可拖动控件
最近做了一个标签打印配置功能,需要根据客户需求自定义标签格式.显示内容,这时就用到了后台生成控件,并且其控件可在窗口中进行拖动,这里仅为记录一下实现过程,方便以后使用. 结果图: 源码: using ...
- 当一个窗体上有PageControl 控件时,是先执行 FormShow呢,还是先执行PageControl 的 TabSheet2Show呢
答案是 先执行 TabSheet2Show ,总算知道了,顺便推理 Onshow事件的执行顺序是 从内到外,先执行容器内的控件的事件,再执行 窗体的事件
- WM_ERASEBKGND官方解释(翻译),以及Delphi里所有的使用情况(就是绘制窗口控件背景色,并阻止进一步传递消息)
#define WM_ERASEBKGND 0x0014 Parameters wParam A handle to the device context. // ...
- WPF Prism MVVM 中 弹出新窗体. 放入用户控件
原文:WPF Prism MVVM 中 弹出新窗体. 放入用户控件 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_37214567/artic ...
- 《zw版·delphi与halcon系列原创教程》zw版_THOperatorSetX控件函数列表 v11中文增强版
<zw版·delphi与halcon系列原创教程>zw版_THOperatorSetX控件函数列表v11中文增强版 Halcon虽然庞大,光HALCONXLib_TLB.pas文件,源码就 ...
随机推荐
- RTP与RTCP协议介绍
转自:http://zhangjunhd.blog.51cto.com/113473/25481/ 本文主要介绍RTP与RTCP协议. author: ZJ 06-11-17 Blog: [url ...
- AutoCompleteTextView自动填充文本
布局: <AutoCompleteTextView android:id="@+id/auto" android:layout_width="match_paren ...
- Redis 连接池的问题
目录 Redis 连接池的问题 1 1. 前言 1 2.解决方法 1 前言 问题描述:Redis跑了一段时间之后,出现了以下异常. Redis Timeout ex ...
- C#二进制与字符串之间的相互转换
1 /// <summary> 2 /// 将字符串转成二进制 3 /// </summary> 4 /// <param name="s">& ...
- cocos2d 创建精灵图
// 在init这个函数当中做一些初始化的事情 bool HelloWorld::init() { ////////////////////////////// // 先构造父级对象 if ( !CC ...
- 稳定的奶牛分配 && 二分图多重匹配+二分答案
题意: 农夫约翰有N(1<=N<=1000)只奶牛,每只奶牛住在B(1<=B<=20)个奶牛棚中的一个.当然,奶牛棚的容量有限.有些奶牛对它现在住的奶牛棚很满意,有些就不太满意 ...
- JS正则表达式验证数字(很全)
1.<script type="text/javascript"> 2. function validate(){ 3. var reg = new ...
- asp.net 微信企业号办公系统-流程设计--流程步骤设置-按钮设置
按钮设置是配置当前步骤的处理者可以执行哪些操作,每个按钮都有对应的执行脚本(javascript脚本). 从左边的按钮列表中选择当前步骤需要的按钮. 注意:如果是流程最后一步则要配置完成按钮而不是发送 ...
- jQuery加载外部文件的方式get、post、ajax、load的区别及异步加载的实现
一.$.post(url, [data], [callback], [type]) url (String) : 发送请求的URL地址. data (Map) : (可选) 要发送给服务器的数据,以 ...
- audio.js – 随时随地,播放 HTML5 的声音
audio.js是一个HTML5标签的简易包装.但它不仅在支持HTML5的浏览器上能够轻松调用标签,并在不支持HTML5的浏览器上也能通过Flash作为B计划使用.除此之外,audio.js所提供的界 ...