Reputation:
Based on my last question, I have a fully functional application that can execute an external process.
But there is a problem. When, for example, Internet Explorer
is started, the browser window is not opened maximized.
How to make the browser window (or any other window) start in maximized mode?
Here is my code:
Form:
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.
Upvotes: 1
Views: 1056
Reputation: 5438
The usual way to maximize a window in Windows
is to call ShowWindow
from Win32 API, passing the handle to the window and SW_MAXIMIZE
as arguments, after the process has been started.
But when using CreateProcess
to start a new process, you can instruct it to call ShowWindow
for you, by setting the wShowWindow
field of TStartupInfo
to SW_MAXIMIZE
.
The value you set in wShowWindow
is only taken in account if you also set the STARTF_USESHOWWINDOW
flag in the dwFlags
field. The dwFlags
bitfield determines whether certain members of the TStartupInfo
record are used when the process creates a window.
Actually, ShowWindow
is called automatically when a GUI process is started. By setting the wShowWindow
field of TStartupInfo
you are just telling it which value to use as argument for nCmdShow
parameter on the first call to ShowWindow
.
Add the following lines after StartInfo.cb := sizeof(StartInfo);
in your code:
StartInfo.dwFlags := STARTF_USESHOWWINDOW;
StartInfo.wShowWindow := SW_MAXIMIZE;
All this is explained in documentation of STARTUPINFO structure:
wShowWindow
If
dwFlags
specifiesSTARTF_USESHOWWINDOW
, this member can be any of the values that can be specified in thenCmdShow
parameter for the ShowWindow function, except forSW_SHOWDEFAULT
. Otherwise, this member is ignored.For GUI processes, the first time
ShowWindow
is called, itsnCmdShow
parameter is ignoredwShowWindow
specifies the default value. In subsequent calls toShowWindow
, thewShowWindow
member is used if thenCmdShow
parameter ofShowWindow
is set toSW_SHOWDEFAULT
.
Unfortunately this does not work universally for all applications. You have to test it individually with every process that you intend to start with CreateProcess
. For some applications setting SW_MAXIMIZED
on the first call to ShowWindow
might not be enough.
Upvotes: 1