Recent

Author Topic: You can embed Windows Console ~ inside your application.  (Read 542 times)

Ozz_Nixon

  • Full Member
  • ***
  • Posts: 131
  • ~ email: nixon.ozz@aol.com or ozznixon@gmail.com
    • http://www.modernpascal.com/
You can embed Windows Console ~ inside your application.
« on: June 17, 2026, 03:39:13 am »
This was asked for by someone else and myself... could it be done. Unfortunately, it was received with a bunch of quick "No!" answers. Wrong!

With a few tweaks to Console's Messages - poof, my placeholder TPanel can envelop CMD.EXE and ultimately any Win32 console application.

PS. Full disclosure ~ I did this using Delphi 7. I am sure someone who can make my Component compile and load in Lazarus ~ can demonstrate this working in an FPC based GUI. [me and Lazarus don't seem to get along well].
« Last Edit: June 17, 2026, 03:46:09 am by Ozz_Nixon »
---
Want to kick the tires to a Free Pascal like script engine? http://www.ModernPascal.com/

Ozz_Nixon

  • Full Member
  • ***
  • Posts: 131
  • ~ email: nixon.ozz@aol.com or ozznixon@gmail.com
    • http://www.modernpascal.com/
Re: You can embed Windows Console ~ inside your application.
« Reply #1 on: June 17, 2026, 11:14:02 pm »
Can someone help get this to work with FPC?

Code: Pascal  [Select][+][-]
  1.  
  2. {===============================================================================
  3.   TConsolePanel - Embed Console Window Inside Delphi TForm
  4.   ===============================================================================
  5.  
  6.   Allows embedding a Windows console window as a child of a TForm at runtime.
  7.   Similar to IDE integration in Linux environments.
  8.  
  9.   Features:
  10.   - Embed console as child window of TForm
  11.   - Automatic window sizing and positioning
  12.   - Resize with parent form
  13.   - Full console input/output redirection
  14.   - Process management
  15.   - Optional auto-launch on Create
  16.  
  17.   Usage:
  18.     ConsolePanel := TConsolePanel.Create(Self);
  19.     ConsolePanel.Parent := Form1;
  20.     ConsolePanel.Align := alClient;
  21.     ConsolePanel.LaunchConsole;
  22.  
  23. ===============================================================================}
  24.  
  25.  
  26. unit ConsolePanel;
  27.  
  28.  
  29. interface
  30.  
  31.  
  32. uses
  33.   Windows, Classes, Controls, Forms, Messages, SysUtils;
  34.  
  35.  
  36. type
  37.   TConsolePanel = class(TCustomControl)
  38.   private
  39.     FConsoleHandle: HWND;
  40.     FProcessHandle: THandle;
  41.     FProcessID: DWORD;
  42.     FAutoLaunch: Boolean;
  43.     FConsoleVisible: Boolean;
  44.     FShowFrame: Boolean;
  45.     FOnConsoleCreated: TNotifyEvent;
  46.     FOnConsoleClosed: TNotifyEvent;
  47.     FConsolePath: String;
  48.     FConsoleTitle: String;
  49.     FInitialWidth: Integer;
  50.     FInitialHeight: Integer;
  51.     FAlign: TAlign;
  52.    
  53.     procedure SetShowFrame(Value: Boolean);
  54.    
  55.     procedure WMSize(var Message: TWMSize); message WM_SIZE;
  56.     procedure WMShowWindow(var Message: TWMShowWindow); message WM_SHOWWINDOW;
  57.     procedure SetParent(AParent: TWinControl); override;
  58.     function GetIsConsoleOpen: Boolean;
  59.     procedure ResizeConsoleWindow;
  60.     procedure UpdateConsoleWindowSize;
  61.     procedure SetAlign(Value: TAlign);
  62.    
  63.   protected
  64.     procedure CreateWnd; override;
  65.     procedure DestroyWnd; override;
  66.     procedure Resize; override;
  67.     procedure Paint; override;
  68.    
  69.   public
  70.     constructor Create(AOwner: TComponent); override;
  71.     destructor Destroy; override;
  72.    
  73.     { Launch or kill console }
  74.     function LaunchConsole(const AConsolePath: String = ''): Boolean;
  75.     procedure CloseConsole;
  76.     procedure KillConsole;
  77.     function IsConsoleRunning: Boolean;
  78.    
  79.     { Window operations }
  80.     procedure FocusConsole;
  81.     procedure ShowConsole;
  82.     procedure HideConsole;
  83.     procedure SetConsoleTitle(const Title: String);
  84.    
  85.     { Get handles }
  86.     function GetConsoleHandle: HWND;
  87.     function GetProcessHandle: THandle;
  88.     function GetProcessID: DWORD;
  89.    
  90.     property IsConsoleOpen: Boolean read GetIsConsoleOpen;
  91.     property OnConsoleCreated: TNotifyEvent read FOnConsoleCreated write FOnConsoleCreated;
  92.     property OnConsoleClosed: TNotifyEvent read FOnConsoleClosed write FOnConsoleClosed;
  93.     property ConsoleTitle: String read FConsoleTitle write FConsoleTitle;
  94.     property AutoLaunch: Boolean read FAutoLaunch write FAutoLaunch;
  95.     property Align: TAlign read FAlign write SetAlign default alNone;
  96.     property ShowFrame: Boolean read FShowFrame write SetShowFrame default True;
  97.    
  98.   end;
  99.  
  100.  
  101. {===============================================================================
  102.   TConsoleManager - Higher-level console management
  103. ===============================================================================}
  104.  
  105.  
  106. type
  107.   TConsoleManager = class(TObject)
  108.   private
  109.     FConsoleWindow: HWND;
  110.     FConsolePanel: TConsolePanel;
  111.     FInputHandle: THandle;
  112.     FOutputHandle: THandle;
  113.     FErrorHandle: THandle;
  114.     FBufferSize: Integer;
  115.     FIsRedirected: Boolean;
  116.    
  117.   public
  118.     constructor Create(AConsolePanel: TConsolePanel);
  119.     destructor Destroy; override;
  120.    
  121.     { Input/Output redirection }
  122.     function RedirectInput: Boolean;
  123.     function RedirectOutput: Boolean;
  124.     procedure RestoreHandles;
  125.    
  126.     { Console interaction }
  127.     procedure Clear;
  128.     procedure SetTextColor(Color: Word);
  129.     procedure SetBufferSize(Width, Height: Word);
  130.     function GetBufferSize: TSize;
  131.    
  132.     { Console info }
  133.     function GetConsoleTitle: String;
  134.     procedure SetConsoleTitle(const Title: String);
  135.    
  136.     property ConsoleWindow: HWND read FConsoleWindow;
  137.     property IsRedirected: Boolean read FIsRedirected;
  138.     property BufferSize: Integer read FBufferSize write FBufferSize;
  139.   end;
  140.  
  141.  
  142. procedure Register;
  143.  
  144.  
  145. implementation
  146.  
  147.  
  148. {===============================================================================
  149.   TConsolePanel Implementation
  150. ===============================================================================}
  151.  
  152.  
  153. constructor TConsolePanel.Create(AOwner: TComponent);
  154. begin
  155.   inherited Create(AOwner);
  156.  
  157.   ControlStyle := ControlStyle + [csOpaque];
  158.   Width := 400;
  159.   Height := 300;
  160.  
  161.   FConsoleHandle := 0;
  162.   FProcessHandle := 0;
  163.   FProcessID := 0;
  164.   FAutoLaunch := False;
  165.   FConsoleVisible := False;
  166.   FShowFrame := True;
  167.   FConsolePath := '';
  168.   FConsoleTitle := 'Console';
  169.   FInitialWidth := Width;
  170.   FInitialHeight := Height;
  171.   FAlign := alNone;
  172.  
  173.   { Auto-launch if requested }
  174.   if FAutoLaunch then
  175.     LaunchConsole;
  176. end;
  177.  
  178.  
  179. destructor TConsolePanel.Destroy;
  180. begin
  181.   CloseConsole;
  182.   inherited Destroy;
  183. end;
  184.  
  185.  
  186. procedure TConsolePanel.CreateWnd;
  187. begin
  188.   inherited CreateWnd;
  189. end;
  190.  
  191.  
  192. procedure TConsolePanel.DestroyWnd;
  193. begin
  194.   CloseConsole;
  195.   inherited DestroyWnd;
  196. end;
  197.  
  198.  
  199. procedure TConsolePanel.SetParent(AParent: TWinControl);
  200. begin
  201.   inherited SetParent(AParent);
  202.  
  203.   if AParent <> nil then
  204.   begin
  205.     if HandleAllocated and (FConsoleHandle <> 0) then
  206.     begin
  207.       UpdateConsoleWindowSize;
  208.     end;
  209.   end;
  210. end;
  211.  
  212.  
  213. procedure TConsolePanel.WMSize(var Message: TWMSize);
  214. begin
  215.   inherited;
  216.   ResizeConsoleWindow;
  217. end;
  218.  
  219.  
  220. procedure TConsolePanel.WMShowWindow(var Message: TWMShowWindow);
  221. begin
  222.   inherited;
  223.   if FConsoleHandle <> 0 then
  224.   begin
  225.     if Message.Show <> 0 then
  226.       ShowWindow(FConsoleHandle, SW_SHOW)
  227.     else
  228.       ShowWindow(FConsoleHandle, SW_HIDE);
  229.   end;
  230. end;
  231.  
  232.  
  233. procedure TConsolePanel.Paint;
  234. begin
  235.   inherited Paint;
  236.  
  237.   { Draw placeholder if no console }
  238.   if FConsoleHandle = 0 then
  239.   begin
  240.     Canvas.Brush.Color := clBlack;
  241.     Canvas.FillRect(ClientRect);
  242.     Canvas.Font.Color := clLime;
  243.     Canvas.TextOut(10, 10, 'Console not launched. Click or call LaunchConsole().');
  244.   end;
  245. end;
  246.  
  247.  
  248. procedure TConsolePanel.Resize;
  249. begin
  250.   inherited Resize;
  251.   ResizeConsoleWindow;
  252. end;
  253.  
  254.  
  255. procedure TConsolePanel.ResizeConsoleWindow;
  256. begin
  257.   if HandleAllocated and (FConsoleHandle <> 0) then
  258.   begin
  259.     UpdateConsoleWindowSize;
  260.   end;
  261. end;
  262.  
  263.  
  264. procedure TConsolePanel.UpdateConsoleWindowSize;
  265. var
  266.   ParentHandle: HWND;
  267.   R: TRect;
  268. begin
  269.   if FConsoleHandle = 0 then Exit;
  270.  
  271.   ParentHandle := Handle;
  272.   if ParentHandle = 0 then Exit;
  273.  
  274.   { Get client rect }
  275.   Windows.GetClientRect(ParentHandle, R);
  276.  
  277.   { Resize console window to fit panel (0,0 since we're using SetParent) }
  278.   SetWindowPos(
  279.     FConsoleHandle,
  280.     0,
  281.     0, 0,
  282.     R.Right - R.Left, R.Bottom - R.Top,
  283.     SWP_NOZORDER or SWP_SHOWWINDOW
  284.   );
  285. end;
  286.  
  287.  
  288. procedure TConsolePanel.SetAlign(Value: TAlign);
  289. begin
  290.   if FAlign <> Value then
  291.   begin
  292.     FAlign := Value;
  293.    
  294.     { Apply standard Delphi alignment behavior }
  295.     case FAlign of
  296.       alNone:
  297.         begin
  298.           { Keep current position and size }
  299.         end;
  300.       alTop:
  301.         begin
  302.           Align := alTop;
  303.           Height := 150; { Default height }
  304.         end;
  305.       alBottom:
  306.         begin
  307.           Align := alBottom;
  308.           Height := 150; { Default height }
  309.         end;
  310.       alLeft:
  311.         begin
  312.           Align := alLeft;
  313.           Width := 200; { Default width }
  314.         end;
  315.       alRight:
  316.         begin
  317.           Align := alRight;
  318.           Width := 200; { Default width }
  319.         end;
  320.       alClient:
  321.         begin
  322.           Align := alClient;
  323.         end;
  324.       alCustom:
  325.         begin
  326.           { Custom positioning - user controls position/size }
  327.         end;
  328.     end;
  329.    
  330.     if HandleAllocated then
  331.       ResizeConsoleWindow;
  332.   end;
  333. end;
  334.  
  335.  
  336. procedure TConsolePanel.SetShowFrame(Value: Boolean);
  337. var
  338.   Style: Longint;
  339. begin
  340.   if FShowFrame <> Value then
  341.   begin
  342.     FShowFrame := Value;
  343.    
  344.     if FConsoleHandle <> 0 then
  345.     begin
  346.       if FShowFrame then
  347.       begin
  348.         { Show the window frame/border }
  349.         Style := GetWindowLong(FConsoleHandle, GWL_STYLE);
  350.         SetWindowLong(FConsoleHandle, GWL_STYLE, Style or WS_CAPTION or WS_BORDER);
  351.         SetWindowPos(FConsoleHandle, 0, 0, 0, 0, 0,
  352.           SWP_NOZORDER or SWP_NOSIZE or SWP_NOMOVE or SWP_FRAMECHANGED);
  353.       end
  354.       else
  355.       begin
  356.         { Hide the window frame/border, keep only the client area }
  357.         Style := GetWindowLong(FConsoleHandle, GWL_STYLE);
  358.         SetWindowLong(FConsoleHandle, GWL_STYLE, Style and not (WS_CAPTION or WS_BORDER));
  359.         SetWindowPos(FConsoleHandle, 0, 0, 0, 0, 0,
  360.           SWP_NOZORDER or SWP_NOSIZE or SWP_NOMOVE or SWP_FRAMECHANGED);
  361.       end;
  362.     end;
  363.   end;
  364.  
  365.  
  366. function TConsolePanel.LaunchConsole(const AConsolePath: String = ''): Boolean;
  367. var
  368.   StartupInfo: TStartupInfo;
  369.   ProcessInfo: TProcessInformation;
  370.   ConsolePath: String;
  371.   Attempt: Integer;
  372. begin
  373.   Result := False;
  374.  
  375.   { Close existing console first }
  376.   if IsConsoleRunning then
  377.     CloseConsole;
  378.  
  379.   { Determine console path }
  380.   if AConsolePath <> '' then
  381.     ConsolePath := AConsolePath
  382.   else if FConsolePath <> '' then
  383.     ConsolePath := FConsolePath
  384.   else
  385.     ConsolePath := 'cmd.exe';
  386.  
  387.   { Check if file exists }
  388.   if not FileExists(ConsolePath) then
  389.   begin
  390.     ShowMessage('Console application not found: ' + ConsolePath);
  391.     Exit;
  392.   end;
  393.  
  394.   { Initialize startup info }
  395.   ZeroMemory(@StartupInfo, SizeOf(TStartupInfo));
  396.   StartupInfo.cb := SizeOf(TStartupInfo);
  397.   StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
  398.   StartupInfo.wShowWindow := SW_SHOW;
  399.  
  400.   { Create the process }
  401.   if not CreateProcess(
  402.     nil,
  403.     PChar(ConsolePath),
  404.     nil,
  405.     nil,
  406.     False,
  407.     CREATE_NEW_CONSOLE,
  408.     nil,
  409.     nil,
  410.     StartupInfo,
  411.     ProcessInfo) then
  412.   begin
  413.     ShowMessage('Failed to create console process');
  414.     Exit;
  415.   end;
  416.  
  417.   FProcessHandle := ProcessInfo.hProcess;
  418.   FProcessID := ProcessInfo.dwProcessId;
  419.   CloseHandle(ProcessInfo.hThread);
  420.  
  421.   { Try to find the console window }
  422.   for Attempt := 1 to 50 do
  423.   begin
  424.     Sleep(50);
  425.     FConsoleHandle := FindWindowEx(0, 0, 'ConsoleWindowClass', nil);
  426.    
  427.     if FConsoleHandle <> 0 then
  428.       Break;
  429.   end;
  430.  
  431.   if FConsoleHandle <> 0 then
  432.   begin
  433.     { Make it a child of our panel }
  434.     SetWindowLong(FConsoleHandle, GWL_STYLE, GetWindowLong(FConsoleHandle, GWL_STYLE) and not WS_POPUP);
  435.     Windows.SetParent(FConsoleHandle, Handle);
  436.    
  437.     { Apply ShowFrame setting }
  438.     if not FShowFrame then
  439.     begin
  440.       { Hide the frame }
  441.       var Style: Longint := GetWindowLong(FConsoleHandle, GWL_STYLE);
  442.       SetWindowLong(FConsoleHandle, GWL_STYLE, Style and not (WS_CAPTION or WS_BORDER));
  443.       SetWindowPos(FConsoleHandle, 0, 0, 0, 0, 0,
  444.         SWP_NOZORDER or SWP_NOSIZE or SWP_NOMOVE or SWP_FRAMECHANGED);
  445.     end;
  446.    
  447.     { Resize and position }
  448.     UpdateConsoleWindowSize;
  449.    
  450.     FConsoleVisible := True;
  451.     SetConsoleTitle(FConsoleTitle);
  452.    
  453.     if Assigned(FOnConsoleCreated) then
  454.       FOnConsoleCreated(Self);
  455.    
  456.     Result := True;
  457.     Invalidate;
  458.   end
  459.   else
  460.   begin
  461.     ShowMessage('Failed to locate console window');
  462.   end;
  463. end;
  464.  
  465.  
  466. procedure TConsolePanel.CloseConsole;
  467. begin
  468.   if FConsoleHandle <> 0 then
  469.   begin
  470.     { Restore parent }
  471.     Windows.SetParent(FConsoleHandle, 0);
  472.     ShowWindow(FConsoleHandle, SW_SHOW);
  473.     FConsoleHandle := 0;
  474.     FConsoleVisible := False;
  475.   end;
  476.  
  477.   if FProcessHandle <> 0 then
  478.   begin
  479.     { Send WM_CLOSE to process }
  480.     TerminateProcess(FProcessHandle, 0);
  481.     WaitForSingleObject(FProcessHandle, INFINITE);
  482.     CloseHandle(FProcessHandle);
  483.     FProcessHandle := 0;
  484.   end;
  485.  
  486.   if Assigned(FOnConsoleClosed) then
  487.     FOnConsoleClosed(Self);
  488.  
  489.   Invalidate;
  490. end;
  491.  
  492.  
  493. procedure TConsolePanel.KillConsole;
  494. begin
  495.   if FProcessHandle <> 0 then
  496.     TerminateProcess(FProcessHandle, 1);
  497.  
  498.   if FConsoleHandle <> 0 then
  499.     FConsoleHandle := 0;
  500.  
  501.   if FProcessHandle <> 0 then
  502.   begin
  503.     CloseHandle(FProcessHandle);
  504.     FProcessHandle := 0;
  505.   end;
  506. end;
  507.  
  508.  
  509. function TConsolePanel.IsConsoleRunning: Boolean;
  510. var
  511.   ExitCode: DWORD;
  512. begin
  513.   Result := False;
  514.  
  515.   if FProcessHandle = 0 then
  516.     Exit;
  517.  
  518.   if GetExitCodeProcess(FProcessHandle, ExitCode) then
  519.     Result := (ExitCode = STILL_ACTIVE);
  520. end;
  521.  
  522.  
  523. procedure TConsolePanel.FocusConsole;
  524. begin
  525.   if FConsoleHandle <> 0 then
  526.     SetForegroundWindow(FConsoleHandle);
  527. end;
  528.  
  529.  
  530. procedure TConsolePanel.ShowConsole;
  531. begin
  532.   if FConsoleHandle <> 0 then
  533.   begin
  534.     ShowWindow(FConsoleHandle, SW_SHOW);
  535.     FConsoleVisible := True;
  536.   end;
  537. end;
  538.  
  539.  
  540. procedure TConsolePanel.HideConsole;
  541. begin
  542.   if FConsoleHandle <> 0 then
  543.   begin
  544.     ShowWindow(FConsoleHandle, SW_HIDE);
  545.     FConsoleVisible := False;
  546.   end;
  547. end;
  548.  
  549.  
  550. procedure TConsolePanel.SetConsoleTitle(const Title: String);
  551. begin
  552.   FConsoleTitle := Title;
  553.   if FConsoleHandle <> 0 then
  554.     SetWindowText(FConsoleHandle, PChar(Title));
  555. end;
  556.  
  557.  
  558. function TConsolePanel.GetConsoleHandle: HWND;
  559. begin
  560.   Result := FConsoleHandle;
  561. end;
  562.  
  563.  
  564. function TConsolePanel.GetProcessHandle: THandle;
  565. begin
  566.   Result := FProcessHandle;
  567. end;
  568.  
  569.  
  570. function TConsolePanel.GetProcessID: DWORD;
  571. begin
  572.   Result := FProcessID;
  573. end;
  574.  
  575.  
  576. function TConsolePanel.GetIsConsoleOpen: Boolean;
  577. begin
  578.   Result := (FConsoleHandle <> 0) and IsWindow(FConsoleHandle);
  579. end;
  580.  
  581.  
  582. {===============================================================================
  583.   TConsoleManager Implementation
  584. ===============================================================================}
  585.  
  586.  
  587. constructor TConsoleManager.Create(AConsolePanel: TConsolePanel);
  588. begin
  589.   inherited Create;
  590.   FConsolePanel := AConsolePanel;
  591.   FConsoleWindow := AConsolePanel.GetConsoleHandle;
  592.   FBufferSize := 4096;
  593.   FIsRedirected := False;
  594.  
  595.   FInputHandle := GetStdHandle(STD_INPUT_HANDLE);
  596.   FOutputHandle := GetStdHandle(STD_OUTPUT_HANDLE);
  597.   FErrorHandle := GetStdHandle(STD_ERROR_HANDLE);
  598. end;
  599.  
  600.  
  601. destructor TConsoleManager.Destroy;
  602. begin
  603.   RestoreHandles;
  604.   inherited Destroy;
  605. end;
  606.  
  607.  
  608. function TConsoleManager.RedirectInput: Boolean;
  609. begin
  610.   { This is complex in Windows - would require creating pipes and attaching console }
  611.   Result := False;
  612. end;
  613.  
  614.  
  615. function TConsoleManager.RedirectOutput: Boolean;
  616. begin
  617.   { This is complex in Windows - would require creating pipes and attaching console }
  618.   Result := False;
  619. end;
  620.  
  621.  
  622. procedure TConsoleManager.RestoreHandles;
  623. begin
  624.   { Restore original handles }
  625.   FIsRedirected := False;
  626. end;
  627.  
  628.  
  629. procedure TConsoleManager.Clear;
  630. var
  631.   hStdOut: THandle;
  632.   csbi: TConsoleScreenBufferInfo;
  633.   dwConSize: DWORD;
  634.   dwCount: DWORD;
  635.   dwCellCount: DWORD;
  636.   coordScreen: TCoord;
  637. begin
  638.   if FConsoleWindow = 0 then Exit;
  639.  
  640.   hStdOut := GetStdHandle(STD_OUTPUT_HANDLE);
  641.  
  642.   if GetConsoleScreenBufferInfo(hStdOut, csbi) then
  643.   begin
  644.     dwConSize := csbi.dwSize.X * csbi.dwSize.Y;
  645.     coordScreen.X := 0;
  646.     coordScreen.Y := 0;
  647.    
  648.     FillConsoleOutputCharacter(hStdOut, ' ', dwConSize, coordScreen, dwCellCount);
  649.     GetConsoleScreenBufferInfo(hStdOut, csbi);
  650.     FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, dwConSize, coordScreen, dwCount);
  651.     SetConsoleCursorPosition(hStdOut, coordScreen);
  652.   end;
  653. end;
  654.  
  655.  
  656. procedure TConsoleManager.SetTextColor(Color: Word);
  657. begin
  658.   if FConsoleWindow = 0 then Exit;
  659.   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), Color);
  660. end;
  661.  
  662.  
  663. procedure TConsoleManager.SetBufferSize(Width, Height: Word);
  664. var
  665.   hStdOut: THandle;
  666.   Coord: TCoord;
  667. begin
  668.   if FConsoleWindow = 0 then Exit;
  669.  
  670.   hStdOut := GetStdHandle(STD_OUTPUT_HANDLE);
  671.   Coord.X := Width;
  672.   Coord.Y := Height;
  673.  
  674.   SetConsoleScreenBufferSize(hStdOut, Coord);
  675. end;
  676.  
  677.  
  678. function TConsoleManager.GetBufferSize: TSize;
  679. var
  680.   hStdOut: THandle;
  681.   csbi: TConsoleScreenBufferInfo;
  682. begin
  683.   ZeroMemory(@Result, SizeOf(TSize));
  684.  
  685.   if FConsoleWindow = 0 then Exit;
  686.  
  687.   hStdOut := GetStdHandle(STD_OUTPUT_HANDLE);
  688.  
  689.   if GetConsoleScreenBufferInfo(hStdOut, csbi) then
  690.   begin
  691.     Result.cx := csbi.dwSize.X;
  692.     Result.cy := csbi.dwSize.Y;
  693.   end;
  694. end;
  695.  
  696.  
  697. function TConsoleManager.GetConsoleTitle: String;
  698. var
  699.   Buffer: array[0..255] of Char;
  700. begin
  701.   if FConsoleWindow = 0 then
  702.   begin
  703.     Result := '';
  704.     Exit;
  705.   end;
  706.  
  707.   GetWindowText(FConsoleWindow, Buffer, SizeOf(Buffer));
  708.   Result := Buffer;
  709. end;
  710.  
  711.  
  712. procedure TConsoleManager.SetConsoleTitle(const Title: String);
  713. begin
  714.   if FConsoleWindow = 0 then Exit;
  715.   SetWindowText(FConsoleWindow, PChar(Title));
  716. end;
  717.  
  718.  
  719. procedure Register;
  720. begin
  721.   RegisterComponents('CodeBox', [TConsolePanel]);
  722. end;
  723.  
  724.  
  725. end.
---
Want to kick the tires to a Free Pascal like script engine? http://www.ModernPascal.com/

Aruna

  • Hero Member
  • *****
  • Posts: 814
Re: You can embed Windows Console ~ inside your application.
« Reply #2 on: June 18, 2026, 01:42:47 am »
Can someone help get this to work with FPC?

Have a look here:  Terminal Component Available . This is for Linux but may help you get started.

Fibonacci

  • Hero Member
  • *****
  • Posts: 1037
  • Behold, I bring salvation - FPC Unleashed
Re: You can embed Windows Console ~ inside your application.
« Reply #3 on: June 18, 2026, 04:18:40 am »
Code: Pascal  [Select][+][-]
  1. procedure EmbedWindow(EmbeddedWindow: HWND; Container: TWinControl);
  2. var
  3.   Style: LONG;
  4.   EmbeddedThreadId: DWORD;
  5.   AttachedInput: Boolean;
  6. begin
  7.   // strip decorations, caption, border and resize frame from embedded window
  8.   Style := GetWindowLong(EmbeddedWindow, GWL_STYLE);
  9.   Style := Style and not (WS_CAPTION or WS_BORDER or WS_OVERLAPPED or WS_THICKFRAME);
  10.   SetWindowLong(EmbeddedWindow, GWL_STYLE, Style);
  11.  
  12.   // attach our input thread to embedded window thread, so it gets keyboard/mouse focus
  13.   EmbeddedThreadId := GetWindowThreadProcessId(EmbeddedWindow, nil);
  14.   AttachedInput := AttachThreadInput(GetCurrentThreadId, EmbeddedThreadId, True);
  15.   try
  16.     // reparent embedded window into our container
  17.     SetParent(EmbeddedWindow, Container.Handle);
  18.     SendMessage(Container.Handle, WM_UPDATEUISTATE, UIS_INITIALIZE, 0);
  19.     UpdateWindow(EmbeddedWindow);
  20.  
  21.     // clip children, prevents container from painting over the embedded window
  22.     SetWindowLong(Container.Handle, GWL_STYLE, GetWindowLong(Container.Handle, GWL_STYLE) or WS_CLIPCHILDREN);
  23.  
  24.     // stretch embedded window to fill container client area
  25.     SetWindowPos(EmbeddedWindow, 0, 0, 0, Container.ClientWidth, Container.ClientHeight, SWP_NOZORDER);
  26.  
  27.     SetForegroundWindow(EmbeddedWindow);
  28.   finally
  29.     // detach input thread, balances the AttachThreadInput above
  30.     if AttachedInput then AttachThreadInput(GetCurrentThreadId, EmbeddedThreadId, False);
  31.   end;
  32. end;
  33.  
  34. procedure tform1.button1click(sender: tobject);
  35. begin
  36.   //EmbedWindow(FindWindow(nil, 'FileZilla Pro'), Form1);
  37.   EmbedWindow(FindWindow('ConsoleWindowClass', nil), Form1);
  38. end;
FPC Unleashed: async/await, parallel for, match, tuples, string interpolation, inline vars, autofree, no-RTTI & tons more. Star on GitHub

Thaddy

  • Hero Member
  • *****
  • Posts: 19472
  • Glad to be alive.
Re: You can embed Windows Console ~ inside your application.
« Reply #4 on: June 18, 2026, 09:17:44 am »
Yes and that is really portable?  :o
Any "programmer" that knows only one programming language is not a programmer

Fibonacci

  • Hero Member
  • *****
  • Posts: 1037
  • Behold, I bring salvation - FPC Unleashed
Re: You can embed Windows Console ~ inside your application.
« Reply #5 on: June 18, 2026, 09:28:29 am »
Yes and that is really portable?  :o

Portable to a non-Windows OS? No. Another OS has no "cmd.exe", let alone a "Windows Console" to embed - which is what the OP asked for.
FPC Unleashed: async/await, parallel for, match, tuples, string interpolation, inline vars, autofree, no-RTTI & tons more. Star on GitHub

Thaddy

  • Hero Member
  • *****
  • Posts: 19472
  • Glad to be alive.
Re: You can embed Windows Console ~ inside your application.
« Reply #6 on: June 18, 2026, 10:02:09 am »
Then I will write a version that embeds a "terminal". Got to have something to do...
Any "programmer" that knows only one programming language is not a programmer

Fibonacci

  • Hero Member
  • *****
  • Posts: 1037
  • Behold, I bring salvation - FPC Unleashed
Re: You can embed Windows Console ~ inside your application.
« Reply #7 on: June 18, 2026, 10:13:32 am »
Cool idea. Feel free to take mine as the Windows version - it's ~10 years old, I just dug it out of my "pascal snippets" folder. Drop it in the Windows {$ifdef} branch and add the other platforms around it to make the multi-platform version.

And remember - get more coffee ;)
FPC Unleashed: async/await, parallel for, match, tuples, string interpolation, inline vars, autofree, no-RTTI & tons more. Star on GitHub

 

TinyPortal © 2005-2018