我在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;
它确实在我的表单上显示窗口,但玻璃边框有时会丢失(特别是当我移动表单时),很难将焦点恢复到嵌入式窗口(我需要多次单击)。 / p>
可能导致这种情况的原因是什么?另外,您是否看到使用此方法可能遇到的任何潜在问题?
感谢您的时间。
答案 0 :(得分:6)
试试这段代码。我从一个较旧的源代码中获取了它。您将丢失玻璃框架,但主菜单是可见的,我没有注意到将焦点设置回嵌入式应用程序时出现任何问题。您应该可以使用SetForegroundWindow()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);
答案 1 :(得分:2)
为了您的理智和计划用户的理智,我认为您最好放弃这个想法:
我尝试使用自己的软件(嵌入到64位包装器中的32位应用程序的窗口)完成此操作,并且它从未100%工作,即使使用您在此处获得的其他答案中的技巧
要让它可靠地工作是非常困难的,有许多微妙的问题你永远无法做到。如果你弄乱其他应用程序的窗口,这些应用程序不知道你的操作,通常你会遇到麻烦。
您正在改变用户期望Windows的行为方式。这对他们来说会让人感到困惑和意想不到。