function RunConsoleApp(
const FileName:
string;
const Parent: TWinControl): THandle;
type
PWndInfo = ^TWndInfo;
TWndInfo =
record
ProcessID: DWORD;
Handle: THandle;
end;
function EnumWindowsProc(hWnd: HWND; lParam: LPARAM): BOOL;
stdcall;
// Klappert alle Prozesse ab, bis derjenige der geöffneten Konsole gefunden wird
var
ProcessId: DWORD;
begin
GetWindowThreadProcessId(hWnd, ProcessId);
if ProcessId = PWndInfo(lParam)^.ProcessID
then // gefunden!
begin
PWndInfo(lParam)^.Handle:= hWnd;
// Handle zurückliefern
Result:= False;
// Enumeration abbrechen
end else
Result:= True;
// Enumeration fortfahren
end;
var
SI: TStartupInfo;
PI: TProcessInformation;
Console: TWndInfo;
cyCaption: Integer;
cxFrame, cyFrame: Integer;
ConsoleRect: TRect;
begin
Result:= 0;
// Struktur initialisieren
FillChar(SI, SizeOf(TStartupInfo), 0);
SI.cb := SizeOf(TStartupInfo);
SI.dwFlags := STARTF_USESHOWWINDOW;
// Konsole soll am Anfang unsichtbar sein
SI.wShowWindow:= SW_HIDE;
// und erst auf unserer Form angezeigt werden
// Konsolenprogramm starten
if CreateProcess(
nil, PChar(FileName),
nil,
nil, False, 0,
nil,
nil, SI, PI)
then
begin
CloseHandle(PI.hProcess);
// Die beiden Handles brauchen wir nicht
CloseHandle(PI.hThread);
// und können sie sofort wieder freigeben
Console.ProcessID:= PI.dwProcessId;
// OK, die ProcessId der Konsole kennen wir...
Console.Handle := 0;
// ... aber ihr Handle noch nicht!
while Console.Handle = 0
do // Also suchen wir es solange,
EnumWindows(@EnumWindowsProc, LPARAM(@Console));
// bis wir es gefunden haben
if Assigned(Parent)
then
begin
SetParent(Console.Handle, Parent.Handle);
// Konsole in unsere Anwendung platzieren
// Jetzt wirds ungemütlich... Damit man die Konsole nicht verschieben/resizen kann,
// muss ihr Rahmen ausgeblendet werden. Da dies über SetWindowLong nicht zu klappen
// scheint, müssen wir ihn halt verstecken :(
cyCaption:= GetSystemMetrics(SM_CYCAPTION);
cxFrame:= GetSystemMetrics(SM_CXFRAME);
cyFrame:= GetSystemMetrics(SM_CYFRAME);
// Konsolengrösse festlegen
// Achtung: Irgendetwas stimmt hier noch nicht so ganz!
SetWindowPos(Console.Handle, 0,
- cxFrame, - cyFrame - cyCaption,
Parent.ClientWidth - 2*cxFrame, Parent.ClientHeight - cyCaption - 2*cyFrame,
SWP_SHOWWINDOW);
// Hier wird die Konsole schliesslich angezeigt
// Da die Konsole nicht stetig resized werden kann, muss der Parent halt noch
// ein wenig angepasst werden...
GetWindowRect(Console.Handle, ConsoleRect);
with ConsoleRect
do
begin
Parent.ClientWidth:= Right - Left + 1 - 2*cxFrame;
Parent.ClientHeight:= Bottom - Top + 1 - cyCaption - 2*cyFrame;
end;
end;
// So, das wäre geschafft. Konsolenhandle zurückgeben und Feierabend.
Result:= Console.Handle;
end;
end;