Entwickler-Ecke

Windows API - externes Programm steuern, Problem: Popup Fenster


daywalker0086 - Mi 01.07.15 15:28
Titel: externes Programm steuern, Problem: Popup Fenster
Hallo Leute,
ich möchte ein externes Programm steuern um eine cpu etwas einfacher zu programmieren. (Das Prorgramm wird aus meiner Software gestartet)

Soweit kein Problem.
Ich drücke den Programmierbutton mit folgenden Routinen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
function FindWindowEx2(hParent: HWND; ChildClassName: string; ChildNr: Word): HWND;
var
   i: Word;
   hChild: HWND;
begin
   hChild := 0;
   Result := 0;
   Dec(ChildNr);
   for i := 0 to ChildNr do
      begin
         hChild := FindWindowEx(hParent, hChild, PChar(ChildClassName), nil);
         //showmessage(inttostr(hchild));
         if hChild = 0 then
         Break;
         Result := hChild;
      end;
end;


procedure upp_prog();
var
   i:integer;
begin
     //testwnd:= $00080652;
   wndMain :=  FindWindow(nil,'FUJITSU FLASH MCU Programmer');
   if wndMain <> 0 then SetForeGroundWindow(wndMain);
   //for i:=0 to 100 do begin
   if wndMain <> 0 then wndChild := FindWindowEx2(wndMain,'Button'2);
   //sendmessage(wndchild,
   if wndChild <> 0 then  SendMessage(wndChild, BM_CLICK,0,0);
   //  end;

end;


procedure TForm1.Button1Click(Sender: TObject);
begin
//if ShellExecute(Handle, 'open', PChar('C:\Program Files (x86)\FUJITSU\FUJITSU FLASH MCU Programmer\FMC16LX\flash.exe'), nil, nil, SW_SHOW)> 32 then
upp_prog;
timer1.Enabled:= true;
//Pressbuttonxy(FindWindow(nil,'FUJITSU FLASH MCU Programmer'),266,40);
//ShellExecute(Handle, 'open', PChar('C:\Program Files (x86)\FUJITSU\FUJITSU FLASH MCU Programmer\FMC16LX\flash.exe'), nil, nil, SW_SHOW);
end;


Es wird das Fenster gesucht und der passende Button zum programmieren gedrückt.
Bis hierhin alles gut!

Dann erscheinen die folgenden Popups wie im Anhang zu sehen.
Dann dacht ich mir machst du einfach einen Timer der nach einer Sekunde nochmal das Fenster 'flash' sucht und den Button drückt:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
   wndMain :=  FindWindow(nil,'flash');
   //if wndMain <> 0 then SetForeGroundWindow(wndMain);
   //for i:=0 to 100 do begin
   if wndMain <> 0 then wndChild := FindWindowEx2(wndMain,'Button'1);
   //sendmessage(wndchild,
   if wndChild <> 0 then  SendMessage(wndChild, BM_CLICK,0,0);
   timer1.Enabled:= false;
end;

Aber sobald ich mienen Button klicke und das andere Programm aufgerufen wird und dort der Button gedrückt wird, bleibt meine Anwendung stehen und auch die Timer.enabled Anweisung wird nicht ausgeführt.
Erst wenn ich in der Fremdanwendung die Meldung mit OK bestätige läuft meine Anwendung weiter und der Timer wird gestartet. Natürlich ist dann kein 'flash' Fenster mehr da wo der OK Button gedrückt werden soll.

Kann mir da jemand helfen wie man es richtig macht?


Nersgatt - Mi 01.07.15 15:40

Verwende mal in upp_prog() PostMessage, statt SendMessage.

Denn SendMessage wartet bis die Meldung abgearbeitet ist und kehrt erst dann zurück. Während PostMessage die Message in die Warteschlage schreibt und sofort zurück kehrt.


daywalker0086 - Mi 01.07.15 15:50

Danke schön, funktioniert nun wie gewünscht.
gibt es noch andere Ideen zur Verzögerung des zweiten Befehls außer mit einem timer? Das Programm brauch eine kurze Zeit bis die Popups kommen.


Nersgatt - Mi 01.07.15 15:52

Du könntest natürlich einen Thread machen, der das Fenster sucht, schließt und sich dann beendet.
Da würde ich aber noch einen Timeout einbauen, für den Fall, dass das Fenster mal nicht kommt, oder es jemand anders schon schneller wieder geschlossen hat.


daywalker0086 - Mi 01.07.15 16:09

Danke auch dafür, das werd ich mir mal überlegen.
Einen hab ich aber noch:
Mit welchem Befehl kann ich mir die Caption eines Handles zurück geben lassen?
Ich würde gern auswerten was da drin steht. Bei einem Error würde ich dann reagieren.
Siehe dazu auch das Bild im Anhang.

grüße Chris


daywalker0086 - Mi 01.07.15 23:28

Gibts da Ideen?

Grüße Christian


jaenicke - Do 02.07.15 05:23

Dafür kannst du WM_GETTEXT benutzen:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms632627(v=vs.85).aspx


daywalker0086 - Di 05.12.17 08:54

Hallo nochmal nach langer Zeit,
ich bräuchte nochmal Hilfe bei der Steuerung eines externen Programms.
Und zwar geht es um die Steuerung eines Hauptmenüs...
Das klickt man ja an (Datei, Bearbeiten, Ansicht, etc.) und dann öffnet sich ein Drop Downfeld wo man dann einzelene Sachen auswählen kann.
Ich muss bei einem externen Programm dort einmal ein Untermenü anklicken damit ich dann in dem sich öffnenden Fenster weitere Einstellungen vornehmen kann.
Mit

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
  wndMain :=  FindWindow(nil,'DOWNLOAD');
  if wndMain <> 0 then
  begin
  showmessage('gefunden1');
    //wndchild:= GetDlgItem(wndMain, 32770);
    wndchild:=getmenu(wndmain);
    if wndchild <> 0 then
    GetMem(Buffer, 251);
    GetMenuString(wndchild, 1, Buffer, 250, MF_BYPOSITION);
    ShowMessage(StrPas(Buffer));
    FreeMem(Buffer);

kann ich das menü schon auslesen, aber wie drücke ich den Button von Menü mit dem Index 1 und dem sich normalerweise aufklappenden Untermenü mit index 0 ?
Wie muss das Postmessage Telegramm aufgebaut sein?
Wenn jemand weis wie esgeht und mir sagt wäre ich sehr dankbar.

Grüße Christian


Delete - Mi 06.12.17 03:57

- Nachträglich durch die Entwickler-Ecke gelöscht -


daywalker0086 - Di 12.12.17 12:49

Hallo Frühlingsrolle,
vielen Dank für den Code, das klappt einwandfrei.
Wenn bei der Windwosdoku mal ein Beispiel dabei wäre...

So das klappt jetzt sehr gut.
Im aufplopenden Fenster muss ich noch eine Combobox umstellen.
Ich hätte gedacht das ich das so hibekomme wie in meinem ersten Fenster, einfach an den Childitems lang hangeln aber irgendwie findet er das Combofeld nicht. :?

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
  hWin := FindWindow(nil'RS232');
  if hWin <> 0 then
  begin
  //gefunden
  showmessage('gefunden1');
  wndchild := FindWindowEX(hWin, 0nil,'&Bits per Second');
  if wndchild <> 0 then
  begin
    showmessage('gefunden2');
    wndchild2 := FindWindowEX(wndchild, 00,'9600');
    if wndchild2 <> 0 then
    begin
      showmessage('gefunden3');
    end;
  end;
  end;

das funktioniert bis gefunden 2 aber da Combofeld innrehalb der Gruppe findet er nichtmehr...
Mach ich da was falsch weil es eine Combobox ist?


Grüße Christian


Delete - Mi 13.12.17 02:30

- Nachträglich durch die Entwickler-Ecke gelöscht -