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

时间:2017-02-04 20:21:34

标签: delphi winapi createprocess

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

但是有一个问题。例如,当启动Internet Explorer时,浏览器窗口未最大化打开。

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

这是我的代码:

形式:

 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.

1 个答案:

答案 0 :(得分:1)

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

但是当使用CreateProcess开始新流程时,您可以通过将wShowWindow的{​​{1}}字段设置为{{1}来指示它为您调用ShowWindow }}

如果您还在TStartupInfo字段中设置SW_MAXIMIZE标记,则只会考虑您在wShowWindow中设置的值。 STARTF_USESHOWWINDOW位域确定在进程创建窗口时是否使用dwFlags记录的某些成员。

实际上,GUI进程启动时会自动调用ShowWindow。通过设置dwFlags TStartupInfo字段,您只需告诉它在第一次调用ShowWindow时使用哪个值作为wShowWindow参数的参数。

在代码中TStartupInfo之后添加以下行:

nCmdShow

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

  

<强> wShowWindow

     

如果StartInfo.cb := sizeof(StartInfo);指定StartInfo.dwFlags := STARTF_USESHOWWINDOW; StartInfo.wShowWindow := SW_MAXIMIZE; ,则此成员可以是dwFlags参数中可以指定的任何值。   ShowWindow函数,STARTF_USESHOWWINDOW除外。否则,这个成员   被忽略了。

     

对于GUI进程,第一次调用nCmdShow时,忽略其SW_SHOWDEFAULT参数ShowWindow指定默认值。   在后续调用nCmdShow时,如果使用wShowWindow成员   ShowWindow的{​​{1}}参数设置为wShowWindow

不幸的是,这并不适用于所有应用程序。您必须对要以nCmdShow开头的每个进程单独测试它。对于某些应用程序,在第一次调用ShowWindow时设置SW_SHOWDEFAULT可能还不够。