Entwickler-Ecke

Sonstiges (Delphi) - Auf anderes Programm zugreifen...


Nano-Ware - Di 02.02.10 18:36
Titel: Auf anderes Programm zugreifen...
Hi,

ich schreibe gerade ein Tester-Programm für "Robot Karol" (http://www.schule.bayern.de/Karol/download.htm hier gibts das Setup zum download) in diesem Programm kann man ein "Robotterabbild" Aufgaben erledigen lassen. Unter "Welt" kann man die größe der Welt in der sich der Roboter bewegt einstellen. Ich würde gerne die drei Angaben (Höhe, Breite & Länge) durch mein Programm ändern lassen. Ist das zu realisieren? Wenn ja wie^^

Vielen vielen Dank schonmal fürs reinschauen :wink:


NACHTRAG:

Leider ist es bei diesem Programmauch so, dass sich die dazugehörigen Dateitypen nicht per Doppelklick im Programm öffnen lassen. Bei dieser Software muss man umständlich auf "Datei -> Öffnen" klicken. Kann ich durch diesen Dialog evtl. dem Programm auch "sagen" dass er eine bestimmte Datei öffnen soll?


Moderiert von user profile iconNarses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Di 02.02.2010 um 18:15


Xion - Mi 03.02.10 00:54

Ich kann dir mal Anregung was von mir hier zeigen


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:
function FindSaveAsWin (H: THandle): Boolean; stdcall;
var hE,hB: THandle;
  S,CName: array [0..255of Char;
begin
  Result:=True;

  GetWindowText(H,S,255);
               
  GetClassName(h,CName,255);

  if CName= '#32770' then
    begin
      hE:=FindWindowEx(h, 0'ComboBoxEx32'nil);
      hE:=FindWindowEx(hE,0,'ComboBox',nil);
      hE:=FindWindowEx(hE,0,'Edit',nil); 
      SendMessage(hE,WM_CUT,0,Integer(PChar(Path)));
      SendMessage(hE,WM_SETTEXT,0,Integer(PChar(Path)));
      PostMessage(H,wm_KeyDown,130);
      PostMessage(hE,WM_PASTE,0,Integer(PChar(Path)));
    end;
end;

procedure TNynxWins.SetFolderTo(S: String);
begin
 Path:=S;
 EnumWindows(@FindSaveAsWin, 0);
 Path:='';
end;


Der Parameter von SetFolderTo ist hierbei ein Ordnerpfad, das ganze wechselt per Knopfdruck in alle geöffneten SaveDialogs zu dem gewählten Ordner. (Der Sinn dahinter ist, dass man dann z.B. auf Speichern geht, der Depp zeigt dir wieder "Eigene Dateien" an und du kannst dann mit einem Klick in mein Programm direkt die 25 Unterordner überspringen und bist gleich drin...)

Prinzipiell geht man so vor: EnumWindows geht alle Fenster durch und ruft jedesmal die übergebene function (FindSaveAsWin) auf. Sobald Result auf False gesetzt wird, bricht dieser Vorgang ab. Wenn es dann das passende Fenster ist (in diesem Fall mit dem Namen "C32770") hab ich in h das Handle des Fensters. Mit FindWindowEx kann man dann irgendwelche Elemente in dem Fenster ansprechen und Nachrichten schicken. Guck dir dazu mal den WinSpector an, damit du die Namen der einzelnen Objekte rausbekommst.

Irgendwie müsstest du damit auch in das von dir beschriebene Menü reinkommen, und wenns ist dass du an das Menü CursorTasten schickst und dann da durch manövrierst.


Nano-Ware - Mi 03.02.10 18:14

Thx erstmal und... von dem Code versteh ich nixx^^ währ nett wenn jemand den etwas erklären könnte^^


Xion - Fr 05.02.10 17:37

Hi,

naja, so bisschen hatte ichs ja schon erklärt.

Erstmal prinzipiell. Ist das Programm dafür ausgelegt wäre es sehr viel einfacher (vielleicht ist es das ja sogar). Man kann nämlich dem andren Programm Nachrichten (messages) schicken, wie im wahren Leben. So kannst du ihm z.B. sagen:
"Drück mal Enter"

Vom Prinzip her könntest du ihm so z.B. auch schicken:
"Mach mal Datei x auf"
wenn du weißt, wie die Message dafür lauten würde. Da aber vermutlich das Programm nicht darauf eingestellt ist, dass man es von außen bedient, gibts vermutlich diese Message garnicht. Du kannst also dann nur mit Messages arbeiten die das Programm versteht. Dazu gehören z.B. die Maus und Tastatureingaben.


Delphi-Quelltext
1:
PostMessage(H,wm_KeyDown,130)                    

Diese Zeile schickt dem Programm H die Nachricht: "KeyDown, Taste 13" (13 ist Enter). Der zweite Parameter ist leer (0), ein Tastendruck hat ja nur die Eigenschaft welche Taste.
H ist dabei das Handle des Fensters, d.h. sozusagen der Name.

z.B. könntest du jetzt ganz einfach an dich selbst schicken, dass Enter gedrückt wurde:

Delphi-Quelltext
1:
PostMessage(Application.Handle,wm_KeyDown,130)                    


Um jetzt rauszufinden, wie das Fenster heißt, das du ansprechen willst, müssen wir das erstmal suchen.

Das geht so:


Delphi-Quelltext
1:
2:
3:
4:
procedure GetHandle;
begin
 EnumWindows(@FindWindow, 0);
end;


EnumWindows ist dabei so ähnlich wie ne for-Schleife:

Delphi-Quelltext
1:
2:
for i:=0 to FENSTERZAHL do
   FindWindow(FENSTER[i].HANDLE);

d.h. es wird für jedes Fenster einmal die Funktion FindWindow aufgerufen. In der müssen wir jetzt checken, ob es denn das ist, welches wir suchen. Da würde ich vorschlagen wir gehen einfach über den Fenstertext.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
function FindWindow(H: THandle): Boolean; stdcall;
var 
  WName: array [0..255of Char;
begin
  Result:=True;

  GetWindowText(H,WName,255);

  if WName= 'Delphi-Forum.de - Antwort schreiben - Mozilla Firefox' then
    begin
      PostMessage(H,wm_KeyDown,130);
    end;
end;


Das hier würde z.B. an das Fenster vom Firefox einen "Enter" schicken. Der Rückgabewert sagt übrigens aus, ob die "Schleife" weiter durchlaufen werden soll, d.h. ob noch mehr Fenster geprüft werden sollen. Der Beispielcode hier würde an alle Fenster mit dem passenden Text ein Enter schicken.

Soweit zum Grundprinzip. Der Trick ist jetzt der, dass man z.B. einen Knopf in dem Fenster sucht und den dann anspricht. Dazu brauchst du halt ein entsprechendes Programm wie WinSpector, dass dir die Namen von dem Knopf angibt.


Nano-Ware - Sa 06.02.10 20:07

Okay jetzt hab ich es einigermaßen verstanden :wink: ich weiß dass die EXE karol.exe heißt (auch im Taskmanager) aber wie muss ich das dann machen???

Sry für des dumme gefrage^^ und thx


Xion - Sa 06.02.10 23:38

Also ich hab jetzt keine Lust das Programm für dich zu schreiben :D

Ich hab mir eben mal einen Screenshot von Robot Carol angeguckt.

Du müsstest demnach nach dem Fenster "Robot Karol" suchen (das, was oben in der Leiste von dem Fenster steht).

Dann hab ich gesehen, das MainMenu von RobotCarol hat short cuts. Du schickst einfach die Tastenkombo "Alt+D" und dann paar mal CursorDown und dann Enter, dann macht er dir schonmal das Datei öffnen Feld auf. Das solltest du analog meinem ersten Code ansprechen können. Weltgröße verändern ist genauso, "Alt+W" usw.

Es wird aber dann wohl auch optisch so sein, dass man sieht wie dein Programm sich da durch das Menü bewegt, aber funktionieren wirds wohl.


Nano-Ware - Do 11.02.10 16:33

Es kann daran liegen , dass ich den Code iwie nich verstehh ;)


Xion - Sa 13.02.10 19:12

http://www.delphi-library.de/viewtopic.php?t=97738

Guck vielleicht mal da, das soll ein Tutorial sein :D

Kapitel 3 ist das, was dich betrifft. Aber ruhig die andren vorher mal durchlesen

---Moderiert von user profile iconNarses: Beiträge zusammengefasst---

Also denn

probiers mal so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
var H: THandle;
begin
H:=FindWindow('','Robot Karol');
  if h= 0 then
    ShowMessage('Handle 0')
  else
    begin
      SendMessage( h, WM_KEYDOWN, 870x20000000 ); //ALT + W
      SendMessage( h, WM_KEYDOWN, 400 ); //CursorDown
      SendMessage( h, WM_KEYDOWN, 130 ); //Enter
    end;
end;


Das müsste dir das erste im Welt-Menü öffnen


Nano-Ware - Sa 13.02.10 19:20

Vielen Dank! Ich werds später versuchen


Nano-Ware - Do 11.03.10 22:33

Soo bin leider erst gestern dazu gekommen mir das etwas näher anzuschauen. Dazu hab ich noch 3 (xD) Fragen

1. Ich würde gern die Funktion SendMessage etwas näher beschrieben bekommen. Also verbessert mich bitte falls im Folgenden etwas falsch ist

- 1.Parameter: Das Handle des Fensters, zu dem der Befehl hinsoll 2.Parameter Wie soll der Befehl ausgeführt werden (KEYDOWN (muss man dann nich auch danach sowas wie KeyUP schreiben?))

der 3. Parameter müsste die zu drückende Taste sein (gibt es eine Tabelle in der steht, welche Taste welche Nummer ist?)

den 4 Parameter verstehe ich überhaupt nicht^^ bitte genau erklären xDD (Also schon mal Danke!

2.Frage:

Bei MS Office Word ist es ja z.B. so, dass sich die Form.Caption ändert wenn man ein neues Dokument öffnet. Wie kann man das dann mit FindWindow finden?


3.Frage

Bei dem Befehl FindWindow steht im ersten Parameter '' für was steht denn der 1. Parameter?

Ich bedanke mich schonmal selbst. Ich wiß ich könnte auch in der Hilfe (z.B.) nachlesen. Nur irgendwie versteh ich das Meiste leichter wenn ihr das erklärt :wink:


Nano-Ware - Sa 13.03.10 00:30

Kann mir keiner helfen?


Nano-Ware - Di 16.03.10 01:47

Sry für den push, aber die Fragen bestehen noch! Bitte antwortet ;)


Xion - Di 16.03.10 11:27

user profile iconNano-Ware hat folgendes geschrieben Zum zitierten Posting springen:

1. Ich würde gern die Funktion SendMessage etwas näher beschrieben bekommen.

Die delphi-Hilfe(F1) liefert da:
F1 hat folgendes geschrieben:
hWnd
[in] Handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows.
Msg
[in] Specifies the message to be sent.
wParam
[in] Specifies additional message-specific information.
lParam
[in] Specifies additional message-specific information.

Im Klartext:
Parameter1: Das Handle des Fensters, das man ansprechen will
Parameter2: Die Nachricht, die man schicken will
Parameter3: Ein Parameter, passend zum Befehl
Parameter4: Zweiter Parameter, passend zum Befehl

user profile iconNano-Ware hat folgendes geschrieben Zum zitierten Posting springen:

2.Parameter Wie soll der Befehl ausgeführt werden (KEYDOWN (muss man dann nich auch danach sowas wie KeyUP schreiben?))

Nö. Es wird in dem angesprochenen Programm einfach das Event ausgelöst, dass beim Knopfdruck ausgelöst werden würde. Der Knopf ist dann aber nicht "reingedrückt", außer das Programm würde sich das irgendwie merken.

user profile iconNano-Ware hat folgendes geschrieben Zum zitierten Posting springen:

der 3. Parameter müsste die zu drückende Taste sein (gibt es eine Tabelle in der steht, welche Taste welche Nummer ist?)

Jo, das ist soweit ich weiß die ASCII-Tabelle [http://www.tcp-ip-info.de/tcp_ip_und_internet/ascii.htm].
Das sind die gleichen Werte, die im OnKeyDown, OnKeyPress kommen.

user profile iconNano-Ware hat folgendes geschrieben Zum zitierten Posting springen:

den 4 Parameter verstehe ich überhaupt nicht^^ bitte genau erklären xDD

Tja, hmm. Im Falle von KEYDOWN ist der zweite Parameter glaube ich ein Wert, der angibt ob Ctrl, Alt oder Shift gedrückt ist...aber das weiß ich auch nicht genau, hab das nur gefunden, obs stimmt, keine Ahnung.

user profile iconNano-Ware hat folgendes geschrieben Zum zitierten Posting springen:

Bei MS Office Word ist es ja z.B. so, dass sich die Form.Caption ändert wenn man ein neues Dokument öffnet. Wie kann man das dann mit FindWindow finden?

*Kein MS Word zur Hand hat* Also bei Firefox steht z.B. am Ende im Titel immer "Mozilla Firefox". Jetzt musst du ALLE Fenster durchgehen (EnumWindows, gibts im Forum Hinweise), das gibt dir praktisch jedes Fensterhandle aus. Für jedes einfach

Delphi-Quelltext
1:
  GetWindowText(Handle,StringVar,255);                    

Und dann gucken ob da Firefox am Ende steht.

Dann hab ich hier z.B. mal alle Windows-Ordner gesucht, die offen sind. Da steht ja (unter XP) nur der Pfad im Titel. Da hab ich auch EnumWindows genommen, und dann

Delphi-Quelltext
1:
2:
3:
 GetClassName(h,CName,255);

  if CName= 'CabinetWClass' then

Den ClassName kriegste mit dem WinSpector raus.




user profile iconNano-Ware hat folgendes geschrieben Zum zitierten Posting springen:

Bei dem Befehl FindWindow steht im ersten Parameter '' für was steht denn der 1. Parameter?



Delphi Hilfe (F1) hat folgendes geschrieben:

lpClassName
[in] Pointer to a null-terminated string that specifies the class name or a class atom created by a previous call to the RegisterClass or RegisterClassEx function. The atom must be in the low-order word of lpClassName; the high-order word must be zero.
If lpClassName points to a string, it specifies the window class name. The class name can be any name registered with RegisterClass or RegisterClassEx, or any of the predefined control-class names.
If lpClassName is NULL, it finds any window whose title matches the lpWindowName parameter.

lpWindowName
[in] Pointer to a null-terminated string that specifies the window name (the window's title). If this parameter is NULL, all window names match.

Wird auch in dem Tutorial von mir erklärt :) Der erste Parameter ist die Klasse (z.B. TForm1) und der zweite ist der Fenster-Titel. Man muss aber immer nu eins angeben


Nano-Ware - Do 18.03.10 00:58

kk und was bedeutet das ? 0x20000000?


platzwart - Do 18.03.10 01:47

Der letzte Parameter kann unterschiedliche Bedeutungen haben, abhängig von dem zweiten Parameter. In dem konkreten Beispiel steht das "0x20000000" für die Tastenkombination "ALT + W". Wobei "0x20000000" eine Hexadezimalzahl ist (wird durch 0x angezeigt).


Xion - Do 18.03.10 08:53

user profile iconplatzwart hat folgendes geschrieben Zum zitierten Posting springen:
In dem konkreten Beispiel steht das "0x20000000" für die Tastenkombination "ALT + W".

Ich hätte jetzt gesagt das steht nur für ALT, weil das W steht ja im ersten Parameter :gruebel: Gibts irgendwo eine Liste, womit man den 2.Parameter so füllen kann?


Nano-Ware - So 21.03.10 00:34

Ja das würd mich auch interessieren xD


platzwart - So 21.03.10 01:33

user profile iconXion hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconplatzwart hat folgendes geschrieben Zum zitierten Posting springen:
In dem konkreten Beispiel steht das "0x20000000" für die Tastenkombination "ALT + W".

Ich hätte jetzt gesagt das steht nur für ALT, weil das W steht ja im ersten Parameter :gruebel: Gibts irgendwo eine Liste, womit man den 2.Parameter so füllen kann?



Ach verdammt, hast recht...


Nano-Ware - Mo 22.03.10 01:17

Ja soweit waren wir auch schon xD also ich will das ja auch später anwenden können. Wie sieht das dann bei STRG+W odder STRG+ALT+W aus?


Nano-Ware - So 28.03.10 19:16

Das Problem besteht noch <.<


uko - Mo 29.03.10 06:18

Wenn Du was zu Messages und die Bedeutung der Parameter wissen willst, dann ist das MSDN immer noch die beste Quelle: Suche im MSDN WM_KEYDOWN

Grüße,
Uli