Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Programm soll Tastendruck in einem anderen Programm ausführen (https://www.delphipraxis.net/204250-programm-soll-tastendruck-einem-anderen-programm-ausfuehren.html)

Asura 11. Mai 2020 11:32

Programm soll Tastendruck in einem anderen Programm ausführen
 
Guten Tag,

kurz zum Hintergrund: Ich saß heute an meinem Tablet und las ein E-Book. Dabei Markiere ich fleißig mit meinem Windows Pen Stellen. Leider kommt es vor, dass man sehr häufig Markierungen entfernen muss. Etwas nervig ist bei PDF-Programmen, dass das "Undo" so klein ist, da man ja eher die Tastenkürzel verwendet. Aus diesem Grund kam mir die Idee, dass ich einfach eine Konsolenanwendung erstelle, die den Tastenkürzel durch das Klicken der Taste auf dem Stift (Man kann ein Programm auswählen, was dann gestartet wird), ausführt. So habe ich mich vorhin direkt hingesetzt und eine Konsolenanwendung erstellt.

Leider hat er nicht die Tastenkürzel ausgegeben, so dachte ich mir, dass eventuell der Fokus auf das Programm gesetzt werden muss, bevor der Tastendruck simuliert wird. Jedoch auch dies hat nicht funktioniert. Es wird weder das Programm in den Vordergrund gerufen, der Fokus gesetzt oder der Tastendruck simuliert. Fehlermeldungen gibt es keine.

Mein Code sieht so aktuell aus:

Delphi-Quellcode:
program strg_z;

uses
  Winapi.Windows, System.SysUtils;

{$R *.res}

begin
  try

    SetForegroundWindow(Findwindow(nil, 'NitroPDF'));
    SetFocus(Findwindow(nil, 'NitroPDF'));

    keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), 0, 0);
    keybd_event(Ord('Z'), MapVirtualKey(Ord('Z'), 0), 0, 0);
    keybd_event(Ord('Z'), MapVirtualKey(Ord('Z'), 0), KEYEVENTF_KEYUP, 0);
    keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), KEYEVENTF_KEYUP, 0)
  except
    on E: Exception do
      Writeln(E.ClassName, 'Fehler: Fokus konnte nicht gesetzt werden.', E.Message);
  end;

  Exit;
end.
Was habe ich hierbei nicht beachtet?

himitsu 11. Mai 2020 13:14

AW: Programm soll Tastendruck in einem anderen Programm ausführen
 
keybd_event sended natürlich an das Fenster, was den Fous hat. (bzw. genauer was die Keyboardevents gefangen hat ... meistens ist Beides das Gleiche, aber muß nicht)

Etwas warten (Sleep), nach dem Fokus-ändern?
Kann ja sein es dauert ein bissl.


Und hat dein Programm überhaupt das Recht den Fokus umzusetzen?
Eventuell nicht, da es selber nicht den Fokus hat, weil es ja kein Fenster besitzt.
https://www.delphipraxis.net/203758-...ml#post1460199


PS: SendMessage/PostMessage der entsprechenden WM_KEY***,
welche man an ein "bestimmtes" Fenster schicken kann.

Asura 11. Mai 2020 17:16

AW: Programm soll Tastendruck in einem anderen Programm ausführen
 
Um sicher zu gehen bin ich nun für das erste in VLC umgestiegen.
Ich habe das mit Sleep ausprobiert, leider ohne Erfolg.

Ich bin also erstmal dann an die Prüfung gegangen, ob er überhaupt das Handle findet.

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var Handle: HWND;
begin

   Handle := FindWindow('NitroPDF', nil);

   if handle <> 0 then ShowWindow(handle, SW_SHOW) else ShowMessage('Nicht gefunden');

end;
Habe es auch mit der Funktion IsWindow probiert. Beides zeigt mir die Nachricht an, dass es nicht gefunden wurde.

Ich habe im Task-Manager aber nachgeschaut unter Details steht das PDF Programm aber unter "NitroPDF.exe".

Also setzen die ersten Probleme überhaupt daran an, dass er gar nicht das Handle findet und somit auch nicht in den Vordergrund setzen kann.

Gibt es hierfür Alternativen?

FriedrichAT 11. Mai 2020 17:35

AW: Programm soll Tastendruck in einem anderen Programm ausführen
 
Sicher...:!:
Syntax:
Delphi-Quellcode:
FindWindow(lpClassName: PChar; {a pointer to a null-terminated class name string}
           lpWindowName: PChar {a pointer to a null-terminated window name string}
          ): HWND; {returns a handle to a window}

Asura 11. Mai 2020 18:36

AW: Programm soll Tastendruck in einem anderen Programm ausführen
 
Ich habe nun die Funktion "FindWindowByTitle" genommen, die ich hier gefunden habe: https://www.swissdelphicenter.ch/en/showcode.php?id=327

Leider musste ich das nun über eine VCL erledigen. Doch nun funktioniert es, wie ich es mir vorgestellt habe.

Hier der Code dafür:

Delphi-Quellcode:
function FindWindowByTitle(WindowTitle: string): Hwnd;
var
  NextHandle: Hwnd;
  NextTitle: array[0..260] of char;
begin
  // Get the first window
  NextHandle := GetWindow(Application.Handle, GW_HWNDFIRST);
  while NextHandle > 0 do
  begin
    // retrieve its text
    GetWindowText(NextHandle, NextTitle, 255);
    if Pos(WindowTitle, StrPas(NextTitle)) <> 0 then
    begin
      Result := NextHandle;
      Exit;
    end
    else
      // Get the next window
      NextHandle := GetWindow(NextHandle, GW_HWNDNEXT);
  end;
  Result := 0;
end;



procedure TSTRG.FormCreate(Sender: TObject);
var Handle:HWND;
begin

     STRG.Hide;

     Handle := FindWindowByTitle('Nitro');

     if handle <> 0 then
      begin
         SendMessage(handle,WM_SYSCOMMAND, SC_MAXIMIZE, 0);
         SetForegroundWindow(handle);
      end
      else showmessage('Fehler im Finden des Handles');

    sleep(200);

    keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), 0, 0);
    keybd_event(Ord('Z'), MapVirtualKey(Ord('Z'), 0), 0, 0);
    keybd_event(Ord('Z'), MapVirtualKey(Ord('Z'), 0), KEYEVENTF_KEYUP, 0);
    keybd_event(VK_CONTROL, MapVirtualKey(VK_CONTROL, 0), KEYEVENTF_KEYUP, 0);

    Application.Terminate;

end;
Ich muss aber sagen, dass ich die Lösung lieber über ein Konsolenprogramm erstellt hätte. Aber gut, durch die Eigenschaft Hide bemerkt man es so gut wie gar nicht, dass das ausgeführt wird.

Für weitere Empfehlungen oder Verbesserungsvorschläge bin ich offen!


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:49 Uhr.

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