The implementation principle is to start an application, get the form handle through ProcessID, and then set the parent form handle to a control handle for this program (this example is the handle of a panel in the window), thus achieving an inline effect.
This article implements an embedded Notepad program, such as:
there are several points to note in implementing the details :
- To beautify the program's embedding effect, you need to hide its title bar
- When external form size changes, the form that needs to be embedded also varies in size
- When the external program exits, the embedded program also exits
Here is an example program. Create a new form with a panel control named Pnlapp, and then write the following code:
unitfrmTestEmbedApp;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls;type TForm1 = class(TForm) pnlApp: TPanel; procedureFormCreate(Sender: TObject); procedureFormClose(Sender: TObject; varAction: TCloseAction); procedureFormResize(Sender: TObject); private { Private declarations } public { Public declarations } end;var Form1: TForm1; hWin: HWND = 0;implementation{$R *.dfm}type // 存储窗体信息 PProcessWindow = ^TProcessWindow; TProcessWindow = record ProcessID: Cardinal; FoundWindow: hWnd; end;// 窗体枚举函数function EnumWindowsProc(Wnd: HWND; ProcWndInfo: PProcessWindow): BOOL; stdcall;var WndProcessID: Cardinal;begin GetWindowThreadProcessId(Wnd, @WndProcessID); ifWndProcessID = ProcWndInfo^.ProcessID thenbegin ProcWndInfo^.FoundWindow := Wnd; Result := False; // 已找到,故停止 EnumWindows end else Result := True; // 继续查找end;// 由 ProcessID 查找窗体 HandlefunctionGetProcessWindow(ProcessID: Cardinal): HWND;var ProcWndInfo: TProcessWindow;begin ProcWndInfo.ProcessID := ProcessID; ProcWndInfo.FoundWindow := 0; EnumWindows(@EnumWindowsProc, Integer(@ProcWndInfo)); // 查找窗体 Result := ProcWndInfo.FoundWindow;end;// 在 Panel 上内嵌运行程序functionRunAppInPanel(constAppFileName: string; ParentHandle: HWND; varWinHandle: HWND): Boolean;var si: STARTUPINFO; pi: TProcessInformation;begin Result := False; // 启动进程 FillChar(si, SizeOf(si), 0); si.cb := SizeOf(si); si.wShowWindow := SW_SHOW; ifnotCreateProcess(nil, PChar(AppFileName), nil, nil, true, CREATE_NEW_CONSOLE orNORMAL_PRIORITY_CLASS, nil, nil, si, pi) thenExit; // 等待进程启动 WaitForInputIdle(pi.hProcess, 10000); // 取得进程的 Handle WinHandle := GetProcessWindow(pi.dwProcessID); ifWinHandle > 0thenbegin // 设定父窗体 Windows.SetParent(WinHandle, ParentHandle); // 设定窗体位置 SetWindowPos(WinHandle, 0, 0, 0, 0, 0, SWP_NOSIZE orSWP_NOZORDER); // 去掉标题栏 SetWindowLong(WinHandle, GWL_STYLE, GetWindowLong(WinHandle, GWL_STYLE) and(notWS_CAPTION) and (notWS_BORDER) and(notWS_THICKFRAME)); Result := True; end; // 释放 Handle CloseHandle(pi.hProcess); CloseHandle(pi.hThread);end;procedureTForm1.FormClose(Sender: TObject; varAction: TCloseAction);begin // 退出时向内嵌程序发关闭消息 ifhWin > 0thenPostMessage(hWin, WM_CLOSE, 0, 0);end;procedureTForm1.FormCreate(Sender: TObject);const App = ‘C:\Windows\Notepad.exe‘;begin pnlApp.Align := alClient; // 启动内嵌程序 ifnotRunAppInPanel(App, pnlApp.Handle, hWin) thenShowMessage(‘App not found‘);end;procedureTForm1.FormResize(Sender: TObject);begin // 保持内嵌程序充满 pnlApp if hWin <> 0thenMoveWindow(hWin, 0, 0, pnlApp.ClientWidth, pnlApp.ClientHeight, True);end;end. |
There are several problems with this approach:
Issue 1: If the program has a splash form displayed first, the actual form cannot be embedded because only the parent form of the splash form is set to the control handle of the program, and subsequent forms cannot be set.
WORKAROUND: You can query the subsequent form by polling and set its parent form as the control handle for this program.
Issue 2: Click on the form of the embedded program, the title bar of the program loses focus
Workaround: Unknown.
Issue 3: Click the embedded program's form, press ALT+F4, then the embedded program exits, leaving only the program
Workaround: The ALT+F4 can be intercepted by hook method.
Technorati Tags: delphi,createprocess,waitforinputidle,enumwindows,setparent,setwindowlong,getwindowlong, Movewindow,startupinfo,tprocessinformation
Delphi Implementation window Embedded Other application forms