您的位置:首页 > 编程语言 > C#

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

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

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

 

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

基本实现:

1. 新建一WindowsForm应用程序

2.重载窗体的OnHandleCreated方法




代码

protectedoverridevoidOnHandleCreated(EventArgs e)

{

SetStyle(ControlStyles.AllPaintingInWmPaint, true);

SetStyle(ControlStyles.UserPaint, true);

UpdateStyles();

base.OnHandleCreated(e);

}

3.重载窗体的CreateParams方法




代码
protectedoverrideCreateParams CreateParams

{

get

{

CreateParams cParms =base.CreateParams;

cParms.ExStyle |=0x00080000; //WS_EX_LAYERED

returncParms;

}

}

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




代码
     private void Form1_Load(object sender, EventArgs e)

{

Bitmap bitmap =new Bitmap(this.BackgroundImage);       SetBits(bitmap);

}
     publicvoidSetBits(Bitmap bitmap)

{

if(!haveHandle) return;

if(!Bitmap.IsCanonicalPixelFormat(bitmap.PixelFormat) ||!Bitmap.IsAlphaPixelFormat(bitmap.PixelFormat))

thrownewApplicationException("图片必须是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 =newWin32.Point(Left, Top);

Win32.Size bitMapSize =newWin32.Size(bitmap.Width, bitmap.Height);

Win32.BLENDFUNCTION blendFunc =newWin32.BLENDFUNCTION();

Win32.Point srcLoc =newWin32.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, reftopLoc, refbitMapSize, memDc, refsrcLoc, 0, refblendFunc, 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. 实现获取不规则区域函数(为了突出重点,算法没有优化)。




代码
    privateGraphicsPath GetWindowRegion(Bitmap bitmap)

{

Color TempColor;

GraphicsPath gp =newGraphicsPath();

if(bitmap ==null) returnnull;

for(intnX =0; nX <bitmap.Width; nX++)

{

for(intnY =0; nY <bitmap.Height; nY++)

{

TempColor =bitmap.GetPixel(nX, nY);

if(TempColor !=Color.Transparent)

{

gp.AddRectangle(newRectangle(nX, nY, 1, 1));

}

}

}

returngp;

}

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

 

 

转自:http://www.cnblogs.com/jxsoft/archive/2011/03/09/1978156.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: