Tipy a triky v Delphi, díl 109.

A máme zde opět něco netradičního a ne příliš často používaného. Budeme programově mačkat tlačítka cizích aplikací.
Jistě, rovnou uznávám, že to není zrovna běžný postup, jak komunikovat s cizí aplikací a je to s trochou nadsázky "pirátský" způsob. Nicméně někdy jinou možnost nemáme, takže se může popsaný způsob některému ze čtenářů hodit.

Nejprve lehce a zjednodušeně nastíním celý postup. Vytvoříme funkci, jejímž parametrem bude handle okna cílové aplikace a text příslušného tlačítka. Funkce pak příslušné okno a tlačítko najde a pošle mu zprávu BM_CLICK, čímž dojde k jeho stisknutí.

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function EnumChildProc(Wnd: hWnd; SL: TStrings): BOOL; stdcall;
var
  szFull: array[0..MAX_PATH] of Char;
begin
  Result := Wnd <> 0;
  if Result then
  begin
    GetWindowText(Wnd, szFull, SizeOf(szFull));
    if (Pos(SL[0], StrPas(szFull)) > 0) and (SL.IndexOfObject(TObject(Wnd)) < 0)
    then SL.AddObject(StrPas(szFull), TObject(Wnd));
    EnumChildWindows(Wnd, @EnumChildProc, Longint(SL));
  end;
end;

function ClickButton(ParentWindow: Hwnd; const ButtonCaption: string): Boolean;
var
  SL: TStringList;
  H: hWnd;
begin
  SL := TStringList.Create;
  try
    SL.AddObject(ButtonCaption, nil);
    EnumChildWindows(ParentWindow, @EnumChildProc, Longint(SL));
    H := 0;
    case SL.Count of
      1: ShowMessage(`Objekt nenalezen.`);
      2: H := hWnd(SL.Objects[1]);
    else
      ShowMessage(`Text neni jednoznacny.`);
    end;
  finally
    SL.Free;
  end;
  Result := H <> 0;
  if Result then PostMessage(H, BM_CLICK, 0, 0);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ClickButton(FindWindow(`TForm1`, `Form1`), `Button1`);
end;

end.

Jak vidíte v ukázce, k získání handle pro hledané okno použijeme funkce FindWindow s patřičnými parametry (tedy třída okna a nadpis okna). Pro otestování příkladu (tak, jak je napsán) si vytvořte novou aplikaci s jedním tlačítkem Button1 a tomuto tlačítku přiřaďte nějakou událost. Například může zobrazit text pomocí ShowMessage. Tuto aplikaci poté spusťte a rovněž náš dnešní příklad. Když pak tlačítkem aktivujeme funkci a vše půjde dobře, bude stisknuto tlačítko u druhé aplikace a zobrazen váš text. Ovšem pozor. Důležité je, aby jste změnili název okna u aplikace s dnešním příkladem. Proč? Protože pokud to neuděláte, bude mít formulář titulek Form1 a bude pochopitelně třídy TForm1. A navíc obsahuje i tlačítko Button1 pro spuštění funkce. Co se stane, pokud nezměníte názvy? Aktivací tlačítka se spustí funkce, která začne přesně podle popsaného postupu hledat cílové okno a cílové tlačítko. Program ovšem najde sám sebe a znovu stiskne tlačítko, čímž se znovu spustí hledání. A stále dokola. Dojde tak vlastně k nekonečnému zacyklení, kdy bude neustále mačkáno tlačítko naší aplikace. Proto nezapomeňte upravit příslušným způsobem název okna.

Diskuze (2) Další článek: NVidia představila GoForce 2150

Témata článku: Software, Windows, Programování, Díl, Trik, Popsaný způsob

Určitě si přečtěte


Aktuální číslo časopisu Computer

Test 6 odolných telefonů a 22 powerbank

Srovnání technologií QLED a OLED

Měřte své sportovní výkony

Sady pro chytrou domácnost