• VSTO之WPF和Winform弹窗


    写插件弹窗是肯定要有的,有弹窗才有展示功能的页面啊!
    记录一下前段时间遇到的一些弹窗方面的坑,一个个踩过来也是收获颇丰啊!

    WPF弹窗

    最简单的弹窗方式,new一个窗体,然后调用Show方法。

    Window window = new Window();
    window.Show();
    

    然后根据需求的不一样,就有一些东西要调整了,简单一些的比如是否在任务栏显示,是否允许最大最小化,是否运行拖拽等等

    window.ShowInTaskbar = false;
    window.ResizeMode = ResizeMode.NoResize;
    window.AllowDrop = false;
    

    像上面那样一顿噼里哗啦操作。确实,弹窗出来了~但是点击起来就有点不对劲了。每次点击或焦点切换到主窗体的时候,弹窗都会被主窗体盖住。
    马上想到了有一个解决方法,设置弹窗为最顶层就ok了啊!就不用担心被盖住了。

    window.Topmost = true;
    

    果然达到了预期,哪怕焦点切换了,弹窗也还是显示在最上面。emmmm,这么大个问题解决了,偷偷摸个鱼不过分吧!愉快的tab切换摸鱼模式。可是,什么鬼!为啥这个弹窗还跟过来了啊!原来不只是插件页面置顶了,全部软件都置顶啊!
    正确解决方法

    Window window = new Window();
    window.Title = "我是WPF弹窗!!!!";
    new System.Windows.Interop.WindowInteropHelper(window) { Owner = new IntPtr(Globals.ThisAddIn.Application.HWND) };
    window.Show();
    

    WindowInteropHelper 这个名字看着有点像自己定义的类,其实是微软的一个帮助类,用于协助WPF和Win32代码之间的互相操作。最简单的应用就是在Win32中弹出一个WPF的弹窗。

    这时候就可以看到,焦点在主窗口时,弹窗也不会被遮盖,并且最小化主窗口的时候,弹窗也会被收起来,切换到别的软件时,会正常盖住弹窗!

    Winform弹窗

    Winform的弹窗肯定和WPF的差不多,毕竟也是先有的Winform才有的WPF。一样两句话弹个窗,但是问题也和上面的一样!

    Form form = new Form();
    form.Show();
    

    细心一点可以发现,在输入Show方法的时候,其实是有一个重载方法的,需要传入一个IWin32Window对象。并且IWin32Window其实是一个接口类,内部只有一个返回句柄的属性。

    //owner:任何实现 System.Windows.Forms.IWin32Window 并表示将拥有此窗体的顶级窗口的对象。
    public void Show(IWin32Window owner);
    
    public interface IWin32Window
    {
        //获取表示由实现者的窗口句柄。
        IntPtr Handle { get; }
    }
    

    尝试一下,建一个类继承IWin32Window接口,然后根据主页面的句柄去new一下这个类,并作为参数传入到Show方法里面。

    public class WinWrap : IWin32Window
    {
        private IntPtr m_Handle;
        public IntPtr Handle
        {
            get { return m_Handle; }
        }
        //构造函数,参数是父窗口的句柄
        public WinWrap(int handle)
        {
            this.m_Handle = new IntPtr(handle);
        }
    }
    
    Form form = new Form();
    form.Text = "这是Winform弹窗!!!";
    WinWrap owner = new WinWrap(Globals.ThisAddIn.Application.HWND);
    form.Show(owner);
    

    Winform弹窗内嵌入WPF控件

    由于一些接口只允许传入Winform窗体或控件,所以需要将WPF控件包装一下

    var toolControl = new Controls.ToolControl();//WPF控件
    var form = new System.Windows.Forms.UserControl();//Winform控件
    System.Windows.Forms.Integration.ElementHost elementHost = new System.Windows.Forms.Integration.ElementHost();
    elementHost.Child = toolControl;
    elementHost.Dock = System.Windows.Forms.DockStyle.Fill;
    form.Controls.Add(elementHost);           
    

    总结

    感叹一下,Winform和WPF真的是一脉相承。。。

  • 相关阅读:
    ADO.NET批量插入数据方法比较
    Thread was being aborted 分析与解决
    第三方刻录软件介绍
    ASP.NET登陆SQL Server数据库
    word 2010页眉页码从第三页开始设置
    误删除、误格式化后的灾难恢复方案
    Asp.Net4.0新特性概述
    ArcGIS Server的切图原理深入
    ArcGIS的缓存技术
    ArcGIS Server操作Mxd文件详细讲解
  • 原文地址:https://www.cnblogs.com/cplemom/p/11514668.html
Copyright © 2020-2023  润新知