Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Button in einer fremden Anwendung aktivieren (https://www.delphipraxis.net/177139-button-einer-fremden-anwendung-aktivieren.html)

musicman56 18. Okt 2013 16:07

Button in einer fremden Anwendung aktivieren
 
Hallo API-Spezialisten,

ich möchte von meinem Programm aus die Windows-Wählhilfe starten und in das Eingabefeld die Telefonnummer schreiben. Das klappt auch wunderbar. Das Problem ist, der Button [Wählen] in der Wahlhilfe wird dadurch nicht aktiviert. Erst wenn der User die Telefonnummer im Eingabefeld nochmals ändert, ist der Button aktiviert. Die Abhilfe wäre wohl, dem Button oder dem Eingabefeld eine weitere Message zur Aktivierung zu schicken, aber welche, das ist meine Frage bzw. mein Problem.

Es soll mal eine Konsolen-Anwendung werden, aber zum Testen hab ich erst mal eine Form erstellt.

Delphi-Quellcode:
unit HwpDialer;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TFrmHwpDialer = class(TForm)
    Nummer: TEdit;
    Label1: TLabel;
    BtnDial: TButton;
    BtnClose: TButton;
    BtnReset: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCanResize(Sender: TObject; var NewWidth, NewHeight: Integer;
      var Resize: Boolean);
    procedure BtnDialClick(Sender: TObject);
    procedure BtnCloseClick(Sender: TObject);
    procedure BtnResetClick(Sender: TObject);
  private
    { Private-Deklarationen }
    FAppHandle, FEditHandle, FDialButtonHandle: THandle;
    FHandleList: TStrings;
  public
    { Public-Deklarationen }
    function WindowsDialerStart: boolean;
    function WindowsDialerInit: boolean;
  end;

var
  FrmHwpDialer: TFrmHwpDialer;

implementation

uses ShellAPI;

{$R *.dfm}

resourcestring
  rsWahlhilfeCaption = 'Wählhilfe';
  rsEditClassname = 'Edit';
  rsButtonDialClassName = 'Button';
  rsWahlhilfeExeName = 'Dialer.exe';

function EnumChilds(hwnd: HWND; lParam: LPARAM): BOOL; stdcall;
begin
  Result := True;
  FrmHwpDialer.FHandleList.Add(IntToStr(hwnd));
end;

procedure TFrmHwpDialer.FormCreate(Sender: TObject);
begin
  FHandleList := TStringList.Create;
  BtnDial.Enabled := WindowsDialerInit;
end;

procedure TFrmHwpDialer.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FHandleList.Free;
end;

procedure TFrmHwpDialer.FormCanResize(Sender: TObject; var NewWidth,
  NewHeight: Integer; var Resize: Boolean);
begin
  Resize := false;
end;

procedure TFrmHwpDialer.BtnCloseClick(Sender: TObject);
begin
  Close;
end;

procedure TFrmHwpDialer.BtnDialClick(Sender: TObject);
begin
  // Hat der User die Wählhilfe beendet...?
  if not WindowsDialerStart then exit;
  // Minimiertes Fenster normal anzeigen
  if IsIconic(FAppHandle) then ShowWindow(FAppHandle, SW_RESTORE);
  // In den Vordergrund
  SetForegroundWindow(FAppHandle);
  // Text an das Editfeld schicken
  SendMessage(FEditHandle,WM_Settext,0,Integer(PChar(Nummer.Text)));
end;

procedure TFrmHwpDialer.BtnResetClick(Sender: TObject);
begin
  BtnDial.Enabled := WindowsDialerInit;
end;

{ Public-Deklarationen }

function TFrmHwpDialer.WindowsDialerStart: boolean;
var
  SEI: TShellExecuteInfo;
begin
  FillChar(SEI, SizeOf(SEI), #0);
  SEI.cbSize := SizeOf(SEI);
  SEI.Wnd := Handle;
  SEI.fMask := SEE_MASK_NOCLOSEPROCESS;
  SEI.lpVerb := 'open';
  SEI.lpFile := PChar(rsWahlhilfeExeName);
  SEI.lpParameters := nil;
  SEI.lpDirectory := nil;
  SEI.nShow := SW_SHOW;
  try
    Result := ShellExecuteEx(@SEI);
  except
    on E:Exception do Showmessage(E.Message);
  end;
  CloseHandle(SEI.hProcess);
end;

function TFrmHwpDialer.WindowsDialerInit: boolean;
const
  iClassNameSize = 128;
var
  i: integer;
  H: THandle;
  ClassName: array[0..iClassNameSize] of char;
  WC: TWndClass;
begin
  if FAppHandle > 0 then
  if FindWindow(nil,PChar(rsWahlhilfeCaption)) = FAppHandle then Exit(True);
  Result := false;
  FEditHandle := 0;
  FDialButtonHandle := 0;
  FHandleList.Clear;
  FAppHandle := FindWindow(nil,PChar(rsWahlhilfeCaption));
  {-wenn die Wählhilfe nicht läuft....starten-}
  if FAppHandle = 0 then begin
    if not WindowsDialerStart then exit;
    FAppHandle := FindWindow(nil,PChar(rsWahlhilfeCaption));
  end;
  if FAppHandle > 0 then begin
    EnumChildWindows(FAppHandle, @EnumChilds, FAppHandle);
    for i := 0 to Pred(FHandleList.Count) do begin
      H := StrToInt(FHandleList[i]);
      GetClassName(H,ClassName,iClassNameSize);
      if GetClassInfo(H,@ClassName,WC) then begin
        {-Eingabefeld-}
        if SameText(rsEditClassName,string(WC.lpszClassName))
        then FEditHandle := H;
        {-Botton-}
        if SameText(rsButtonDialClassName,string(WC.lpszClassName)) then begin
          {-Button gefunden...aber welcher ??? }
          FDialButtonHandle := H;
        end;
      end;
      if (FDialButtonHandle > 0) and (FEditHandle > 0) then Exit(true);
    end;
  end;
end;

end.

zeras 18. Okt 2013 17:35

AW: Button in einer fremden Anwendung aktivieren
 
Ich wollte mal in einer HTML Seite Daten automatisch ausfüllen und dann den "Senden" Button ferngesteuert drücken. Da das nicht funkionierte, habe ich irgendwo nachgefragt und man sagte mir, dass dies aus Sicherheitsgründen nicht gehen würde.
Vielleicht ist das auch bei dir ein Sicherheitsproblem, denn man könnte ja ohne Zutun eines Users eine Telefonnummer wählen.
Ist aber nur so eine Idee.

musicman56 18. Okt 2013 18:04

AW: Button in einer fremden Anwendung aktivieren
 
Hallo Matthias,

die Sicherheitsbedenken kann ich verstehen. Aber, ich möchte den Button gar nicht drücken, sondern nur "enablen". Ich vermute, dass es sich um das "OnChange"-Ereignis handelt, das in der Wahlhilfe nicht abgefragt wird. Wahrscheinlich haben die MS-Programmierer nur Tastendruck im Edit-Feld ausgewertet, und somit bekommt das Programm gar nicht mit, dass sich der Inhalt des Eingabefeldes geändert hat. Dann müsste man dem Edit-Feld "einen Key unterjubeln" aber auch da weiß ich nicht, wie das geht.

EWeiss 18. Okt 2013 19:13

AW: Button in einer fremden Anwendung aktivieren
 
Delphi XE2 und dann PChar? .. hmmm na gut.

gruss

musicman56 18. Okt 2013 20:40

AW: Button in einer fremden Anwendung aktivieren
 
Zitat:

Zitat von EWeiss (Beitrag 1232477)
Delphi XE2 und dann PChar? .. hmmm na gut.

gruss

Vielen Dank für deinen hilfreichen Kommentar. Darf ich fragen, wo du ein Problem hast?

In der Delphi-Hilfe für XE2 steht:

System.PWideChar
type PWideChar = ^Char;

System.PChar
type PChar = ^Char;

Volker Z. 18. Okt 2013 20:49

AW: Button in einer fremden Anwendung aktivieren
 
Hallo,

hast Du es schon mal so versucht?
Delphi-Quellcode:
if not IsWindowEnabled (FDialButtonHandle) then
  EnableWindow (FDialButtonHandle, LongBool (True))
Gruß

musicman56 19. Okt 2013 08:13

AW: Button in einer fremden Anwendung aktivieren
 
Hallo,

Problem vorerst mit WM_CHAR gelöst. Bin gerade dabei alle OS durchzuchecken.

@Volker

Habe ich nicht in Erwägung gezogen, weil ich keinen sicheren Weg kenne herauszufinden, welcher von den 20 Buttons der richtige ist. Das wäre ja Bestandteil meiner Frage gewesen. Jetzt schicke ich dem Edit eine WM_CHAR und das enabled dann den Button. Vielleicht klappts ja mit allen OS.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:31 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz