Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 将窗口嵌入到另一个进程中_Delphi_Winapi - Fatal编程技术网

Delphi 将窗口嵌入到另一个进程中

Delphi 将窗口嵌入到另一个进程中,delphi,winapi,Delphi,Winapi,我在这里读过一些关于StackOverflow的帖子,但没有一篇对我有用。以下是我用来在表单上显示标准计算器窗口的代码: procedure TForm1.Button1Click(Sender: TObject); var Tmp: Cardinal; R: TRect; begin CalcWindow := FindWindow(nil, 'Calculator'); if (CalcWindow <> 0) then begin GetWindow

我在这里读过一些关于StackOverflow的帖子,但没有一篇对我有用。以下是我用来在表单上显示标准计算器窗口的代码:

procedure TForm1.Button1Click(Sender: TObject);
var
  Tmp: Cardinal;
  R: TRect;
begin
  CalcWindow := FindWindow(nil, 'Calculator');
  if (CalcWindow <> 0) then
  begin
    GetWindowThreadProcessID(CalcWindow, CalcProcessID);

    Tmp := GetWindowLong(CalcWindow, GWL_STYLE);
    Tmp := (Tmp and not WS_POPUP) or WS_CHILD;
    SetWindowLong(CalcWindow, GWL_STYLE, Tmp);
    GetWindowRect(CalcWindow, R);

    SetForegroundWindow(CalcWindow);
    Windows.SetParent(CalcWindow, Panel1.Handle);
    SetWindowPos(CalcWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE or SWP_FRAMECHANGED);

    AttachThreadInput(GetCurrentThreadID(), CalcWindow, True);
  end;
end;
procedure TForm1.按钮1点击(发送方:TObject);
变量
Tmp:红衣主教;
R:TRect;
开始
CalcWindow:=FindWindow(nil,“计算器”);
如果(CalcWindow 0),则
开始
GetWindowThreadProcessID(CalcWindow、CalcProcessID);
Tmp:=GetWindowLong(CalcWindow,GWL_样式);
Tmp:=(Tmp而非WS_弹出窗口)或WS_子对象;
SetWindowLong(CalcWindow,GWL_样式,Tmp);
GetWindowRect(CalcWindow,R);
SetForegroundWindow(CalcWindow);
SetParent(CalcWindow,Panel1.Handle);
设置窗口位置(CalcWindow、HWND_Top、0、0、0、SWP_NOSIZE或SWP_FRAMECHANGED);
AttachThreadInput(GetCurrentThreadID(),CalcWindow,True);
结束;
结束;
它确实会在我的窗体上显示窗口,但玻璃边框丢失,有时(特别是当我移动窗体时),很难将焦点恢复到嵌入的窗口(我需要单击几次)

这可能是什么原因造成的?另外,您是否看到我使用此方法可能遇到的任何潜在问题


谢谢您的时间。

试试这段代码。我从一个旧的源代码中获取了它。你将失去玻璃框架,但主菜单是可见的,我没有注意到任何问题,在设置焦点回到嵌入式应用程序。您应该能够使用setForeGroundIndow()API函数来实现这一点。无论何时移动容器表单,嵌入式应用程序都会失去焦点,因此需要再次调用SetForegroundWindow以恢复焦点:

procedure ShowAppEmbedded(WindowHandle: THandle; Container: TWinControl);
var
  WindowStyle : Integer;
  FAppThreadID: Cardinal;
begin
  /// Set running app window styles.
  WindowStyle := GetWindowLong(WindowHandle, GWL_STYLE);
  WindowStyle := WindowStyle
                 - WS_CAPTION
                 - WS_BORDER
                 - WS_OVERLAPPED
                 - WS_THICKFRAME;
  SetWindowLong(WindowHandle,GWL_STYLE,WindowStyle);

  /// Attach container app input thread to the running app input thread, so that
  ///  the running app receives user input.
  FAppThreadID := GetWindowThreadProcessId(WindowHandle, nil);
  AttachThreadInput(GetCurrentThreadId, FAppThreadID, True);

  /// Changing parent of the running app to our provided container control
  Windows.SetParent(WindowHandle,Container.Handle);
  SendMessage(Container.Handle, WM_UPDATEUISTATE, UIS_INITIALIZE, 0);
  UpdateWindow(WindowHandle);

  /// This prevents the parent control to redraw on the area of its child windows (the running app)
  SetWindowLong(Container.Handle, GWL_STYLE, GetWindowLong(Container.Handle,GWL_STYLE) or WS_CLIPCHILDREN);
  /// Make the running app to fill all the client area of the container
  SetWindowPos(WindowHandle,0,0,0,Container.ClientWidth,Container.ClientHeight,SWP_NOZORDER);

  SetForegroundWindow(WindowHandle);
end;
你可以这样称呼它:

  ShowAppEmbedded(FindWindow(nil, 'Calculator'), Panel1);

为了你的理智和程序用户的理智,我认为你最好放弃这个想法:

我试着用我自己的软件(嵌入64位包装器的32位应用程序的窗口)完全做到这一点,但它从来没有100%起作用,即使使用其他答案中的技巧

  • 要使它可靠地工作是非常困难的,有无数的小微妙的问题,你永远不会得到正确的。如果你在摆弄其他应用程序的窗口,而这些应用程序不知道你的操作,通常你是在自找麻烦

  • 您正在改变用户期望Windows的行为方式。这将使他们感到困惑和意外


  • 也许下面是彼得的作品,与你有关。我看不到你在改变计算器的边框样式。谢谢,但是删除标题栏会使窗口失去主菜单。要让它正常工作是出了名的困难。为什么不嵌入一个本地的Delphi计算器控件呢?我希望能够嵌入任何应用程序,计算器只是一个例子。@Pateman我建议不要尝试在你的应用程序中嵌入应用程序。谢谢!我将尝试这种方法,再加上另一种方法。儿童窗呢?比如,假设应用程序打开标准的“打开文件”对话框。有没有办法把它也保存在我的应用程序中?您认为呢?AttachThreadInput函数的第三个参数fAttach设置为False是否正常?这不意味着要分离线程吗?另一件事是,AttachInputThread必须失败,因为您提供了processId。我认为您必须传递ThreadId,它是GetWindowThreadProcessId@loursonwinny,是的,关于False参数,您是对的。我首先在另一个过程中编写了一个代码以从输入中分离,然后在此过程中复制\粘贴该代码,并且忘记将参数更改为True。@loursonwinny,同样对于AttachThreadInput失败,也就是说,我没有传递GetWindowThreadProcessId的返回值,而是在AttachThreadInput中使用了返回的进程id。谢谢你指出这一点。我更新了源代码来解决这个问题。