Entwickler-Ecke

Windows API - Text einfügen in DOS Fenster (Eingabeaufforderung)


LonghornUser - Mi 10.09.08 19:20
Titel: Text einfügen in DOS Fenster (Eingabeaufforderung)
Hallo,

ich würde gerne über einen HotKey einen String in die MS DOS Eingabeaufforderung eingeben.

Hierzu habe ich bis jetzt immer Strg+V simuliert, aber das geht ja bekanntlich in einer DOS Box nicht.

Nun suche ich nach einer Möglichkeit, dies doch zu bewerkstelligen. Habt ihr da eine Idee ? Gibt es vielleicht doch eine Tastenkombi dafür ?

Ciao LHUser


Boldar - Mi 10.09.08 21:42

Erzeuge doch einfach die Console mit createprocess und gib die erforderlichen Parameter mit an!


LonghornUser - Mi 10.09.08 22:36

user profile iconBoldar hat folgendes geschrieben:
Erzeuge doch einfach die Console mit createprocess und gib die erforderlichen Parameter mit an!


Mhm, das hört sich erst mal schon nach einer Lösung an.

Aber ich möchte gerne dynamisch Texte einfügen können. Also zB. gewisse Pfade usw. Und manchmal auch mehreres in einem DOS Fenster.

Geht so etwas auch ?


delphi10 - Do 11.09.08 08:12

user profile iconLonghornUser hat folgendes geschrieben:

Aber ich möchte gerne dynamisch Texte einfügen können.

Sollen das immer wiederkehrende gleiche Texte nur in verschiedener Reihenfolge oder grundsätzliche immer andere Texte sein? Für den ersten Fall hätte ich da eine Lösung


baka0815 - Do 11.09.08 09:18

Wenn du das Handle des Fensters hast, kannst du versuchen eine WM_CHAR Nachricht an selbiges zu schicken. Das sollte funktionieren.


jaenicke - Do 11.09.08 10:40

http://maxxdelphisite.free.fr/doscmd.htm
Damit kannst du auch mit einem gestarteten Konsolenprogramm interagieren, wenn dieses Eingaben erwartet.


LonghornUser - Do 11.09.08 12:25

user profile icondelphi10 hat folgendes geschrieben:
user profile iconLonghornUser hat folgendes geschrieben:

Aber ich möchte gerne dynamisch Texte einfügen können.

Sollen das immer wiederkehrende gleiche Texte nur in verschiedener Reihenfolge oder grundsätzliche immer andere Texte sein? Für den ersten Fall hätte ich da eine Lösung

Also es soll so laufen, dass man in dem Programm sich unbegrenzt viele Strings etwa in einer Liste anlegen kann, die man dann mit einem Hot Key verknüpft und so schnell oft gebrauchte Strings einfügen kann. Meintest du das mit deiner ersten Variante ?

user profile iconbaka0815 hat folgendes geschrieben:
Wenn du das Handle des Fensters hast, kannst du versuchen eine WM_CHAR Nachricht an selbiges zu schicken. Das sollte funktionieren.

Das hört sich interessant an. Wo finde ich denn da Informationen, wie man mit WM_CHAR umgeht ?

user profile iconjaenicke hat folgendes geschrieben:
http://maxxdelphisite.free.fr/doscmd.htm
Damit kannst du auch mit einem gestarteten Konsolenprogramm interagieren, wenn dieses Eingaben erwartet.

Hab ich mir gerade geladen, mal schauen,ob ich da was finde.


LonghornUser - Do 11.09.08 12:37

@jaenicke:

Ich habe mir DosCommand einmal geladen und habe den Befehl doscommand1.SendLine('Text',False);

auf einen definierten Hot Key gelegt. Dann habe ich wie gewohnt über Ausführen->cmd die Eingabeaufforderung gestartet und dann F2 gedrückt, aber nichts funktionierte. Leider :( Muss man da noch irgendwas vorher machen, damit der Text eingefügt wird ?


baka0815 - Do 11.09.08 12:53

Das DOSCommand funktioniert nur bei definierten Kommandos. Du musst der Komponente den Befehl, den du ausführen möchtest, mitgeben.

Also z.B.

Delphi-Quelltext
1:
2:
3:
DOSCommand.CommandLine := 'C:\Windows\cmd.exe'// Befehl zuweisen
DOSCommand.Execute; // Befehl ausführen
DOSCommand.SendLine('Text', False); // Nachricht an den Befehl schicken

Hab's aber nicht getestet.

Was das Senden von WM_CHAR angeht, solltest du im Forum genug Infos finden, guck z.B. mal hier [http://www.delphi-forum.de/viewtopic.php?t=86225].


delphi10 - Do 11.09.08 13:22

user profile iconLonghornUser hat folgendes geschrieben:
Meintest du das mit deiner ersten Variante?


Ja. Funktioniert ohne Delphi oder anderes Programm. Schreib eine Batch, in der deine Texte mit ECHO ausgegeben werden:
Echo off
Echo Text1
echo Text2
usw.
Starte zwei DOS-Boxen. in der ersten startest du die Text-Batch, ist jetzt deine Textvorlage. In die zweite DOS-Box holst du dir die gewünschten Texte mit Mausselekt und rechter Maustaste rein. Ist zwar primitiv, aber IMO die einzige Möglichkeit unter DOS Crtl.C/Crtl.V nachzuahmen. Mit bzw. unter Delphi gehts natürlich eleganter aber davon stand in deinem Ausgangsposting nichts.


jaenicke - Do 11.09.08 13:48

user profile iconLonghornUser hat folgendes geschrieben:
@jaenicke:

Ich habe mir DosCommand einmal geladen und habe den Befehl doscommand1.SendLine('Text',False);

auf einen definierten Hot Key gelegt. Dann habe ich wie gewohnt über Ausführen->cmd die Eingabeaufforderung gestartet und dann F2 gedrückt, aber nichts funktionierte. Leider :( Muss man da noch irgendwas vorher machen, damit der Text eingefügt wird ?
Ja, wie user profile iconbaka0815 bereits erläutert hat:
Die Komponente ist dafür da, einen Befehl auszuführen und sowohl die Ausgabe abzufangen (und zu analysieren und ggf. selbst auszugeben) als auch dafür dann Eingaben zu senden.

Beispiel:
Du startest die Kommandozeile, dann sendest du den format Befehl, und wenn die Abfrage zur Bestätigung kommt, sendest du das j. So ist das gemeint.


LonghornUser - Do 11.09.08 13:54

@ baka0815: Dein Vorschlag mit dem DosCommand würde ja bedeuten, dass jedesmal ein neues Dos fenster gestartet werden müsste.
Ich stelle mir das aber eher so vor, dass ich eine einzige Dosbox habe und dann zB. folgendermaßen eintippe:
1.) Zeichenfolge "cd " von Hand eingeben
2.) Über einen HotKey, zB. F2, einen im Programm definierten Text einfügen

Das scheint mit DosCommand nicht zu gehen, oder doch ?

Mehr verspreche ich mir da irgendwie von dem WM_CHAR Event.Ich lese mich da jetzt mal ein und schaue, ob es mich weiterbringt.

@delphi10: Diese Variante ist leider nicht drin, da ich ja eben genau dieses "Von Hand Kopieren" umgehen möchte.


jaenicke - Do 11.09.08 13:56

user profile iconLonghornUser hat folgendes geschrieben:
@ baka0815: Dein Vorschlag mit dem DosCommand würde ja bedeuten, dass jedesmal ein neues Dos fenster gestartet werden müsste.
Ich stelle mir das aber eher so vor, dass ich eine einzige Dosbox habe und dann zB. folgendermaßen eintippe:
1.) Zeichenfolge "cd " von Hand eingeben
2.) Über einen HotKey, zB. F2, einen im Programm definierten Text einfügen

Das scheint mit DosCommand nicht zu gehen, oder doch ?
Doch, genau das macht die Komponente, die Ausgaben musst du ggf. selbst anzeigen, wenn du das willst. Du kannst mit der Komponente auch eine eigene Konsolenbox schreiben. (Sowas habe ich auch gemacht bereits.)

// EDIT:
Ich habe gerade ein kleines Programm gefunden, da habe ich nicht die Komponente verwendet sondern anderen Code, von dem ich leider nicht mehr weiß woher ich den hatte, das Projekt ist etwas älter.


LonghornUser - Do 11.09.08 15:03

@Jaenicke: Ich schaue mir dein Programm nachher mal an.

@ all:
Ich habe es jetzt mal mit WM_CHAR versucht und bin zu folgendem Code gekommen:

Delphi-Quelltext
1:
2:
3:
  hWordWindow := FindWindowByTitle('Unbenannt - Editor'); //So ist der Title von Notepad in Vista
  if hWordWindow <> 0 then
    SendMessage(hWordWindow,WM_CHAR,Ord('s'),0);


Aber leider passiert garnichts. Der Handle wird zwar gefunden, aber das SendMessage hat keinelei Auswirkung :(

Edit: @jeanicke:
Du hast ja ein komplettes DOS Fenster simuliert. Ich denke, das ist schon etwas zu viel. Ich möchte in bestehende DOS Fenster Text einsetzen.


LonghornUser - Fr 12.09.08 13:13

@jaenicke: Vielleicht könnte ich mich mit dieser Lösung doch anfreunden. Nur ein Problem gibt es: Deine DOS Box funktioniert nicht wie eine normale. Wenn ich eine Datei per Kommando öffne (zB. per cd Befehl zum Desktop navigiere und eine Textdatei öffne), kommt es zur Exception. Warum das und wie kann man es beheben ?

@all: Habt ihr keine Idee wegen des WM_CHAR Events ? :(


baka0815 - Fr 12.09.08 13:30

Ich vermute, dass du bei Notepad die WM_CHAR Nachricht nicht an das Notepad-Fenster, sondern an das Memo-Feld im Fenster schicken musst und das Notepad-Fenster den Event einfach verwirft.

edit:
Folgendes funktioniert bei mir bestens:

Delphi-Quelltext
1:
2:
3:
    hWordWindow := FindWindow(nil'C:\WINDOWS\system32\cmd.exe');
    if hWordWindow <> 0 then
      SendMessage(hWordWindow, WM_CHAR, Ord('s'), 0);


In der Kommandozeile steht dann "s" :)


LonghornUser - Fr 12.09.08 14:03

Mhm, also vielleicht liegt das an Vista. Aber bei mir geht das definitiv nicht.

Obwohl cmd.exe auch in diesem Verzeichnis liegt (C:\Windows\system32).

Er findet übrigens noch nicht einmal das Handle, was der folgende Code zeigt:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
var hWordWindow:hwnd;
begin
    hWordWindow := FindWindow(nil'C:\Windows\system32\cmd.exe');
    if hWordWindow <> 0 then begin   showmessage('');
      SendMessage(hWordWindow, WM_CHAR, Ord('s'), 0);
      end;


jaenicke - Fr 12.09.08 14:24

Die Kommandozeilenfenster in Vista beinhalten evtl. noch anderen Text, da steht vor "C:\WINDOWS\system32\cmd.exe" z.B. "Administrator", also schau mal nach wie genau die Fensterüberschrift ist. Wenn es das Fenster mit "C:\WINDOWS\system32\cmd.exe" nicht findet muss da was anderes stehen ;-).

Zur Exception: Zu der Zeit konnte ich noch nicht so gut Delphi glaube ich, der Code ist älter, ich werde mir den mal nochmal anschauen.


LonghornUser - Fr 12.09.08 14:36

user profile iconjaenicke hat folgendes geschrieben:
Die Kommandozeilenfenster in Vista beinhalten evtl. noch anderen Text, da steht vor "C:\WINDOWS\system32\cmd.exe" z.B. "Administrator", also schau mal nach wie genau die Fensterüberschrift ist. Wenn es das Fenster mit "C:\WINDOWS\system32\cmd.exe" nicht findet muss da was anderes stehen ;-).

Zur Exception: Zu der Zeit konnte ich noch nicht so gut Delphi glaube ich, der Code ist älter, ich werde mir den mal nochmal anschauen.


Ah, stimmt, jetzt geht es.
Aber deine Lösung mit der DOS Box wäre auch noch interessant zu wissen.


jaenicke - Fr 12.09.08 14:42

Habs mir angeschaut, den Fehler hab ich nach nen paar Sekunden gefunden:
Zeile 352 in SJDOSShell.pas muss statt

Delphi-Quelltext
1:
        else if Buffer[1] = #12 then                    
lauten

Delphi-Quelltext
1:
        else if (Length(Buffer) > 0and (Buffer[1] = #12then                    
;-)


LonghornUser - Fr 12.09.08 14:54

OK. Ich teste es nachher. Aber nochmal ne andere Frage:

Die Titelleiste vom DOS Fenster ist ja nicht immer gleich. Kann ich die Titelleiste nicht auch dynamisch bekommen ?

Also ein Handle vom aktuell aktiven Fenster bestimmen ? Geht das mit Delphi ?


Boldar - Fr 12.09.08 14:55

ich glaube

Delphi-Quelltext
1:
getactivewindow                    

ermittelt das oberste Fenster

EDIT: die Schweizer sagen dazu das hier [http://www.swissdelphicenter.ch/de/showcode.php?id=327]


LonghornUser - Fr 12.09.08 15:24

Mhm, aus dem schweizerischen Artikel kann ich aber nicht so richtig viel rauslesen. Ich kann zwar ein Handle bekommen, welches ein bestimmtes Keyword enthält, aber leider können ja auch mehrere CMD Fenster geöffnet sein, oder nicht ?

Die Frage ist, wie ich das bekomme, in dem sich der User gerade befindet ?
oder habe ich da was überlesen ?

Edit: Ich habe es mal mit ForceForegroundWindow (siehe hier: http://64.233.183.104/search?q=cache:PcNzir9QxnIJ:http://www.swissdelphicenter.ch/torry/showcode.php%3Fid%3D261+GetForegroundWindow+delphi&hl=de&ct=clnk&cd=3&gl=de&client=firefox-a) probiert, da GetActiveWindow laut Google nicht das richtige Ergebnis liefert. Aber geht irgendwie nicht.

Bin relativ ratlos :(


LonghornUser - Fr 12.09.08 15:46

Also:
Ich habe es scheinbar nun doch hingebogen ;) Mit GetForegroundWindow geht es:

Delphi-Quelltext
1:
SendMessage(GetForegroundWindow, WM_CHAR, Ord('s'), 0);                    


Nur weiß ich nicht, was der Unterschied zwischen GetForegroundWindow und GetActiveWindow ist !?


Martok - Fr 12.09.08 16:32

user profile iconLonghornUser hat folgendes geschrieben:
Nur weiß ich nicht, was der Unterschied zwischen GetForegroundWindow und GetActiveWindow ist !?

RTFM.

Zitat:
The GetActiveWindow function retrieves the window handle to the active window attached to the calling thread's message queue.


Zitat:
The GetForegroundWindow function returns a handle to the foreground window (the window with which the user is currently working).


LonghornUser - Fr 12.09.08 18:40

Ist ja gut, beruhige dich wieder.

Vielen vielen Dank an alle !!!