Die Windows Console (CMD) aus einem anderen Programm zu steuern, ist eine tolle Sache. Das ermöglicht dem Programmierer, viele Funktionen und Ausführungen zu nutzen, ohne sie wirklich programmieren zu müssen.
Doch egal welche Programmiersprache man anwendet, es ist leider nicht möglich, alle Funktionen der Konsolensteuerung zu nutzen, als würde man die Originalkonsole von Windows nutzen.
Um dieses Problem zu umgehen, kann man einen Trick anwenden, und zwar die Originalwindows-Konsole in die Form einzubetten.
Danach kann man die Steuerung auf diese Konsole übertragen und hätte dann alle Funktionen zur Verfügung.
Der folgende Code zeigt, wie sich das machen lässt.
Es wird benötigt : 2xButton, 1xPanel
private
{ Private declarations }
mHWnd :HWND;
public
{ Public declarations }
Constructor Create( AOwner:TComponent );Override;
//
constructor TForm1.Create(AOwner: TComponent);
begin
Inherited;
Button1.Caption := 'Launch CMD';
Button2.Caption := 'Terminate CMD';
end;
Function InstanceToWnd( Const TgtPID:DWORD):HWND;
Var
ThisHWnd :HWND;
ThisPID :DWORD;
Begin
Result := 0;
ThisPID := 0;
// Find the first window
ThisHWnd := FindWindow( Nil, Nil);
While ThisHWnd <> 0 Do
Begin
//Check if the window isn't a child
If GetParent( ThisHWnd ) = 0 Then
Begin
//Get the window's thread & ProcessId
GetWindowThreadProcessId( ThisHWnd, Addr(ThisPID) );
If ThisPID = TgtPID Then
Begin
Result := ThisHWnd;
Break;
End;
End;
// 'retrieve the next window
ThisHWnd := GetWindow( ThisHWnd, GW_HWNDNEXT );
End;
End;{InstanceToWnd}
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
SendMessage(mHWnd, WM_CLOSE, 0, 0);
end;
Function ExecCmd( Const cmdline:String):HWND;
Var
PI :PROCESS_INFORMATION;
SI :STARTUPINFO;
Ret :LONGBOOL;
Begin;
Result := 0;
ZeroMemory( Addr(PI), SizeOf(PI) );
ZeroMemory( Addr(SI), SizeOf(SI) );
// Initialize the STARTUPINFO structure
SI.cb := SizeOf(SI);
// Start the shelled application:
Ret := CreateProcessA( Nil, PChar( cmdline ),
Nil, Nil, True,
NORMAL_PRIORITY_CLASS,
Nil, Nil,
SI, PI);
// --- let it start - this seems important
WaitForSingleObject( PI.hProcess, 500 );
If Ret Then
Begin
Result := InstanceToWnd( PI.dwProcessID );
CloseHandle( PI.hThread );
CloseHandle( PI.hProcess );
End;
End;{ExecCmd}
Konsole einbetten :
procedure TForm1.Button1Click(Sender: TObject);
begin
// Lock the window update - prevent flashing
// Does not work under XP
LockWindowUpdate( GetDesktopWindow );
// Execute notepad.Exe - Get its hWnd
mHWnd := ExecCmd( 'cmd.exe' );
If mHWnd = 0 Then
ShowMessage( 'Error starting the app' );
// Set the notepad's parent
If mHWnd <> 0 Then
Begin
Windows.SetParent( mHWnd, Panel1.Handle );
Windows.MoveWindow(mHWnd, 0, 0,
Panel1.ClientWidth,
Panel1.ClientHeight, True);
// Put the focus on notepad
Windows.SetFocus( mHWnd );
End;
// Unlock window update
LockWindowUpdate( 0 );
end;
Konsole entfernen :
procedure TForm1.Button2Click(Sender: TObject);
begin
SendMessage(mHWnd, WM_CLOSE, 0, 0);
end;
Keine Kommentare:
Kommentar veröffentlichen