寫插件彈窗是肯定要有的,有彈窗才有展示功能的頁面啊!
記錄一下前段時間遇到的一些彈窗方面的坑,一個個踩過來也是收獲頗豐啊!
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真的是一脈相承。。。