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真的是一脈相承。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM