C# 透明窗体制作方法比较(2)

 

 

 上文讨论了C#本身提供的2种透明窗体制作方法,但在有些情况下满足不了需要,这里再提供2种方法供参考。UpdateLayeredWindow()和GraphicsPath。

  关于用Windows api的SetLayeredWindowAttributes(),bitblt()制作透明窗体在这里不再讨论。SetLayeredWindowAttributes()可参照上文,bitblt()类似于UpdateLayeredWindow()。

 

(1)UpdateLayeredWindow就是把一幅图片(有alpha通道)作为窗体,做出的显示效果非常好,同时问题也来了,窗体上的任何控件是看不到的。比如,要想窗体上的一个按钮响应鼠标事件,你只能在窗体中捕获该事件,通过该事件的发生位置来判断是否由按钮来响应。对于包含多个控件的窗体来说,这将是一场灾难(至少我没实现通用性)。如果你只是想画一条鱼,在桌面上游来游去,倒是不错的选择。

基本实现:

1. 新建一WindowsForm应用程序

2.重载窗体的OnHandleCreated方法

代码
     
     
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> protected override void OnHandleCreated(EventArgs e) { SetStyle(ControlStyles.AllPaintingInWmPaint, true ); SetStyle(ControlStyles.UserPaint, true ); UpdateStyles(); base .OnHandleCreated(e); }

3.重载窗体的CreateParams方法

代码
     
     
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ --> protected override CreateParams CreateParams { get { CreateParams cParms = base .CreateParams; cParms.ExStyle |= 0x00080000 ; // WS_EX_LAYERED return cParms; } }

4.调用UpdateLayeredWindow()方法。this.BackgroundImage为你事先准备的带透明图片。

代码
     private void Form1_Load(object sender, EventArgs e)
        {
            Bitmap bitmap =new Bitmap(this.BackgroundImage);
       SetBits(bitmap);
        }
     
     
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->      public void SetBits(Bitmap bitmap) { if ( ! haveHandle) return ; if ( ! Bitmap.IsCanonicalPixelFormat(bitmap.PixelFormat) || ! Bitmap.IsAlphaPixelFormat(bitmap.PixelFormat)) throw new ApplicationException( " 图片必须是32位带Alhpa通道的图片。 " ); IntPtr oldBits = IntPtr.Zero; IntPtr screenDC = Win32.GetDC(IntPtr.Zero); IntPtr hBitmap = IntPtr.Zero; IntPtr memDc = Win32.CreateCompatibleDC(screenDC); try { Win32.Point topLoc = new Win32.Point(Left, Top); Win32.Size bitMapSize = new Win32.Size(bitmap.Width, bitmap.Height); Win32.BLENDFUNCTION blendFunc = new Win32.BLENDFUNCTION(); Win32.Point srcLoc = new Win32.Point( 0 , 0 ); hBitmap = bitmap.GetHbitmap(Color.FromArgb( 0 )); oldBits = Win32.SelectObject(memDc, hBitmap); blendFunc.BlendOp = Win32.AC_SRC_OVER; blendFunc.SourceConstantAlpha = 255 ; blendFunc.AlphaFormat = Win32.AC_SRC_ALPHA; blendFunc.BlendFlags = 0 ; Win32.UpdateLayeredWindow(Handle, screenDC, ref topLoc, ref bitMapSize, memDc, ref srcLoc, 0 , ref blendFunc, Win32.ULW_ALPHA); } finally { if (hBitmap != IntPtr.Zero) { Win32.SelectObject(memDc, oldBits); Win32.DeleteObject(hBitmap); } Win32.ReleaseDC(IntPtr.Zero, screenDC); Win32.DeleteDC(memDc); } }

(2)GraphicsPath是通过设置窗口的不规则区域来实现,在动态方面效率不如UpdateLayeredWindow,但优点也很明显,你可以在窗体里加控件,并响应你的操作。你的控件就像你的窗口一样可以实现不规则形状。(用ImageBox也很好实现不规则按钮)

实现:

1. 新建一WindowsForm应用程序

2. 实现获取不规则区域函数(为了突出重点,算法没有优化)。

代码
     
     
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->      private GraphicsPath GetWindowRegion(Bitmap bitmap) { Color TempColor; GraphicsPath gp = new GraphicsPath(); if (bitmap == null ) return null ; for ( int nX = 0 ; nX < bitmap.Width; nX ++ ) { for ( int nY = 0 ; nY < bitmap.Height; nY ++ ) { TempColor = bitmap.GetPixel(nX, nY); if (TempColor != Color.Transparent) { gp.AddRectangle( new Rectangle(nX, nY, 1 , 1 )); } } } return gp; }

3. 设置窗体区域。控件如果有Region属性,也类似,读者可自己实现。

代码
     
     
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->      private void Form1_Load( object sender, EventArgs e) { Bitmap bitmap = new Bitmap( this .BackgroundImage); this .Region = new Region(GetWindowRegion(bitmap)); }

全文完。

http://www.cnblogs.com/zhongxg/archive/2010/08/02/1790492.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值