Minimum code I used is:
procedure TForm1.FormCreate(Sender: TObject);
Var
windowstyle: Integer;
appthreadid: Cardinal;
cmdhandle: THandle;
Begin
cmdhandle := FindWindow('ConsoleWindowClass', 'Command Prompt');
// Hide title bars and borders of launched application
windowstyle := GetWindowLong(cmdhandle, GWL_STYLE);
windowstyle := windowstyle - WS_CAPTION - WS_BORDER - WS_OVERLAPPED - WS_THICKFRAME;
SetWindowLong(cmdhandle,GWL_STYLE,windowstyle);
// Attach the container applications input thread to the launched ones, so that we receive user input
appthreadid := GetWindowThreadProcessId(cmdhandle, nil);
AttachThreadInput(GetCurrentThreadId, appthreadid, True);
// Docking. Change the parent of the launched application
WinApi.Windows.SetParent(cmdhandle, Self.Handle);
SendMessage(Self.Handle, WM_UPDATEUISTATE, UIS_INITIALIZE, 0);
UpdateWindow(cmdhandle);
// Make the docked window fill all the client area of the container
SetWindowPos(cmdhandle, 0, 0, 0, Self.ClientWidth, Self.ClientHeight, SWP_NOZORDER);
// This prevents the parent control to redraw on the area of its child windows (the launched application)
SetWindowLong(Self.Handle, GWL_STYLE, GetWindowLong(Self.Handle, GWL_STYLE) Or WS_CLIPCHILDREN);
// SetForegroundWindow(WindowHandle);
// SetFocus(WindowHandle);
End;
This does not take care of resizing the docked window if the form resizes and you also have to keep an eye on if / when your docked application closes. Also it includes no error checking / handling.
The result is as expected: