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

Posted

技术标签:

【中文标题】如何以最大化模式执行应用程序?【英文标题】:How to execute an application in maximized mode? 【发布时间】:2017-02-04 20:21:33 【问题描述】:

根据我的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.

【问题讨论】:

尝试将StartupInfo.dwFlags 设置为STARTF_USESHOWWINDOWStartupInfo.wShowWindow 设置为SW_MAXIMIZE @quasoft,谢谢,这行得通。 但在您之前的问题中,您希望应用程序在屏幕外启动和/或隐藏。那么它是否“最大化”又有什么关系呢? (这意味着填充计算机上可能多个屏幕之一的整个空间。即 on-screen), 【参考方案1】:

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

但是当使用CreateProcess启动一个新进程时,你可以通过将TStartupInfowShowWindow字段设置为SW_MAXIMIZE来指示它为你调用ShowWindow

只有在dwFlags 字段中设置了STARTF_USESHOWWINDOW 标志时,才会考虑您在wShowWindow 中设置的值。 dwFlags 位域决定进程创建窗口时是否使用TStartupInfo 记录的某些成员。

实际上,ShowWindow 在 GUI 进程启动时会自动调用。通过设置TStartupInfowShowWindow 字段,您只是告诉它在第一次调用ShowWindow 时将哪个值用作nCmdShow 参数的参数。

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

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

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

wShowWindow

如果dwFlags 指定STARTF_USESHOWWINDOW,则此成员可以是可以在nCmdShow 参数中指定的任何值 ShowWindow 函数,SW_SHOWDEFAULT 除外。否则,该成员 被忽略。

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

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

【讨论】:

以上是关于如何以最大化模式执行应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

如何在管理模式和最大化窗口中启动.exe?

Winforms:如何加速 Invalidate()?

如何在 Symfony 2 中进入维护模式以安全地更新生产应用程序?

MFC 应用程序只能在管理员模式下最大化

如何以编程方式关闭在 Kiosk 模式下运行的 Chrome?

从python调用命令行以使用args以批处理模式执行程序[重复]