How can I specify the window position of an extern

2020-02-25 08:49发布

问题:

In my Win32 VCL application I am using ShellExecute to launch a number of smaller Delphi console applications. Is there a way to control the position of those console windows? I would like to launch them centered on screen.

回答1:

If you have control over the console application, You could set the console window position from inside the console application itself:

program Project1;
{$APPTYPE CONSOLE}
uses
  Windows,
  MultiMon;

function GetConsoleWindow: HWND; stdcall; external kernel32 name 'GetConsoleWindow';

procedure SetConsoleWindowPosition;
var
  ConsoleHwnd: HWND;
  R: TRect;
begin
  ConsoleHwnd := GetConsoleWindow;
  // Center the console window
  GetWindowRect(ConsoleHwnd, R);
  SetWindowPos(ConsoleHwnd, 0,
    (GetSystemMetrics(SM_CXVIRTUALSCREEN) - (R.Right - R.Left)) div 2,
    (GetSystemMetrics(SM_CYVIRTUALSCREEN) - (R.Bottom - R.Top)) div 2,
    0, 0, SWP_NOSIZE);
end;

begin
  SetConsoleWindowPosition;  
  // Other code...
  Readln;
end.

If you can't recompile the console application, you could use FindWindow('ConsoleWindowClass', '<path to the executable>') to obtain the console window handle (the Title parameter could vary if it was set via SetConsoleTitle). The downside with this approach, is that the console window is seen "jumping" from it's default position to it's new position (tested with Windows XP).



回答2:

You can use CreateProcess and specify the window size and position in its STARTUPINFO structure parameter. In the following example function, you can specify the size of a console window, which is then according to the specified size centered on the current desktop. The function returns process handle, if succeed, 0 otherwise:

function RunConsoleApplication(const ACommandLine: string; AWidth,
  AHeight: Integer): THandle;
var
  CommandLine: string;
  StartupInfo: TStartupInfo;
  ProcessInformation: TProcessInformation;
begin
  Result := 0;
  FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
  FillChar(ProcessInformation, SizeOf(TProcessInformation), 0);
  StartupInfo.cb := SizeOf(TStartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USEPOSITION or 
    STARTF_USESIZE;
  StartupInfo.wShowWindow := SW_SHOWNORMAL;
  StartupInfo.dwXSize := AWidth;
  StartupInfo.dwYSize := AHeight;
  StartupInfo.dwX := (Screen.DesktopWidth - StartupInfo.dwXSize) div 2;
  StartupInfo.dwY := (Screen.DesktopHeight - StartupInfo.dwYSize) div 2;
  CommandLine := ACommandLine;
  UniqueString(CommandLine);
  if CreateProcess(nil, PChar(CommandLine), nil, nil, False,
    NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcessInformation)
  then
    Result := ProcessInformation.hProcess;
end;