使用Python脚本自动化 Delphi 2007应用程序-如何明确引用控件?

vc6uscn9  于 2023-10-18  发布在  Python
关注(0)|答案(1)|浏览(114)

我有一个遗留的 Delphi 应用程序,我需要自动化测试的目的。我很难将自动化请求定向到正确的组件。包含的示例演示了这个问题(无论如何,在我的环境中)。这里有一个简单的 Delphi 应用程序,我想控制:

Project1.dpr

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Unit1.pas

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    CheckBox1: TCheckBox;
    Timer1: TTimer;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    Label2: TLabel;
    Panel1: TPanel;
    procedure ControlClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.ControlClick(Sender: TObject);
begin
Memo1.Lines.Add (Format ('Control "%s" clicked', [TControl (Sender).Name])) ;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
if Assigned(Screen.ActiveControl) then
    begin
    Panel1.Caption := Screen.ActiveControl.Name ;
    end
else
    begin
    Panel1.Caption := 'None.' ;
    end ;
end ;

end.

Unit1.dfm

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 212
  ClientWidth = 407
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Label2: TLabel
    Left = 73
    Top = 193
    Width = 32
    Height = 13
    Caption = 'Focus:'
  end
  object Memo1: TMemo
    Left = 24
    Top = 8
    Width = 201
    Height = 177
    TabOrder = 0
  end
  object Button1: TButton
    Left = 304
    Top = 11
    Width = 75
    Height = 25
    Caption = '1'
    TabOrder = 1
    OnClick = ControlClick
  end
  object CheckBox1: TCheckBox
    Left = 296
    Top = 171
    Width = 97
    Height = 17
    Caption = 'CheckBox1'
    TabOrder = 6
    OnClick = ControlClick
  end
  object Button2: TButton
    Left = 304
    Top = 42
    Width = 75
    Height = 25
    Caption = '2'
    TabOrder = 2
    OnClick = ControlClick
  end
  object Button3: TButton
    Left = 304
    Top = 73
    Width = 75
    Height = 25
    Caption = '3'
    TabOrder = 3
    OnClick = ControlClick
  end
  object Button4: TButton
    Left = 304
    Top = 104
    Width = 75
    Height = 25
    Caption = '4'
    TabOrder = 4
    OnClick = ControlClick
  end
  object Button5: TButton
    Left = 304
    Top = 135
    Width = 75
    Height = 25
    Caption = '5'
    TabOrder = 5
    OnClick = ControlClick
  end
  object Panel1: TPanel
    Left = 116
    Top = 191
    Width = 109
    Height = 17
    TabOrder = 7
  end
  object Timer1: TTimer
    Interval = 300
    OnTimer = Timer1Timer
    Left = 240
    Top = 152
  end
end

Automate.py

import pywinauto
from pywinauto import application

def Click (AForm, AControlName):
    FControl = AForm [AControlName]
    FControl.click()
    return ()

FormTitle = "Form1"
try:
    app = application.Application().connect(title=FormTitle)
    form1 = app[FormTitle]

    Click (form1, "Button1")
    Click (form1, "Button2")
    Click (form1, "Button3")
    Click (form1, "Button4")
    Click (form1, "Button5")

    Click (form1, "Checkbox1")

    exit (0)

except pywinauto.application.ProcessNotFoundError:
    print(f"No running instance of {FormTitle} found.")
    exit (1)

except Exception as e:
    print(f"An error occurred: {str(e)}")
    exit (1)

一切都很好,除了按钮颠倒。如果我直接单击Button 1,Button 5会记录一次单击。其他实验表明,它不一定能预测如何重定向请求-例如,复选框是OK的,尽管我从未尝试过大量的复选框。我想要的只是一种明确的引用控件的方式--因为控件名并不能解决这个问题。

UPDATE进一步的实验似乎表明,控件的 caption 是我需要传递给调用以向控件发送单击消息的内容。

vuktfyat

vuktfyat1#

按属性或按项目访问执行防打字错误的搜索过程。这个过程中的索引是不同的。这在Getting Started Guide中有更详细的描述。
对于搜索的确切标题,你需要使搜索条件这样(它的工作速度更快!):

form1.child_window(title="1", class_name="TButton").click()
form1.child_window(title="2", class_name="TButton").click()    
form1.child_window(title="3", class_name="TButton").click()

如果你想知道正确的规范,只需转储它:

form1.dump_tree()

所以你可以从这个转储文件中复制粘贴这样的child_window规范。
顺便说一句,connect方法有一个已知的问题,现在需要显式超时:connect(title=FormTitle, timeout=10)

相关问题