Autor Beitrag
daywalker0086
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 231


Delphi 2005 Architect
BeitragVerfasst: Mi 01.07.15 15:28 
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:
ausblenden volle Höhe 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:
ausblenden 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?
Einloggen, um Attachments anzusehen!
Nersgatt
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1561
Erhaltene Danke: 267


Delphi 10 Seattle Prof.
BeitragVerfasst: 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.

_________________
Gruß, Jens
Zuerst ignorieren sie dich, dann lachen sie über dich, dann bekämpfen sie dich und dann gewinnst du. (Mahatma Gandhi)
daywalker0086 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 231


Delphi 2005 Architect
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1561
Erhaltene Danke: 267


Delphi 10 Seattle Prof.
BeitragVerfasst: 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.

_________________
Gruß, Jens
Zuerst ignorieren sie dich, dann lachen sie über dich, dann bekämpfen sie dich und dann gewinnst du. (Mahatma Gandhi)
daywalker0086 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 231


Delphi 2005 Architect
BeitragVerfasst: 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
Einloggen, um Attachments anzusehen!
daywalker0086 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 231


Delphi 2005 Architect
BeitragVerfasst: Mi 01.07.15 23:28 
Gibts da Ideen?

Grüße Christian
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 18694
Erhaltene Danke: 1620

W10 x64 (Chrome, IE11)
Delphi 10.2 Ent, Oxygene, C# (VS 2015), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 02.07.15 05:23 
Dafür kannst du WM_GETTEXT benutzen:
msdn.microsoft.com/e...632627(v=vs.85).aspx
daywalker0086 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 231


Delphi 2005 Architect
BeitragVerfasst: 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
ausblenden 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
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2279
Erhaltene Danke: 419

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Mi 06.12.17 03:57 
Guten Morgen daywalker0086,

ausblenden 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:
var
  hWin, hMenue: THandle;
  menuCaption: string;
  menuId, menuCaptionLength: Integer;
begin
  menuCaption := '';
  hWin := FindWindow(nil'DOWNLOAD');
  if hWin <> 0 then
  begin
    //SetForeGroundWindow(hWin);
    hMenue := GetMenu(hWin);
    if hMenue <> 0 then
    begin
      hMenue := GetSubMenu(hMenue, 1); // 1 -> zweiter Hauptmenüpunkt
      if hMenue <> 0 then
      begin
        menuId := GetMenuItemId(hMenue, 0); // 0 -> erster Untermenüpunkt
        if menuId <> -1 then
        begin
          PostMessage(hWin, WM_COMMAND, menuId, 0);

          menuCaptionLength := GetMenuString(hMenue, menuId, nil00);
          SetLength(menuCaption, menuCaptionLength);
          GetMenuString(hMenue, menuId, @menuCaption[1], menuCaptionLength + 10);
        end;
      end;
    end;
  end;
  ShowMessage(menuCaption);
end;

Nachzulesen:
- GetMenu()
- GetSubMenu()
- GetMenuItemID()
- GetMenuString()
- WM_COMMAND

P.S.: Im Untermenü werden alle Elemente (in/aktive, de/selektierte, Trennlinien) gezählt.

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)
daywalker0086 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 231


Delphi 2005 Architect
BeitragVerfasst: 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. :?
ausblenden 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
Einloggen, um Attachments anzusehen!
Frühlingsrolle
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2279
Erhaltene Danke: 419

[Win NT] 5.1 x86 6.1 x64
[Delphi] 7 PE, 2006, 10.1 Starter, Lazarus - [C#] VS Exp 2012 - [Android API 15] VS Com 2015, Eclipse, AIDE - [C++] Builder 10.1
BeitragVerfasst: Mi 13.12.17 02:30 
Gern geschehen.
Probier's mal direkt mit dem Klassennamen (TComboBox):

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
var
  hWin: HWND;
begin
  hWin := FindWindow(nil'RS232');
  if hWin <> 0 then
  begin
    hWin := FindWindowEx(hWin, 0nil'&Bits per Second');
    if hWin <> 0 then
    begin
      hWin := FindWindowEx(hWin, 0'TComboBox'nil);
      if hWin <> 0 then
      begin
        ShowMessage('Combobox gefunden');
      end;
    end;
  end;
end;

P.S.: Bitte halte den Delphi-Styleguide ein. Das richtige Einrücken, sowie die KamelSchreibWeise für diverse Namensgebungen, ist das Mindeste. ;)

Um die Combobox-Auswahl zu ändern, benutz' die Nachricht CB_SETCURSEL.
Zum Auslesen des gesetzten ItemIndex, siehe CB_GETCURSEL.
Beides in Verbinung mit der SendMessage() Methode:

ausblenden Delphi-Quelltext
1:
SendMessage(Objekt-Handle, Nachricht, WParam-aus-der-Nachricht, LParam-aus-der-Nachricht): liefert LRESULT bzw. Integer					

Du solltest in der Lage sein, dies ohne fremden Code und nur mit Hilfe der verlinkten Doku zu lösen.

Gutes Gelingen. :beer:

_________________
„Politicians are put there to give you the idea that you have freedom of choice. You don’t. You have no choice. You have owners. They own you. They own everything." (George Denis Patrick Carlin)