如何以最大化模式执行应用程序?

How to execute an application in maximized mode?

基于我的 last question,我有一个功能齐全的应用程序,可以执行外部进程。

但是有个问题。例如,当 Internet Explorer 启动时,浏览器 window 不会最大化打开。

如何使浏览器 window(或任何其他 window)以最大化模式启动?

这是我的代码:

形式:

 type
      PEnumInfo = ^TEnumInfo;
      TEnumInfo = record ProcessID: DWORD; HWND: THandle; end;

    type
      TForm1 = class(TForm)
        btn1: TButton;
        procedure btn1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;

    var
      Form1: TForm1;
      myPID: DWORD = 0;

    implementation

  uses
  UTaskBarList;  

    {$R *.dfm}

    function EnumWindowsProc(Wnd: DWORD; var EI: TEnumInfo): Bool; stdcall;
        var
          PID: DWORD;
        begin
          GetWindowThreadProcessID(Wnd, @PID);
          Result := (PID <> EI.ProcessID) or (not IsWindowVisible(WND)) or (not IsWindowEnabled(WND));
          if not Result then EI.HWND := WND;
        end;

      function FindMainWindow(PID: DWORD): DWORD;
        var
          EI: TEnumInfo;
        begin
          EI.ProcessID := PID;
          EI.HWND := 0;
          EnumWindows(@EnumWindowsProc, Integer(@EI));
          Result := EI.HWND;
        end;

    procedure dgCreateProcess(const FileName: string);
    var ProcInfo: TProcessInformation;
        StartInfo: TStartupInfo;
    begin
         FillMemory(@StartInfo, sizeof(StartInfo), 0);
         StartInfo.cb := sizeof(StartInfo);
        // StartInfo.dwX := Screen.DesktopRect.BottomRight.X;
        // StartInfo.dwY := Screen.DesktopRect.BottomRight.Y;
         CreateProcess(
                       PChar(FileName),
                       nil,
                       nil, Nil, False,
                       NORMAL_PRIORITY_CLASS,
                       nil, nil,
                       StartInfo,
                       ProcInfo);

                       myPID := ProcInfo.dwProcessId;

         CloseHandle(ProcInfo.hProcess);
         CloseHandle(ProcInfo.hThread);
    end;

    procedure TForm1.btn1Click(Sender: TObject);
    var
      hWindow : DWORD;
      szRect  : TRect;
      posX, posY, windW, windH: Integer;
    begin

      dgCreateProcess('C:\Program Files\Internet Explorer\iexplore.exe');

      repeat

          hWindow := FindMainWindow(myPID);//FindWindow('IEFrame', nil);

          if hWindow > 0 then
          begin

            GetWindowRect(hWindow,szRect);

            windW := szRect.Width;
            windH := szRect.Height;

            posX := Screen.DesktopRect.BottomRight.X;
            posY := Screen.DesktopRect.BottomRight.Y;

            MoveWindow(hWindow, posX, posY, windW, windH,True);

            TTaskbarList.Remove(hWindow);

          end;
      until (IsWindowVisible(hWindow));

     ShowMessage('outside of loop');
    end;

    end.

UTaskBarList:

unit UTaskBarList;

interface

uses ComObj, ShlObj;

type
  ITaskbarList = interface
    [SID_ITaskbarList]
    function HrInit: HResult; stdcall;
    function AddTab(hwnd: Cardinal): HResult; stdcall;
    function DeleteTab(hwnd: Cardinal): HResult; stdcall;
    function ActivateTab(hwnd: Cardinal): HResult; stdcall;
    function SetActiveAlt(hwnd: Cardinal): HResult; stdcall;
  end;

  TTaskbarList = class
  private
    xTaskbarList: ITaskbarList;
  public
    constructor Create;
    procedure Activate(hwnd: THandle);
    procedure Add(hwnd: THandle);
    procedure Delete(hwnd: THandle);
    class procedure Insert(hwnd: THandle);
    class procedure Remove(hwnd: THandle);
  end;

implementation

constructor TTaskbarList.Create;
begin
  inherited Create;
  xTaskbarList := CreateComObject(CLSID_TaskbarList) as ITaskbarList;
  xTaskbarList.HrInit;
end;

procedure TTaskbarList.Activate(hwnd: THandle);
begin
  xTaskbarList.ActivateTab(hwnd);
end;

procedure TTaskbarList.Add(hwnd: THandle);
begin
  xTaskbarList.AddTab(hwnd);
end;

procedure TTaskbarList.Delete(hwnd: THandle);
begin
  xTaskbarList.DeleteTab(hwnd);
end;

class procedure TTaskbarList.Insert(hwnd: THandle);
begin
  with TTaskbarList.Create do
  begin
    Add(hwnd);
    Free;
  end;
end;

class procedure TTaskbarList.Remove(hwnd: THandle);
begin
  with TTaskbarList.Create do
  begin
    Delete(hwnd);
    Free;
  end;
end;

end.

Windows 中最大化 window 的常用方法是从 Win32 API 调用 ShowWindow,将句柄传递给 window 和 SW_MAXIMIZE 作为参数,在进程启动后。

但是当使用CreateProcess启动一个新进程时,你可以通过设置[=16=来指示它为你调用ShowWindow ] TStartupInfoSW_MAXIMIZE 的字段。

仅当您还在 dwFlags 字段中设置了 STARTF_USESHOWWINDOW 标志时,才会考虑您在 wShowWindow 中设置的值。 dwFlags 位域确定在进程创建 window.

时是否使用 TStartupInfo 记录的某些成员

实际上,ShowWindow 是在 GUI 进程启动时自动调用的。通过设置 TStartupInfowShowWindow 字段,您只是告诉它在第一次调用 ShowWindow.

时将哪个值用作 nCmdShow 参数的参数

在您的代码中 StartInfo.cb := sizeof(StartInfo); 后添加以下行:

StartInfo.dwFlags := STARTF_USESHOWWINDOW;
StartInfo.wShowWindow := SW_MAXIMIZE;

所有这些都在 STARTUPINFO 结构的文档中进行了解释:

wShowWindow

If dwFlags specifies STARTF_USESHOWWINDOW, this member can be any of the values that can be specified in the nCmdShow parameter for the ShowWindow function, except for SW_SHOWDEFAULT. Otherwise, this member is ignored.

For GUI processes, the first time ShowWindow is called, its nCmdShow parameter is ignored wShowWindow specifies the default value. In subsequent calls to ShowWindow, the wShowWindow member is used if the nCmdShow parameter of ShowWindow is set to SW_SHOWDEFAULT.

不幸的是,这并不适用于所有应用程序。您必须针对您打算从 CreateProcess 开始的每个进程单独测试它。对于某些应用程序,在第一次调用 ShowWindow 时设置 SW_MAXIMIZED 可能还不够。