WPF本身并沒有提供MDI實現,但是有個簡單的方法可以實現MDI方法。
第一步:添加引用API方法
using System;
using System.Runtime.InteropServices;
namespace WPFMdi {
public class Win32Native {
[DllImport( "user32.dll", EntryPoint = "SetParent")]
public extern static IntPtr SetParent(IntPtr childPtr, IntPtr parentPtr);
}
}
第二步:子父窗口設置
using System.Windows;
using System.Windows.Interop;
namespace WPFMdi {
/// <summary>
/// MainWindow.xaml 的交互邏輯
/// </summary>
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e) {
ChildWindow win = new ChildWindow();
win.Show();
//創建MDI窗體
WindowInteropHelper parentHelper = new WindowInteropHelper(this);
WindowInteropHelper childHelper = new WindowInteropHelper(win);
Win32Native.SetParent(childHelper.Handle, parentHelper.Handle);
}
}
}
雖然實現了MDI窗口,但是還有一些問題:先設置好主窗口背景圖片(為了能演示出效果),然后創建一個子窗口,當移動子窗口時,子窗口的邊緣產生了花屏效果。
分析了原因,應該是當窗口移動時,渲染產生了問題。所以我迫切希望在子窗口的LocationChanged事件中重繪,WPF中沒有Invalidate方法,試了很多方法也沒有成功。請教高手如何解決這個問題,或者如何重繪子窗口,使其邊緣不產生花屏效果。
我的臨時解決方案:我發現當窗口大小發生變化后,窗口會自動重繪,邊緣的花屏也就沒了,正常了。于是我在LocationChanged事件中更改窗口大小
using System;
using System.Windows;
namespace WPFMdi {
/// <summary>
/// ChildWindow.xaml 的交互邏輯
/// </summary>
public partial class ChildWindow : Window {
public ChildWindow() {
InitializeComponent();
}
#region Window重繪處理
int count = 0;
private void Window_LocationChanged(object sender, EventArgs e) {
if (count < 10) {
this.Width += 0.101;
} else if (count < 20) {
this.Width -= 0.102;
}
count = ++count % 20;
}
#endregion
}
}
微軟論壇對于該問題的回答:
很遺憾的是,WPF本身沒有實現MDI,所以你會想到用Host的方式,將一個窗體的句柄設置為另一窗體的子窗體 (調用 SetParent API)
這一點就會引起問題,WPF不同于一般的Win32程序,本身內容是沒有句柄的,因為它通過DX去實現繪制,所以消息循環就不同于Win32的窗體了,不能有一個消息隊列來對應每一個組件,來各自處理不同的消息,來處理每一次的重繪消息。何況,WPF使用DX后,為了提高性能,緩存了大量的UI信息,使并不是每次窗體區域被遮住或者改變都要進行重繪的,所以上述兩點就很顯然會導致大小改變的時候邊緣有無效區域或者花屏產生。
你的臨時方案是可行的,但是我還是要推薦你使用下面的WPF MDI解決方案://wpfmdi.codeplex.com/
他已經很好的實現了父子窗體間的消息傳遞了。
標簽:
本站文章除注明轉載外,均為本站原創或翻譯。歡迎任何形式的轉載,但請務必注明出處、不得修改原文相關鏈接,如果存在內容上的異議請郵件反饋至chenjj@fc6vip.cn
文章轉載自:CSDN學生大本營