如何控制其他程序窗体上的窗口控件,枚举设备

delphi 枚举设备使用代码

有了回调函数的概念及上面的例子,我们可以继续了。其实想要找到一个标题已知的窗口句柄,用一个API函数就可以了:FindWindow.

现在的 delphi(2010、xe) 已经自带了 directx

其函数原形是:

的相关单元(...sourcertlwin).

//枚举函数
function directsoundenumerate(
  lpdsenumcallback: tdsenumcallback; //回调函数
  lpcontext: pointer                 //用户指针
): hresult; stdcall; //返回错误代码, 成功则返回 s_ok(0)

//directsoundenumerate 需要的回调函数的原形:
tdsenumcallback = function(
  lpguid: pguid;            //设备的 guid
  lpcstrdescription: pchar; //设备描述
  lpcstrmodule: pchar;      //模块标识
  lpcontext: pointer        //由 directsoundenumerate 提供的用户指针
): bool; stdcall; //返回 true 表示要继续枚举, 不在继续找了就返回 false


function FindWindow(lpClassName, lpWindowName: PChar): HWND; stdcall;

这是常见的代码:

 
unit unit1;

interface

uses
  windows, messages, sysutils, variants, classes, graphics, controls, forms,
  dialogs, stdctrls;

type
  tform1 = class(tform)
    listbox1: tlistbox; //只在窗体上放了一个列表框
    procedure formcreate(sender: tobject);
  end;

var
  form1: tform1;

implementation

{$r *.dfm}

uses directsound; //!

function enumcallback(lpguid: pguid; lpcstrdescription, lpcstrmodule: pchar;
    lpcontext: pointer): bool; stdcall;
begin
  form1.listbox1.items.add(lpcstrdescription);
  result := true;
end;

procedure tform1.formcreate(sender: tobject);
begin
  directsoundenumerate(enumcallback, nil);
end;

end.


lpClassName:窗口类名.如果只知道标题,可以为空.窗口类名可以用很多工具获得.如winsignt32.
lpWindowName:窗口标题.

在回调函数中直接使用窗体控件不好, 修改如下:

 
uses directsound;

function enumcallback(lpguid: pguid; lpcstrdescription, lpcstrmodule: pchar;
    lpcontext: pointer): bool; stdcall;
begin
  tstrings(lpcontext).add(lpcstrdescription);
  result := true;
end;

procedure tform1.formcreate(sender: tobject);
begin
  directsoundenumerate(enumcallback, listbox1.items);
end;


调用方式举例:

获取更多信息:

 
uses directsound;

function enumcallback(lpguid: pguid; lpcstrdescription, lpcstrmodule: pchar;
    lpcontext: pointer): bool; stdcall;
begin
  if lpguid <> nil then tstrings(lpcontext).add(guidtostring(lpguid^));
  tstrings(lpcontext).add(lpcstrdescription);
  if lpcstrmodule <> nil then tstrings(lpcontext).add(lpcstrmodule);
  tstrings(lpcontext).add(emptystr);
  result := true;
end;

procedure tform1.formcreate(sender: tobject);
begin
  directsoundenumerate(enumcallback, listbox1.items);
end;

var wndhwnd:HWND;
wndhwnd:=FindWindow(nil,某窗口标题);
if wndhwnd<>0 then  file://找到此窗口句柄.
begin
  xxxxx
end
else begin
  MessageBox(self.handle,没找到该窗口句柄,提示,0);
end;

有了这个窗口句柄,就离我们的初始目的不远了:控制其他窗体上的窗口控件.

同样,首先要得到其他窗体上窗口控件的句柄.我们用这个API函数:EnumChildWindows.

其函数原形是:
function EnumChildWindows(hWndParent: HWND; lpEnumFunc: TFNWndEnumProc;
  lParam: LPARAM): BOOL; stdcall;

这个函数和EnumWindow函数很有些想象.其作用也很相似.它的功能就是列举窗口句柄为hWndParent的窗体上所有的窗口控件的句柄.同样也是以回调函数参数的形式给出的.

我们再举一个实际的例子,来说明这个函数的用法.程序的功能是让用户输入一个窗口标题,然后调用FindWindow函数找到此窗口句柄.通过这个句柄,我们在一个Memo里显示该窗口上所有的窗口控件.

同样先编写回调函数.
function  EnumChildWndProc(AhWnd:LongInt;
  AlParam:lParam):boolean;stdcall;
var
  WndClassName: array[0..254] of Char;
  WndCaption: array[0..254] of Char;
begin
  GetClassName(AhWnd,wndClassName,254);
  GetWindowText(aHwnd,WndCaption,254);
  with form1.memo1 do
  begin
    lines.add( string(wndClassName));
    lines.add( string(wndCaption));
    lines.add(-------);
  end;
  result:=true;
end;

然后在一事件里调用EnumChildWindows函数.
procedure TForm1.Button1Click(Sender: TObject);
var
  hWnd:LongInt;
begin
  memo1.Lines.Clear;
  Memo1.Lines.Add(Edit1.Text+ 有如下控件类名称);
  hWnd:=FindWindow(nil,pchar(Edit1.Text));
  if hWnd<>0 then
  begin
    EnumChildWindows(hWnd,@EnumChildWndProc,0);
  end
  else  MessageBox(self.handle,没找到该窗口句柄,提示,0);
end;

程序清单如下:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Memo1: TMemo;  file://用来显示找到的控件
    Label1: TLabel; 
    Edit1: TEdit;  file://输入标题.
    Button1: TButton; 
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

  function  EnumChildWndProc(AhWnd:LongInt;
    AlParam:lParam):boolean;stdcall;

implementation

{$R *.dfm}
function  EnumChildWndProc(AhWnd:LongInt;
  AlParam:lParam):boolean;stdcall;
var
  WndClassName: array[0..254] of Char;
  WndCaption: array[0..254] of Char;
begin
  GetClassName(AhWnd,wndClassName,254);
  GetWindowText(aHwnd,WndCaption,254);
  with form1.memo1 do
  begin
    lines.add( string(wndClassName));
    lines.add( string(wndCaption));
    lines.add(-------);
  end;
  result:=true;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  hWnd:LongInt;
begin
  memo1.Lines.Clear;
  Memo1.Lines.Add(Edit1.Text+ 有如下控件类名称);
  hWnd:=FindWindow(nil,pchar(Edit1.Text));
  if hWnd<>0 then
  begin
    EnumChildWindows(hWnd,@EnumChildWndProc,0);
  end
  else  MessageBox(self.handle,没找到该窗口句柄,提示,0);
end;

end.

有了控件句柄,我们当然就可以随心所欲了.比如:

SendMessage(hWnd,WM_SETTEXT,0,LongInt(Pchar(sdafdsf)));就可以给控件发送文本.其他还可以发送不同的消息可以做很多事情.

但是,有很大一个问题:假设一个窗体上有很多相同的控件,并且根本没办法区分他们,即使我们能找到所有的控件句柄,我们又不能区分到底哪个是我们想要的,同样是干着急.

我想了很长时间,后来在大富翁里找到了答案,只要用到一个小技巧,就可以解决了.

. 其函数原形是...

本文由365bet体育在线官网发布于365bet,转载请注明出处:如何控制其他程序窗体上的窗口控件,枚举设备

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。