手头目前的一个项目(.Net4.0)中有这样一个需求:在程序中要进行视频采集,并且要在视频影像区域进行绘图编辑,对绘图能进行拉伸,拖拽和删除。从需求来看,必须得在视频影像区的上方盖一层画布才能这么操作了。

  首先是找视频成像控件,在网上找了一圈,找到AForge(http://www.aforgenet.com/framework/downloads.html),写了个测试代码,直接用办公用的笔记本摄像头进行视频采集,发现还不错,DevExpress也有一个视频控件,不过那个设置起来比较麻烦,而且我们也不需要用那么多附加功能,只要能够输出影像就可以。

  然后就开始折腾视频层的上一层了。一开始想法挺简单,panel不就是可以透明的吗,找了网上的一个方法,对panel进行透明设置:

BackColor=Color.Transparent

设置完成后调试,哦哟,果然是透明的,然后兴冲冲的把视频控件开启,悲剧的发现那层白花花的panel挡了,看来此法不通。

然后仔细研究了一下Winform的透明机制,控件的BackColor应该是一个“静态”属性,是在重绘的时候进行颜色的传递,达到透明的目的,其实是把Panel做成了完美的“变色龙”,而视频流应该是无法通过这种方式透传的(不知道我的理解对不对),而我们要的是一块玻璃,因此这种方式不能达到目的。

然后又开始了各种google,网上找到另一种方式的透明:控制重绘。具体参看[http://my.oschina.net/HenuToater/blog/520649]

结果还是没法把视频流透传上来。

这下抓瞎了,病急乱投医,开始尝试各种方法,而网上能找到的都是第一种方式。

后来找到一个Demo,是利用Form来做这个透明的,因为Form本身就有透明属性:Opacity,把这个属性调到1以下,就能产生透明效果。

OK,就用Form的透明吧,然后紧接着第二个问题来了,怎么盖到目标控件上面呢?

一开始也是各种瞎试,后来找到一个老司机带路

Form a = new Form();
a.Show(this); //设置a的Location

然后再监听主窗体的移动事件,基本上就可以了。

接着,我又兴高采烈的开始往下做,在这层Form上画了几个图形,惨烈的发现画出来的图形也是透明的,颜色非常淡。这个就是Form透明设置的结果吧——一透到底,上面的控件什么的都透明了,这个可不是我想要的。

继续在网上瞎几把找(Winform开发真是累),后来找到了一个商业库(DSkin),国人开发的,价格也算良心,跟作者沟通了自己遇到的问题,作者表示自己的库能解决这个问题,于是花了199大洋买了授权,(以下内容为安利DSkin)看了一下DSkin做得还算不错的,整个控件库看下来,大多是针对特效这块做的,作者对Winform应该是非常通透的。

买了授权后,开始心急火燎的写测试程序,在和作者一轮沟通交流后,顺利的解决了这个折腾我2天的东西。

代码:

GlassDraw.cs 部分

    public partial class GlassDrawer : DSkinForm
{
private Image _Backup; public GlassDrawer()
{
FormBorderStyle = FormBorderStyle.None;
BackColor = Color.Transparent;
DoubleBuffered = true;
ShowInTaskbar = false;
ShowSystemButtons = false;
DrawIcon = false;
ShowIcon = false;
EnableAnimation = false;
Text = string.Empty;
InitializeComponent();
_Backup = new Bitmap(this.Width, this.Height);
_LastLocation = Location;
} public Func<GlassDrawer,bool> MoveAssert
{
get;set;
} public void Draw(Action<Graphics> drawer)
{
try
{
Graphics g = Graphics.FromImage(_Backup);
drawer(g);
g.Dispose();
Invalidate();
}
catch(Exception e)
{ }
}
protected override void OnLayeredPaint(PaintEventArgs e)
{
if (_Backup != null)
{
e.Graphics.DrawImage(_Backup, , );
}
}
protected override void OnMove(EventArgs e)
{ base.OnMove(e);
}
private Point _LastLocation;
protected override void OnLocationChanged(EventArgs e)
{
if (MoveAssert != null)
{
if (!MoveAssert(this))
{
Location = _LastLocation;
return;
}
}
_LastLocation = Location;
base.OnLocationChanged(e);
} private Point _TargetLocation;
private Control _Target;
public void Follow(Control target)
{
if(_Target != null)
{
_Target.LocationChanged -= Target_LocationChanged;
}
_Target = target;
target.LocationChanged += Target_LocationChanged;
_TargetLocation = PointToScreen( target.Location);
} private void Target_LocationChanged(object sender, EventArgs e)
{
var p = PointToScreen(_Target.Location); }
}

Form1.cs 部分

InitializeComponent();
gd.Width = cameraFrame1.Width;
gd.Height = cameraFrame1.Height;
gd.Location = PointToScreen(cameraFrame1.Location);
gd.Text = string.Empty;
gd.MoveAssert = (g) =>
{
var srcp = PointToScreen(g.Location);
int top = srcp.Y;
int left = srcp.X;
int right = srcp.X + g.Width;
int bottom = srcp.Y + g.Height;
var targetp = PointToScreen(this.Location); if (top < targetp.Y ||
left < targetp.X ||
right > targetp.X + this.Width ||
bottom > targetp.Y + this.Height)
return false;
return true;
};
gd.Show(this);
cameraFrame1.Start();

最新文章

  1. 【腾讯bugly干货分享】HTML 5 视频直播一站式扫盲
  2. Kubernetes集群搭建过程中遇到的问题
  3. vmware esxi 找不到网卡驱动,硬盘的解决方法
  4. nginx相关配置说明
  5. NSArray和NSDictionary的混合
  6. 【HDOJ】4305 Lightning
  7. JS单词形式的运算符
  8. Canvas保存图片保存到本地
  9. jQuery实现页面元素智能定位
  10. tomcat实现多端口、多域名访问
  11. js封装一个模块
  12. springboot项目js文件404
  13. 模仿WIN32程序处理消息
  14. OC 属性关键字
  15. nginx信号量
  16. servlet填充Response时,数据转换之content-type
  17. Always on (HA 负载均衡 异地容灾 一体化 )
  18. lable标签的妙用
  19. 前端开发之JavaScript基础篇四
  20. 02_zookeeper配置

热门文章

  1. COGS2531. [HZOI 2016]函数的美 打表+欧拉函数
  2. dwarf tower
  3. CSS-用伪类制作小箭头(轮播图的左右切换btn)
  4. Html中设置访问页面不在后进行其他页面跳转
  5. 逆向工程学习第二天--动手开发自己的第一个shellcode
  6. wamp 局域网访问
  7. SpringMVC学习记录2
  8. 商业智能BI
  9. mysql中Invalid default value for &#39;stime&#39;问题
  10. Android Studio使用Git版本控制工具