将 WPF 窗口附加到另一个进程的窗口

2024-04-02

我想编写一个 WPF 应用程序,该应用程序停靠到在另一个进程中运行的应用程序(这是我无法控制的第 3 方应用程序)。理想情况下,我希望能够定义应用程序是停靠在左侧还是右侧。

这是我想做的一个例子:

我尝试实现以下 2 个示例,但没有成功。

将窗口附加到另一个进程的窗口 https://stackoverflow.com/questions/10676649/attach-window-to-window-of-another-process- Button_Click 出现以下错误:

在 C# 中将窗体窗口附加到另一个窗口 https://stackoverflow.com/questions/10773003/attach-form-window-to-another-window-in-c-sharp- Button_Click_1 将其停靠在标题栏上,但我看不到整个应用程序:

以下是代码:

namespace WpfApplicationTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    [DllImport("user32.dll")]
    public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);

    [DllImport("user32.dll")]
    public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    public static int GWL_STYLE = -16;
    public static int WS_CHILD = 0x40000000;

    [DllImport("user32")]
    private static extern bool SetWindowPos(
        IntPtr hWnd,
        IntPtr hWndInsertAfter,
        int x,
        int y,
        int cx,
        int cy,
        uint uFlags);

    private IntPtr _handle;
    private void SetBounds(int left, int top, int width, int height)
    {
        if (_handle == IntPtr.Zero)
            _handle = new WindowInteropHelper(this).Handle;

        SetWindowPos(_handle, IntPtr.Zero, left, top, width, height, 0);
    }

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Process hostProcess = Process.GetProcessesByName("notepad").FirstOrDefault();
        IntPtr hostHandle = hostProcess.MainWindowHandle;

        //MyWindow window = new MyWindow();
        this.ShowActivated = true;

        HwndSourceParameters parameters = new HwndSourceParameters();

        parameters.WindowStyle = 0x10000000 | 0x40000000;
        parameters.SetPosition(0, 0);
        parameters.SetSize((int)this.Width, (int)this.Height);
        parameters.ParentWindow = hostHandle;
        parameters.UsesPerPixelOpacity = true;
        HwndSource src = new HwndSource(parameters);

        src.CompositionTarget.BackgroundColor = Colors.Transparent;
        src.RootVisual = (Visual)this.Content;
    }

    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        Process hostProcess = Process.GetProcessesByName("notepad").FirstOrDefault();
        if (hostProcess != null)
        {
            Hide();

            //this.WindowStyle;

            //new WindowInteropHelper(this).SetBounds(0, 0, 0, 0, BoundsSpecified.Location);

            //SetWindowPos(new WindowInteropHelper(this).Handle, IntPtr.Zero, 0, 0, 0, 0, 0);
            SetBounds(0, 0, 0, 0);

            IntPtr hostHandle = hostProcess.MainWindowHandle;
            IntPtr guestHandle = new WindowInteropHelper(this).Handle;

            SetWindowLong(guestHandle, GWL_STYLE, GetWindowLong(guestHandle, GWL_STYLE) | WS_CHILD);
            SetParent(guestHandle, hostHandle);

            Show();
        }
    }
}

您的实现是完全错误的,您试图将窗口作为要捕捉的窗口的子窗口。

我编写了一个小帮助程序类,用于通过标题捕捉到另一个窗口,我希望这会有所帮助。

WindowSnapper.cs

public class WindowSnapper
{
    private struct Rect
    {
        public int Left { get; set; }
        public int Top { get; set; }
        public int Right { get; set; }
        public int Bottom { get; set; }

        public int Height
        {
            get { return Bottom - Top; }
        }

        public static bool operator !=(Rect r1, Rect r2)
        {
            return !(r1 == r2);
        }

        public static bool operator ==(Rect r1, Rect r2)
        {
            return r1.Left == r2.Left && r1.Right == r2.Right && r1.Top == r2.Top && r1.Bottom == r2.Bottom;
        }
    }

    [DllImport("user32.dll")]
    private static extern bool GetWindowRect(IntPtr hwnd, ref Rect rectangle);

    private DispatcherTimer _timer;
    private IntPtr _windowHandle;
    private Rect _lastBounds;
    private Window _window;
    private string _windowTitle;

    public WindowSnapper(Window window, String windowTitle)
    {
        _window = window;
        _window.Topmost = true;
        _windowTitle = windowTitle;

        _timer = new DispatcherTimer();
        _timer.Interval = TimeSpan.FromMilliseconds(10);
        _timer.Tick += (x, y) => SnapToWindow();
        _timer.IsEnabled = false;
    }

    public void Attach()
    {
        _windowHandle = GetWindowHandle(_windowTitle);
        _timer.Start();
    }

    public void Detach()
    {
        _timer.Stop();
    }

    private void SnapToWindow()
    {
        var bounds = GetWindowBounds(_windowHandle);

        if (bounds != _lastBounds)
        {
            _window.Top = bounds.Top;
            _window.Left = bounds.Left - _window.Width;
            _window.Height = bounds.Height;
            _lastBounds = bounds;
        }
    }

    private Rect GetWindowBounds(IntPtr handle)
    {
        Rect bounds = new Rect();
        GetWindowRect(handle, ref bounds);
        return bounds;
    }

    private IntPtr GetWindowHandle(string windowTitle)
    {
        foreach (Process pList in Process.GetProcesses())
        {
            if (pList.MainWindowTitle.Contains(windowTitle))
            {
                return pList.MainWindowHandle;
            }
        }

        return IntPtr.Zero;
    }
}

使用示例:

public partial class MainWindow : Window
{
    private WindowSnapper _snapper;

    public MainWindow()
    {
        InitializeComponent();

        _snapper = new WindowSnapper(this, "Notepad");
        _snapper.Attach();
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 WPF 窗口附加到另一个进程的窗口 的相关文章

随机推荐

  • xaml 中的 WPF ObservableCollection

    我在用户控件的代码后面创建了一个 ObservableCollection 它是在窗口加载时创建的 private void UserControl Loaded object sender RoutedEventArgs e Entiti
  • 找不到列“dbo”或用户定义函数或聚合“dbo.Splitfn”,或者名称不明确

    我使用了以下分割函数 CREATE FUNCTION dbo Splitfn String varchar 8000 Delimiter char 1 returns temptable TABLE items varchar 8000 a
  • 加密 web.config 失败错误

    我知道有人已经问过有关加密 web config 的问题 我还尝试加密我的测试配置文件 但我收到此错误 aspnet regiis pef connectionStrings C encryptedWeb config 正在加密配置部分 无
  • 从 Javascript 方法返回全局变量 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我有一个方法 function ca
  • 在 PySpark 中读取 Lzo 文件

    我是 Spark 新手 我的文件夹中有一堆 LZO 索引文件 索引已完成 如上所示https github com twitter hadoop lzo https github com twitter hadoop lzo 文件如下 1
  • 如何检查所有列表项是否具有相同的值并返回它,或者如果没有则返回另一个值?

    如果列表中的所有项目都具有相同的值 那么我需要使用该值 否则我需要使用 otherValue 我想不出一个简单明了的方法来做到这一点 当列表为空时 它应该返回 其他 值 也可以看看编写对集合中的第一项具有特殊逻辑的循环的巧妙方法 https
  • JQGRID , 获取过滤后的所有行

    过滤 JQgrid 后 我无法获取所有行 分页 我试过 gt var myData grid jqGrid getGridParam data var myData grid jqGrid getRowData 但第一个选项给出了所有行 并
  • 崩溃时退出代码

    我想通过 shell 脚本知道应用程序是否崩溃 如果应用程序崩溃 退出代码是什么 应用程序的退出代码将位于 shell 变量中 如果您的应用程序崩溃 即操作系统认为它做了坏事 并导致它终止 向其发送信号 那么这会反映在退出状态中 这是我使用
  • 在 Excel VBA 中使用 COM 插件中的 CLR 类吗?

    我有一个 Excel VSTO COM 插件 我可以成功加载 Excel VBA 中的引用 我可以交换基本类型 如字符串 但我也可以在 VBA 中使用我的外接程序中的复杂类吗 假设我有 C 类 public class TestClass
  • 在 ggplot2 中使用 geom_point 有条件地使用抖动

    I have a graph with 12 variables divided into two groups I can t use facets but using colour and shape I have been able
  • 连接或级联多个预训练的 keras 模型

    我正在尝试构建一组串联或级联 实际上甚至不知道这是否是正确的定义 的模型 为了简单起见 我的基本模型如下所示 Input L1 1 L1 2 Dense
  • 通过 Javascript 解析 JSON 对象(对象列表)并在其中循环?

    好吧 我知道出了点问题 但我不明白是什么 我从我编写的 Web 服务中读取了 Service 的 ArrayList 采用 JSON 媒体类型 访问该地址会返回 json 字符串 现在我正在尝试制作一个网页来显示该值并查看每 3 秒请求一次
  • 状态栏和底部应用栏遮挡 WP 8.1

    我使用以下代码使状态栏显示在内容顶部 并设置背景不透明度 0 var applicationView Windows UI ViewManagement ApplicationView GetForCurrentView applicati
  • jQuery PickMeUp datepicker:禁用日期数组

    我正在使用一个名为的 jQuery 日期选择器插件PickMeUp https github com nazar pc PickMeUp 我的日期选择器可以工作 但无法弄清楚如何禁用其中的日期 我的计划是在日期选择器日历上禁用一系列日期 我
  • Exchange ItemID 与 Outlook 加载项的 GlobalAppointmentID 不同

    我遇到的问题是 使用 Outlook FormRegion 创建的 Outlook 约会的 GlobalAppointmentID 与使用 EWS 托管 API 时的 ItemID 不同 我正在创建一个 Outlook 插件 允许用户将客户
  • 1.7 中 javax.sql.CommonDataSource 添加了新方法

    尝试针对 java 1 7 编译我的应用程序 我发现 javax sql CommonDataSource 以及 j s DataSource 中 添加了一个新方法 getParentLogger 你可以比较一下通用数据源 1 7 http
  • 如何将 Guava ServiceManager 与 Guice 注入结合使用

    如上所述here https plus google com 118010414872916542489 posts 86dUfeQk5dH Guava ServiceManager 可以通过以下方式获取 ServiceManager ma
  • 检查 keyDown event.modifierFlags 会产生错误

    我继承 NSTextView 并覆盖 keyDown 我想检测命令键组合 例如 Command L 苹果的文档 https developer apple com library mac documentation Cocoa Concep
  • 酶测试嵌套组件的方法

    我正在尝试使用 Enzyme 来测试组件的方法 我知道执行此操作的典型方法是使用酶instance method 问题是 这只适用于root组件和我的组件需要包装在两个上下文提供程序中才能渲染 即react router和apollo客户端
  • 将 WPF 窗口附加到另一个进程的窗口

    我想编写一个 WPF 应用程序 该应用程序停靠到在另一个进程中运行的应用程序 这是我无法控制的第 3 方应用程序 理想情况下 我希望能够定义应用程序是停靠在左侧还是右侧 这是我想做的一个例子 我尝试实现以下 2 个示例 但没有成功 将窗口附