項目案例:WPF使用WindowsFormsHost播放視頻,視頻上顯示邊框、字幕等特效;
難點問題
1、WindowsFormsHost不支持背景透明;
2、WPF Panel.ZIndex無效,WindowsFormsHost更優先;
3、使用Show打開兩個窗口,數據同步延時
解決方案:
使用Popup,解決最頂層、解決背景透明
使用Canvas,解決元素拖拽
XAML
<ctrl:uiPopup x:Name="canvas" VerticalOffset="-410" IsOpen="True" AllowsTransparency="True" PopupAnimation="Fade">
<Canvas Height="410" Width="548">
<Image x:Name="PanelLeft" Height="410" Width="45" Canvas.Left="0"></Image>
<Image x:Name="PanelTop" Height="45" Width="548" Canvas.Top="0"></Image>
<Image x:Name="PanelRight" Height="410" Width="45" Canvas.Right="0"></Image>
<Image x:Name="PanelBottom" Height="45" Width="548" Canvas.Bottom="0"></Image>
<Image x:Name="PanelPlus" Height="100" Width="100" Panel.ZIndex="1"></Image>
</Canvas>
</ctrl:uiPopup>
ctrl:uiPopup控件,參考: 自定義WPF Popup控件
C#
//注冊移動事件 PanelPlus.MouseLeftButtonDown += rectOne_MouseLeftButtonDown; PanelPlus.MouseLeftButtonUp += rectOne_MouseLeftButtonUp; PanelPlus.MouseMove += rectOne_MouseMove;
bool enableMove = false;
double spanLeft = 0;
double spanTop = 0;
//鼠標移動
private void rectOne_MouseMove(object sender, MouseEventArgs e)
{
if (enableMove)
{
var cLeft = e.GetPosition(canvas).X - spanLeft;
var cTop = e.GetPosition(canvas).Y - spanTop;
//設置矩形的位置
Canvas.SetLeft(PanelPlus, cLeft);
Canvas.SetTop(PanelPlus, cTop);
}
}
//鼠標松開
private void rectOne_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
//釋放鼠標捕獲
PanelPlus.ReleaseMouseCapture();
enableMove = false;
}
//鼠標按下
private void rectOne_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var y = Convert.ToDouble(e.GetPosition(canvas).Y);
y = Utils.IsNumber(y) ? y : 0;
var x = Convert.ToDouble(e.GetPosition(canvas).X);
x = Utils.IsNumber(x) ? x : 0;
//創建鼠標捕獲
Mouse.Capture(PanelPlus);
double l = Convert.ToDouble(Canvas.GetLeft(PanelPlus));
l = Utils.IsNumber(l) ? l : 0;
double t = Convert.ToDouble(Canvas.GetTop(PanelPlus));
t = Utils.IsNumber(t) ? t : 0;
spanLeft = x - l;
spanTop = y - t;
enableMove = true;
}
public class Utils
{
//判斷字符串是否為純數字
public static bool IsNumber(object str)
{
if (str == null) return false;
ASCIIEncoding ascii = new ASCIIEncoding();
byte[] bytestr = ascii.GetBytes(str.ToString());
foreach (byte c in bytestr)
{
if (c < 48 || c > 57)
{
return false;
}
}
return true;
}
}
