项目案例: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;
}
}