Autor |
Beitrag |
snoopyonline
      
Beiträge: 38
|
Verfasst: Mo 15.08.05 21:48
Ich habe das ganze Forum nach allen möglichen Vorkommen von Postmessage und Sendmessage durchsucht aber nirgendwo herausfinden können warum meine Versuche scheitern, bzw. wie mans eigentlich macht:
Ich versuche verzweifelt, beim Internet-Explorer-Download Fenster den Speichern-Button auszulösen.
Es klappt zwar, mit folgendem Code ein "Return/Enter" zu senden:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8:
| procedure TForm1.Timer1Timer(Sender: TObject); var hwindow: hwnd;
begin hwindow := FindWindow(nil,pchar('Dateidownload')); if hwindow <> 0 then try postMessage(hWindow, WM_KEYDOWN,VK_Return,0) except end; end; |
Das löst zwar den "Speichern"-Button aus - allerdings in ca 5% der Fälle gleich anschließend auch den "Abbrechen"-Knopf während des gestarteten Downloads...
Leider kann man die beiden unterschiedlichen Fenster vor und während des downloads nicht unterscheiden, da beide Fenster den gleichen Titel tragen.
Die Lösung wäre also, mit dem senden von "S" den Speichern-Knopf zu drücken, doch egal wie ichs probiere - nichts bewegt sich...
--> postMessage(hWindow, WM_KEYDOWN,VK_Return,0)
Ich habe statt VK-Return schon alles mögliche probiert:
83 als Tastencode für S
53 als Tastencode für S laut der MSDN-VirtualKey-Liste
ord('s')
und nichts klappt.
Was mache ich falsch?????
Moderiert von matze: Code- durch Delphi-Tags ersetzt.Moderiert von Christian S.: Topic aus CLX / Delphi Language (Object-Pascal) verschoben am Mi 17.08.2005 um 12:50
|
|
Logikmensch
      
Beiträge: 390
Win XP
Delphi 2007 Prof., XE2, XE5
|
Verfasst: Di 16.08.05 06:32
Titel: Taste auch wieder loslassen...
Hallo,
ich kenne Dein Problem - habe selber schon sowas ähnliches versucht.
Ist aber schon 'ne Weile her. Aber weißt Du, es genügt eben nicht, die Taste nur zu drücken, sie muss auch wieder losgelassen werden. Schicke noch eine entsprechende Botschaft hinterher, wahrscheinlich läuft's dann...
Liebe Grüße,
Claus.
|
|
Harry M.
      
Beiträge: 754
Win 2000, XP
D2005
|
Verfasst: Di 16.08.05 08:43
Naja ein Problem war das ja nicht hat ganze 2 Min gedauert
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| procedure PressKeyDown(ZEICHEN: Char; GROSS: Boolean); begin if GROSS then keybd_event(VK_SHIFT, MapVirtualKey(VK_SHIFT, 0), 0, 0); keybd_event(Ord(UpCase(ZEICHEN)), MapVirtualKey(Ord(UpCase(ZEICHEN)), 0), 0, 0); end; procedure PressKeyUp(ZEICHEN: Char; GROSS: Boolean); begin keybd_event(Ord(UpCase(ZEICHEN)), MapVirtualKey(Ord(UpCase(ZEICHEN)), 0), KEYEVENTF_KEYUP, 0); if GROSS then keybd_event(VK_SHIFT, MapVirtualKey(VK_SHIFT, 0), KEYEVENTF_KEYUP, 0); end; procedure TForm1.Timer1Timer(Sender: TObject); var hwindow: hwnd; begin hwindow := FindWindow(nil,pchar('Dateidownload')); if hwindow <> 0 then begin PressKeyDown(chr(13), FALSE); PressKeyUp(chr(13), FALSE); end; end; |
Edit: Die Sache mit dem "S" kann auch nicht gehen. Du musst nämlich Alt+S drücken 
_________________ Gruß Harry
Et spes me per dies sine te ducat et amor me ferat, si dolor spem tollit.
|
|
snoopyonline 
      
Beiträge: 38
|
Verfasst: Di 16.08.05 20:43
@Harry
Also ersteinmal danke für die Antwort... Allerdings war die Lösung des Problems dann doch nicht ganz so einfach.
Das Problem liegt einfach darin, dass die verwendete keybd_event Prozedur die Taste "wild in die Gegend" sendet. Genau das ist aber das was ich nicht gebrauchen kann und sicher genauso schnell hinbekommen hätte
Mit Postmessage kann man halt genau das gewünschte Fenster ansteuern, was unabdingbar ist, da bei mir das Download-Fenster nicht immer den Focus hat.
Und wieso muß ich ALT+S simulieren, wenn doch 'S' als realer Tastendruck normalerweise ausreicht? Aber wenn es so klappen könnte wärs ja gut - nur weiß ich leider noch weniger wie ich ALT+S mit dem Postmessage kombinieren kann.
@Logikmensch
Also ich habe sämtliche meiner im 1. Thread beschriebenen Varianten mit "Keydown" und anschließendem "Keyup" im Postmessage durchprobiert - immer mit dem gleichen unzureichenden Ergebnis
Zuletzt bearbeitet von snoopyonline am Di 16.08.05 20:46, insgesamt 1-mal bearbeitet
|
|
Harry M.
      
Beiträge: 754
Win 2000, XP
D2005
|
Verfasst: Di 16.08.05 20:46
Also das Beispiel wie ich es oben gepostet habe, hat bei mir gefuntz. Sonst hätte ich es nicht gepostet. Wenn ich heute abend noch Zeit finde poste ich noch wie es mit PostMessage geht. Bin nur grad busy.
_________________ Gruß Harry
Et spes me per dies sine te ducat et amor me ferat, si dolor spem tollit.
|
|
snoopyonline 
      
Beiträge: 38
|
Verfasst: Di 16.08.05 20:51
@Harry
Bitte glaub nicht einen Vorwurf aus meinem letzten Posting herauszuhören... Hab den augenzwinkernden Smiley halt nicht dick genug hinbekommen...
Und prinzipiell funktioniert dein Code ja auch - nur leider auch dann wenn man gerade im falschen Fenster arbeitet und dann entsprechend die "S" oder Enter-Taste ungefragt dazwischengeknallt bekommt...
Ich könnte mich ja auch mit meiner bisherigen 95% Trefferquote zufrieden geben - aber irgendwie glaube ich geht das hier im Forum allen so - man kann dort einfach nicht aufhören
|
|
Harry M.
      
Beiträge: 754
Win 2000, XP
D2005
|
Verfasst: Di 16.08.05 20:55
Warum machst Du es überhaupt so kompliziert und lädst die File nicht mit den Indys runter? Einfacher und komfortabler gehst nicht.
_________________ Gruß Harry
Et spes me per dies sine te ducat et amor me ferat, si dolor spem tollit.
|
|
snoopyonline 
      
Beiträge: 38
|
Verfasst: Di 16.08.05 21:19
@Harry:
Einfach runterladen - egal ob mit Indy, Downloadtofile oder Delphi-Downloadmanager-Komponenten scheitert daran, dass die Programmierer der betreffenden Webseite dies (anscheinend sehr effektiv) unterbunden haben. Man kann nur eine Pseudo-Webadresse mit dem Browser annavigieren, wodurch der Download dann gestartet und die tatsächliche Datei-URL erst "mitgeteilt" wird... Es funktioniert also irgendwie nur der Download per Browser-Downloadfenster. Und alle Versuche diesen abzufangen und die Url zubekommen sind noch mehr im Sande verlaufen....
P.S.(1): Selbst technisch ausgereifte, professionelle Downloadmanager beißen sich daran irgendwie die Zähne aus...
P.S.(2): Um irgendwelchen Fragen/Vorwürfen zuvorzukommen: ich bin ordentlich angemeldeter User der betreffenden Seite und versuche nichts illegales sondern bin einfach zu faul und zu ehrgeizig um ständig selbst zu klicken...
P.S.(3): Ok - mit dem Ehrgeiz ist das so ne Sache - wie man sieht schaff ichs ja doch nicht ganz alleine 
|
|
Harry M.
      
Beiträge: 754
Win 2000, XP
D2005
|
Verfasst: Mi 17.08.05 00:27
Ich bin zwar jetzt nicht sicher ob es in Deinem konkreten Fall funtz aber versuch das mal:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure TForm1.Timer1Timer(Sender: TObject); var hWindow: hwnd; begin hwindow := FindWindow(nil, PChar('Dateidownload')); if hWindow <> 0 then begin PostMessage(hWindow, WM_KEYDOWN, VK_RETURN, 0); PostMessage(hWindow, WM_KEYUP, VK_RETURN, 0);
hwindow := FindWindow(nil, PChar('Datei speichern unter')); if hWindow <> 0 then begin PostMessage(hWindow, WM_KEYDOWN, VK_RETURN, 0); PostMessage(hWindow, WM_KEYUP, VK_RETURN, 0); end; end; end; |
Problem gab es bei mir nur, wenn die Datei schon existiert.
_________________ Gruß Harry
Et spes me per dies sine te ducat et amor me ferat, si dolor spem tollit.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mi 17.08.05 06:45
Irgendwie ziemlich grausam, was ihr da macht. Irgendwelchen obskuren Tasten wild durch die Gegend schicken und auf gut Glück irgendwelche Returns an Dialoge schicken. Da kann man nur beten, dass da kein "Datei löschen"-Dialog versehentlich aufgegangen ist.
Wenn man einen Schaltfläche anklickt, dann sendet Windows an das Parent eine WM_COMMAND Nachricht mit dem Notificationcode (hier BN_CLICKED) und der ID des Kontrols. Die ID ist immer gleich, nicht zu verwechseln mit dem Handle, und dient dazu, dass der Programmierer die Kontrols besser unterscheiden kann, wenn er so clever ist und welche vergibt. Rausfinden kann man diese IDs entweder mit dem Spy++ vom VC oder WinSpy von Delphi oder mit dem Programm WindowInfo von mir. In der Fensterprozedur des Parents sieht das dann so aus:
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:
| function dlgfunc(hDlg: hWnd; uMsg: dword; wParam: wParam; lParam: lParam): bool; stdcall; begin result := true; case uMsg of WM_...: ; WM_...: ; WM_COMMAND: begin if hiword(wParam) = BN_CLICKED then begin case LoWord(wParam) of IDC_BTN_CLOSE: SendMessage(hDlg, WM_CLOSE, 0, 0); end; end; end else result := false; end; end; |
IDC_BTN_CLOSE ist nur eine benannte Konstante. Hat hier zum Beispiel den Wert 103 oder so. Bei uns hat sie einmal 4420 für die "Speichern"-Schaltfläche auf dem Download-Dialog und einmal 1 auf dem "Datei speichern unter"-Dialog.
Schicken wir die Nachricht BM_CLICK an die Schaltfläche lösen wir genau das aus:
Zitat: |
An application sends a BM_CLICK message to simulate the user clicking a button. [..] ...and the button's parent window to receive a BN_CLICKED notification message.
|
Dazu suchen wir uns erst das jeweilige Parent mit FindWindow und dann holen wir uns das Handle der Schaltfläche über die Kontrol ID mit der API Funktion GetDlgItem.
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: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69:
| procedure TForm1.Button1Click(Sender: TObject); var hDlg : THandle; hBtn : THandle; begin hDlg := FindWindow(nil, 'Dateidownload'); if hDlg <> 0 then begin hBtn := GetDlgItem(hDlg, 4420); if hBtn <> 0 then begin SendMessage(hBtn, BM_CLICK, 0, 0); SendMessage(hBtn, BM_CLICK, 0, 0); Sleep(2000); hDlg := FindWindow(nil, 'Datei speichern unter'); if hDlg <> 0 then begin hBtn := GetDlgItem(hDlg, 1); if hBtn <> 0 then begin SendMessage(hBtn, BM_CLICK, 0, 0); end; end; end; end; end;
procedure TForm1.Timer1Timer(Sender: TObject); var hDlg : THandle; hBtn : THandle; begin hDlg := FindWindow(nil, 'Dateidownload'); if hDlg <> 0 then begin hBtn := GetDlgItem(hDlg, 4420); if hBtn <> 0 then begin SendMessage(hBtn, BM_CLICK, 0, 0); SendMessage(hBtn, BM_CLICK, 0, 0); Sleep(2000); hDlg := FindWindow(nil, 'Datei speichern unter'); if hDlg <> 0 then begin hBtn := GetDlgItem(hDlg, 1); if hBtn <> 0 then begin SendMessage(hBtn, BM_CLICK, 0, 0); end; end; end; end; end; |
Einmal mit Schaltfläche und einmal mit Timer. Und das mit dem Timer geht auch, wenn das Programmfesnetr im Hintergrund ist bzw. das Downloadfenster, also eigentlich sollte es immer gehen.
@Harry M: Als Systemprogrammierer sollte man eigentlich solche grundlegenden Mechanismen kennen wie Windows funktioniert. 
|
|
Harry M.
      
Beiträge: 754
Win 2000, XP
D2005
|
Verfasst: Mi 17.08.05 06:51
_________________ Gruß Harry
Et spes me per dies sine te ducat et amor me ferat, si dolor spem tollit.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mi 17.08.05 06:55
|
|
Harry M.
      
Beiträge: 754
Win 2000, XP
D2005
|
Verfasst: Mi 17.08.05 06:59
Was den besseren UserMgr angeht. Das soll es gar nicht werden. Ist nur eines von vielen Features. Und warte ab... Ende diesen Jahres / Anfang Nächsten's 
_________________ Gruß Harry
Et spes me per dies sine te ducat et amor me ferat, si dolor spem tollit.
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mi 17.08.05 07:04
In sechs Monaten? Viel Glück.
|
|
Harry M.
      
Beiträge: 754
Win 2000, XP
D2005
|
Verfasst: Mi 17.08.05 07:05
Thx. Das werd ich brauchen 
_________________ Gruß Harry
Et spes me per dies sine te ducat et amor me ferat, si dolor spem tollit.
|
|
snoopyonline 
      
Beiträge: 38
|
Verfasst: Mi 17.08.05 20:30
@Luckie:
Funktioniert wunderbar und ist zudem anscheinend auch noch "sauberstes" Delphi - da muß ich wohl mal den ganzen Quellcode posten, damit mir den auch gleich noch jemand so perfekt überarbeitet
Na gut - Scherz beiseite: Das mit dem Knöpfendrücken über die Button-ID geht super. Allerdings würde mich dann am Rande doch interessieren, wie man die IDs der einzelnen Buttons auch bei anderen Fenstern herausbekommen kann. Gibts da irgendne funktion für?
Aber wenns zuviel Mühe machen würde ist es auch nicht ganz so wild - wer weiß ob man das jemals wieder braucht...
Ihr habt mir ja schon enorm weitergeholfen - THX an alle Beteiligten...
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Do 18.08.05 00:52
Habe ich dir doch geschrieben:
Zitat: |
Rausfinden kann man diese IDs entweder mit dem Spy++ vom VC oder WinSpy von Delphi oder mit dem Programm WindowInfo von mir.
|
WindowInfo findest du hier: www.luckie-online.de...per/Delphi/Programme
|
|
|