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