Delphi 实现第三方程序嵌入

WinApi:GetParent SetParent MoveWindow  获取、指定父窗口和移动窗口
提示:SetParent应该Windows.SetParent,因为TForm的父类有同名方法

定义:
{获取父窗口句柄}
GetParent(hWnd:HWND):HWND;

{指定父窗口}
SetParent(
  hWndChild:HWND;{子句柄,即当前要移动对象的句柄}
  hWndNewParent:HWND;{父句柄,即要移动到的目标对象的句柄}
)

{移动窗体}
MoveWindow(
  hWnd:HWND;  {窗口句柄}
  x,y:Integer;{位置}
  nWidthm,hHeight:integer; {大小}
  bRepaint:bool            {True表示刷新;false 表示不刷新}
):boolan;

 

{
  功能:封装对第三方程序运行启动和第三方程序运行窗口显示位置
        调整的功能
  编写:sundh
  编写时间:2018.10.25
  最后修改时间:
}
unit uSetOtherAppPostion;

interface
  uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, Dialogs,shlobj,shellapi, ExtCtrls, StdCtrls,inifiles;
type
  TSetTCMSMonitor=class
    public
      {运行第三方程序并设定其运行的屏幕-多屏}
      class procedure  setMonitor(monitorIndex:Integer;ATitle:string;appName:string;appPath:string); //把制定标题的窗体移动到指定序号的屏幕上
      class procedure closeMonitor;
  end;
  TParmSet=record
    appTitle:string; //程序窗口名称
    appPath:string;//程序路径
    handle:Cardinal;//句柄
    width:integer; //宽度
    height:Integer; //高度
  end;
  TSetPosCallBack=procedure(isFinished:Boolean) of object;
  TSetPostion=class(TThread)
    private
      FControlTitle:string;
      FControlPath:string;
      FHandled:Boolean;
      FTargetHandle:Cardinal;
      FTargetWidth:Integer;
      FTargetHeight:Integer;
      FOnSetPosCallback:TSetPosCallBack;
      FtmpHandle:cardinal;
    private
      FIsCallU3D: Boolean;
      procedure fSetPostion;
      procedure ProcessSetPosCallback;
    public
      procedure execute;override;
      {关闭第三方程序,即退出程序时需要首先关闭嵌入到目标容器中的第三方程序}
      procedure CloseWindow;
      procedure CloseWindowEx;
      {运行第三方程序并设定其运行的屏幕-多屏}
//      procedure setMonitor(monitorIndex:Integer;ATitle:string;appName:string;appPath:string); //把制定标题的窗体移动到指定序号的屏幕上
      {构造方法,可通过构造方法传参也可不传参通过属性设置}
      constructor  Create(ATitle:string='';APath:string='';AHandle:cardinal=0;AWidth:Integer=0;AHeigh:Integer=0);overload;
    public
      //重新调整大小
      //aIsDoOnce: 是否执行一次
      procedure Resize(aIsDoOnce: Boolean=False);
      {控制目标程序的标题,即第三方程序运行后其显示窗口的标题}
      property ControlTitle:string read FControlTitle write FControlTitle;
      {控制目标程序的路径,即第三方程序存放的路径(全路径)}
      property ControlPath:string read FControlPath write FControlPath;
      {目标句柄,即第三方程序要植入的容器的句柄}
      property TargetHandle:Cardinal read FTargetHandle write FTargetHandle;
      {目标控件的宽度,即第三方程序要植入的容器的宽度}
      property TargetWidth:Integer read FTargetWidth write FTargetWidth;
      {目标控件的高度,即第三方程序要植入的容器的高度}
      property TargetHeight:Integer read FTargetHeight write FTargetHeight;
      {回调方法,用于通知是否已经获取制定屏幕的句柄,而且至少执行了一次置位操作}
      property OnSetPosCallback:TSetPosCallBack read FOnSetPosCallback write FOnSetPosCallback;
      //是否调用U3D
      property IsCallU3D: Boolean read FIsCallU3D write FIsCallU3D;
  end;

   TSetParent=class
     private
       FParentHandle:Cardinal;
       FChildHandle:Cardinal;
       FParentWidth:Integer;
       FParentHeight:Integer;
     public
       constructor Create;
       destructor Destroy;override;
       {设置父窗体}
       function funSetParent:Boolean;overload;
       {设置父窗体}
       function funSetParent(const parentHandle,childHandle:Cardinal;const  pwidth,pheight:Integer):Boolean;overload;
     public
       {父窗体或容器的句柄}
       property ParentHandle:Cardinal read FParentHandle write FParentHandle;
       {子窗体的句柄}
       property ChildHandle:Cardinal read FChildHandle write FChildHandle;
       {父窗体或容器的宽度}
       property ParentWidth:Integer read FParentWidth write FParentWidth;
       {父窗体或容器的高度}
       property ParentHeight:Integer read FParentHeight write FParentHeight;

   end;

  {
    功能描述:读写ini文件
    参数说明:iniPath ini文件的路径(全路径)
              section 节点
              key     键名
              value   键值
              readorwrite 读写标志 0读  1写
    编写:sundh
    编写时间:2018.10.26
  }
  procedure iniReadWrite(iniPath:string{ini文件};section:string{节点};key:string{键名};var value:string{键值};readorwrite:integer);

  var
  {机车微机屏句柄,因为程序只能启动一个机车微机屏屏程序,所以这里公用一个变量 类似P-V操作来控制}
    ahandle:Cardinal; {接口变量}
implementation

{ TSetPostion }
var
  tempHandle:Cardinal; //获取目标的句柄

procedure TSetPostion.CloseWindow;     //关闭打开窗体
begin
  if FtmpHandle > 0 then
  begin
    PostMessage(FtmpHandle, WM_CLOSE, 0, 0);
  end;
end;

procedure TSetPostion.CloseWindowEx;
begin
  if FtmpHandle > 0 then
  begin
    SetParent(FtmpHandle, 0);
    ShowWindow(FtmpHandle, SW_MINIMIZE); //最小化窗口
//    PostMessage(FtmpHandle, WM_CLOSE, 0, 0);
  end;
end;

constructor TSetPostion.Create(ATitle: string='';APath:string='';AHandle:Cardinal=0;AWidth:integer=0;AHeigh:Integer=0);
begin
  FIsCallU3D := True;
  FControlTitle:=ATitle;
  FControlPath:=APath;
  FTargetHandle:=Ahandle;
  FTargetWidth:=AWidth;
  FTargetHeight:=AHeigh;
  inherited Create(True);
end;

procedure TSetPostion.execute;
begin
  inherited;
  FreeOnTerminate:=false; //线程结束后不自动释放线程对象
  fSetPostion;  //启动设置程序
end;

procedure TSetPostion.fSetPostion;
var
  tmpHandle:Cardinal;
  label LocateWin;
begin
   tmpHandle:=0;
   tmpHandle:=FindWindow(nil,PAnsiChar(FControlTitle));
   if (tmpHandle > 0) or (FtmpHandle > 0) then   //如果目标已经启动
   begin
     if tmpHandle > 0 then
       FtmpHandle := tmpHandle;
     FHandled:=True;
//     Sleep(1000); //延时10秒钟
     //zlm 隐藏窗口标题栏
     SetWindowLong(FtmpHandle, gwl_style, getwindowlong(FtmpHandle, gwl_style) and not ws_caption);
     SetParent(FtmpHandle,FTargetHandle); //设置容器句柄
     MoveWindow(FtmpHandle,0,0,FTargetWidth,FTargetHeight,true);
     Synchronize(ProcessSetPosCallback);
     Exit;
   end
   else
   begin
     if not FIsCallU3D then
       goto LocateWin;
     if ((FileExists(FControlPath)) and (tmpHandle<=0) and ((FtmpHandle <= 0))) then  //启动目标程序
     begin
       //ShowMessage('U3D:'+ Format('FControlTitle:%s, tmpHandle=%d,  FtmpHandle=%d', [FControlTitle, tmpHandle, FtmpHandle]));
       ShellExecute(0,'open',PChar(FControlPath),'',PChar(FControlPath),SW_NORMAL);
     end;
   end;
   while (not FHandled) do
   begin
      LocateWin:
      tmpHandle:=FindWindow(nil,PAnsiChar(FControlTitle));
      if (tmpHandle > 0) or (FtmpHandle > 0) then
      begin
        if tmpHandle > 0 then
          FtmpHandle := tmpHandle;
//        Sleep(1000); //延时10秒钟
        //zlm 隐藏窗口标题栏
        SetWindowLong(FtmpHandle, gwl_style, getwindowlong(FtmpHandle, gwl_style) and not ws_caption);
        SetParent(FtmpHandle,FTargetHandle); //设置容器句柄
        MoveWindow(FtmpHandle,0,0,FTargetWidth,FTargetHeight,true);
        FHandled:=True;  //退出循环
      end;
      Sleep(10);
   end;

   Synchronize(ProcessSetPosCallback);
   FHandled:=False; // 还原状态
end;

procedure TSetPostion.ProcessSetPosCallback;
begin
  if Assigned(OnSetPosCallback) then //回调方法,通知当前状态
     OnSetPosCallback(FHandled);
end;

procedure TSetPostion.Resize(aIsDoOnce: Boolean);
begin
  if aIsDoOnce then
  begin
    if FtmpHandle = 0 then
      Exit;
    //zlm 隐藏窗口标题栏
    SetWindowLong(FtmpHandle, gwl_style, getwindowlong(FtmpHandle, gwl_style) and not ws_caption);
    SetParent(FtmpHandle, FTargetHandle); //设置容器句柄
    MoveWindow(FtmpHandle, 0, 0, FTargetWidth,FTargetHeight, True);
  end
  else
    fSetPostion;
end;

{
  功能:把标题为ATitle 的窗口移动到序号为monitorIndex的屏幕上
  ATitle:目标程序的窗口标题
  monitorIndex:目标屏幕的序号
  appName:应用程序的名称
  appPath:应用程序的路径
}
procedure iniReadWrite(iniPath:string{ini文件};section:string{节点};key:string{键名};var value:string{键值};readorwrite:integer);
var
  ini:TIniFile;
begin
  try
    if FileExists(iniPath) then
    begin
      ini:=TIniFile.Create(iniPath);
    end;
    if readorwrite=0 then
    begin
      value:=ini.ReadString(section,key,'');
    end
    else if readorwrite=1 then
    begin
      ini.WriteString(section,key,value);
    end;
  finally
    ini.Free;
  end;
end;
{ TSetTCMSMonitor }

class procedure TSetTCMSMonitor.closeMonitor;
begin
  if ahandle>0 then
     SendMessage(ahandle,WM_CLOSE,0,0); //关闭机车微机屏
  ahandle:=0;  //清空句柄变量
end;

class procedure TSetTCMSMonitor.setMonitor(monitorIndex: Integer; ATitle, appName, appPath: string);
begin
   ahandle:=FindWindow(nil,PAnsiChar(ATitle));
  if ahandle<=0 then //程序尚未启动
  begin
    if FileExists(appPath) then
       ShellExecute(0,'open',PAnsiChar(appPath),'',PAnsiChar(appPath),SW_NORMAL); //启动程序
    Sleep(2000); //延时2秒钟
    ahandle:= FindWindow(nil,PAnsiChar(ATitle));
  end;
  if ahandle>0 then
  begin
    with Screen.Monitors[monitorIndex] do
    begin
      MoveWindow(ahandle,Left-5,Top,Width+7,Height,True);
    end;
  end;
end;

{ TSetParent }

constructor TSetParent.Create;
begin
  inherited;

end;

destructor TSetParent.Destroy;
begin
  {如果子窗体没有关闭,则向子窗体发送消息,让其执行关闭动作}
  if ChildHandle>0 then  
     PostMessage(ChildHandle,WM_CLOSE,0,0);
  inherited;
end;

function TSetParent.funSetParent: Boolean;
var
  flag:Cardinal;
begin
  flag:=0;
  flag:=Windows.SetParent(ChildHandle,ParentHandle);
  if flag>0 then
  begin
     MoveWindow(ChildHandle,0,0,ParentWidth,ParentHeight,true);
     result:=True;
  end
  else
  begin
    result:=False;
  end;
end;

function TSetParent.funSetParent(const parentHandle, childHandle: Cardinal; const pwidth, pheight: Integer): Boolean;
begin
  Self.ParentHandle:=parentHandle;
  Self.ChildHandle:=childHandle;
  Self.ParentWidth:=pwidth;
  Self.ParentHeight:=pheight;
  result:=funSetParent;
end;

end.
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值