Author: Jonas Bilinkevicius
I want to execute an external program from my Delphi application when I click on a
button. However, when the program is executed, I want both my Delphi application
and the external program to tile side by side (just like in Windows own "Tile
windows") vertically.
Answer:
The problem boils down to finding the started programs window handle. Once you have
that the tiling boils down to a single call to the TileWIndow API function. The
following is starting an application and tiling its window with the current
application window.
1
2 procedure StartAppAndTileWindows(const appname: string; const windows: array of
3 HWND;
4 tileHorizontal: Boolean = true);
5 const
6 tileflags: array[Boolean] of UINT = (MDITILE_VERTICAL, MDITILE_HORIZONTAL);
7 var
8 currhwnd: HWND;
9 newhwnd: HWND;
10 counter: Integer;
11 wndArray: array of HWND;
12 begin
13 currhwnd := GetForegroundWindow;
14 if ShellExecute(currhwnd, nil, Pchar(appname), nil, nil, SW_SHOWNORMAL) > 32 then
15 begin
16 counter := 0;
17 repeat
18 Sleep(100);
19 newhwnd := GetForegroundWindow;
20 if (newhwnd <> 0) and (newhwnd <> currhwnd) then
21 begin
22 SetLength(wndArray, High(windows) + 2);
23 Move(windows[0], wndArray[0], (High(windows) + 1) * sizeof(HWND));
24 wndArray[High(wndArray)] := newhwnd;
25 TileWindows(0, {tile on desktop}
26 tileflags[tileHorizontal], {mode as per param}
27 nil, {use desktops full client area}
28 Length(wndArray), {count of windows to tile}
29 @wndArray[0]); {array of window handles to tile}
30 Exit;
31 end
32 else
33 Inc(counter);
34 until
35 counter >= 20;
36 raise Exception.CreateFmt('Could not find main window of %s', [appname]);
37 end;
38 raise Exception.CreateFmt('Could not execute %s', [appname]);
39 end;
40
41 procedure TForm1.Button1Click(Sender: TObject);
42 begin
43 StartAppAndTileWindows('notepad.exe', [handle]);
44 end;
|