在胜利10中将窗口(另一个进程)嵌入到另一个进程中 [英] Embedding window (of another process) inside another on win 10

查看:107
本文介绍了在胜利10中将窗口(另一个进程)嵌入到另一个进程中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为另一个应用程序制作一个额外的选项面板。



我成功地使我的窗口无边界并将其不断放在另一个窗口的顶部,但这个方法有一些问题:1)它看起来不合适2)它涵盖了一些主机应用程序ui。



更好的方式似乎是另一个窗口是在我小时候在窗口进行的。令我惊讶的是,它在Win 7上就像魅力一样!但是在Windows 10上似乎有两个问题:1)另一个窗口没有边界2)育儿不起作用。



育儿并非绝对必要的,因为我可以将另一个窗口放在我的窗口上,但是当嵌入式窗口是一个孩子时它会更好地工作(让它与主窗口完美地移动而不需要z-order技巧)。这里的主要问题是那些边界...但是如果在Win 10上设置父级是可能的,这是一个很大的奖励:)



所以我需要帮助才能解决这个问题或另一个角度如何实现原始目标...



我尝试过的事情:



此示例程序启动记事本并将其嵌入 childPlaceholder 控件之上。在窗口调整大小时,子窗口会相应调整。

这是适用于Windows 7的代码:



WPF XAML:

I'd want to make an extra panel of options for another application.

I succeeded making my window borderless and placing it constantly on top of the other window, but there's a few problems in this method: 1) it looks out of place 2) it covers some of "host" applications ui.

Better way seems to be making the other window take place in my window as a child. To my surprise, it worked like charm on Win 7! But on windows 10 there seems to be 2 problems: 1) the other window doesn't go borderless 2) parenting doesn't work.

Parenting isn't absolutely necessary as I can just place the other window on my window, but it simply works better when embedded window is a child (having it move perfectly with main window and no z-order trickery needed). The main problem here is those borders... but if setting parent is possible on Win 10 it's a great bonus :)

So I need help either getting this thing fixed or another perspective how to accomplish original goal...

What I have tried:

This example program launches notepad and embeds it on top of childPlaceholder control. On window resize the child window is adjusted accordingly.
Here's the code which works on Windows 7:

WPF XAML:

<Window x:Class="EmbedWindow.MainWindow"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="Embedded window example" Height="350" Width="525" Loaded="Window_Loaded" SizeChanged="Window_SizeChanged">
    <DockPanel>
        <Grid Name="myContent" DockPanel.Dock="Right">
            <TextBlock Margin="10">Some extra content here...</TextBlock>
        </Grid>
        <Border Name="childPlaceholder" BorderBrush="DarkGray" BorderThickness="2" >
            <TextBlock Margin="10">Here should be the embedded window...</TextBlock>
        </Border>
    </DockPanel>
</Window>





代码落后(C#):



Code behind (C#):

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;

namespace EmbedWindow
{
	public partial class MainWindow : Window
	{
		IntPtr otherWindow = IntPtr.Zero, thisWindow = IntPtr.Zero;

		public MainWindow()
		{
			InitializeComponent();
		}

		private async void Window_Loaded(object sender, RoutedEventArgs e)
		{
			//This window's handle
			thisWindow = new WindowInteropHelper(this).Handle;

			//Open another program for embedding
			Process proc = new Process();
			proc.StartInfo = new ProcessStartInfo("Notepad.exe");
			proc.Start();

			//Wait until otherWindow has been opened
			await Task.Delay(500);

			otherWindow = proc.MainWindowHandle;

			//This bit removes the border of otherWindow and sets thisWindow as parent
			//I actually don't know what flags should be set, but simply setting the WS_VISIBLE flag seems to make window work, however borderless.
			WinHelper.SetWindowLong(otherWindow, WinHelper.GWL_STYLE, WinHelper.winStyle.WS_VISIBLE);
			WinHelper.SetParent(otherWindow, thisWindow);
			ArrangeWindows();
		}

		private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
		{
			ArrangeWindows();
		}

		private void ArrangeWindows()
		{
			//Moves the otherWindow on top of childPlaceHolder
			Point topLeft = childPlaceholder.TransformToAncestor(this).Transform(new Point(0, 0));
			Point bottomRight = childPlaceholder.TransformToAncestor(this).Transform(new Point(childPlaceholder.ActualWidth, childPlaceholder.ActualHeight));
			WinHelper.MoveWindow(otherWindow, (int)topLeft.X, (int)topLeft.Y, (int)bottomRight.X - (int)topLeft.X, (int)bottomRight.Y - (int)topLeft.Y, true);
		}

		//Some imported functions from user32.dll
		static class WinHelper
		{
			//Sets a window to be a child window of another window
			[DllImport("user32.dll")]
			public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

			[DllImport("user32.dll")]
			public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

			//Sets window attributes
			[DllImport("user32.dll")]
			public static extern int SetWindowLong(IntPtr hWnd, int nIndex, winStyle dwNewLong);

			public static int GWL_STYLE = -16;

			[Flags]
			public enum winStyle : int
			{
				WS_VISIBLE = 0x10000000,
				WS_CHILD = 0x40000000, //child window
				WS_BORDER = 0x00800000, //window with border
				WS_DLGFRAME = 0x00400000, //window with double border but no title
				WS_CAPTION = WS_BORDER | WS_DLGFRAME //window with a title bar
			}
		}
	}
}

推荐答案

关于不同操作系统版本之间差异的细节很难说,很抱歉不给你全面的答案。我可以给你一些一般的想法,并希望你可以在实践中考虑它们。



根本问题是将一个应用程序嵌入另一个应用程序一个(除非应用程序基于标准控制台)不是Windows操作系统的预期功能。事实上,这些技巧是可能的,这是Windows遗产的一些后果。 Windows的第一个版本不是OS产品。这是MS DOS系统上的图形环境,在我们通常使用的意义上,它本身不能被视为完全成熟的操作系统;这不是系统的大小,而是原则。回到Windows:即使应用程序是单独的进程,它们也不是具有基于NT的Windows功能的进程。所有应用程序都在相同的地址空间中工作,并且始终可以直接修改内存的任何部分。在这种背景下,使用窗口跨进程直接操作非常自然。可以通过Windows API和直接向应用程序发送/发布Windows消息。一切都在单个应用程序中共享所有资源。



随着Windows NT和虚拟内存的出现,进程已被隔离,每个进程都在其独立的空间中工作。但是,跨进程的窗口的直接操作幸免于难,这可以解释为试图保持与为非OS版本的Windows开发的应用程序的向后兼容性。这不是现代操作系统的自然特征。



因此,对我来说这样的功能最终会被打破并不奇怪。再说一遍,对不起,我不知道任何进一步的细节。



我能做的就是一个实用的建议:你做的是违反Windows API的意图,是一种虐待。你根本不应该做这些事情。将一个应用程序窗口嵌入另一个应用程序窗口没有严重的原因。当应用程序专为此类协作而设计时,应用程序将相互协作。您确实需要开发更合理的应用程序架构。如果你分享了一些最终目标,也许我可以提供更多帮助。



-SA
It's hard to say about detail of the difference between different OS versions, so sorry for not giving you the comprehensive answer. I can just give you some general ideas and hope that you can take them into account in practice.

The root problem is that such "embedding" of one application in another one (unless the applications are based on standard console) is not the intended feature of Windows OS. The fact that such tricks are possible at all is some consequence of the Windows legacy. First versions of Windows were not OS products. It was the graphical environment over the MS DOS system, which itself could not be considered as a fully-fledged OS in the sense we usually use; and this is not about the size of the system, but the principles. Back to Windows: even though the applications were the separate processes, they were not the processes with the features of the NT-based Windows. All applications worked in the same address space, and direct modification of any part of memory was always possible. On this background, direct manipulations with windows across processes was pretty much natural. It was possible through Windows API and through sending/posting Windows messages directly to the application. Everything worked as in one single application sharing all resources.

With the advent of Windows NT and virtual memory, processes have been isolated, each working in its separate space. However, direct manipulation of windows across processes survived, which can be explained as an attempt to preserve backward compatibility with applications developed for "non-OS" versions of Windows. This is not a natural feature of modern OS.

So, it's not totally surprising to me that such functionality can eventually be broken. Again, sorry, I don't know any further detail.

All I can do is one practical advice: what you do is against the intention of the Windows API, is a kind of abuse. You simply should not do such things. There are no serious reasons for embedding of one application window in another. The application collaborate with each other when they are designed for such collaboration. You really need to develop more reasonable application architecture. Perhaps I could help more if you shared some of your ultimate goals.

—SA


这篇关于在胜利10中将窗口(另一个进程)嵌入到另一个进程中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆