当前位置: 首页 > 科技观察

C#Winform实现炫酷的透明动画界面

时间:2023-03-17 22:13:12 科技观察

做过.NETWinform窗体美化的应该对UpdateLayeredWindow不陌生,UpdateLayeredWindow可以实现窗体的任意透明,效果非常好,不会出现毛边。但是使用这个API后会出现普通控件无法使用的问题,没有Paint消息。要解决这个问题,有两种方法。1、使用双层窗体,底层窗体使用UpdateLayeredWindow作为背景,上层窗体使用普通窗体,可以使用TransparencyKey或者Region去掉不需要的窗体内容,让上层窗体可以看到底层窗体.2.直接单层窗体,使用控件的DrawToBitmap将控件图像绘制到UpdateLayeredWindow窗体上,这样就可以看到普通控件了。但是这样也有问题:1.控件的内容不能自动更新。2、效率低下。许多控件使用DrawToBitmap绘制不完整的图像,甚至无法绘制图像。例如,TextBox无法显示光标,WebBrowser无法显示内容。3、使用DirectUI技术重写所有基础控件。效果最好,但工作量很大。使用UpdateLayeredWindow时,一般需要缓存Bitmap,通过设置裁剪区域和局部重绘来提高效率。另外可以异步重绘,模拟Winform失败重绘。有人会说为什么不直接用WPF呢。Wpf和Winform各有优缺点,适用于不同的场合。Winform使用起来更简单,对系统的要求也更低。当然,这取决于人们习惯于什么以及他们擅长什么。UpdateLayeredWindow的基本用法:protectedoverrideCreateParamsCreateParams{get{CreateParamscp=base.CreateParams;cp.ExStyle|=0x00080000;//WS_EX_LAYERED扩展样式returncp;}}重写表单API调用的CreateParams属性:publicvoidSetBitmap(Bitmapbitmap,byteopacity){if(bitmap.PixelFormat!=PixelFormat.Format32bppArgb)thrownewApplicationException("Bitmapmustbe32-bitwithalphachannel");IntPtrscreenDc=Win32.GetDC(IntPtr.Zero);IntPtrmemDc=Win32.CreateCompatibleDC(screenDc);IntPtrhBitmap=IntPtr.Zero;IntPtroldBitmap=IntPtr.Zero;try{hBitmap=bitmap.GetHbitmap(Color.FromArgb(0));//创建GDI位图句柄,效率较低oldBitmap=Win32.SelectObject(memDc,hBitmap);Win32.Sizesize=newWin32.大小(位图。宽度,位图。高度);Win32.PointpointSource=newWin32.Point(0,0);Win32.PointtopPos=newWin32.Point(左,上);Win32.BLENDFUNCTIONblend=newWin32.BLENDFUNCTION();blend.BlendOp=Win32.AC_SRC_OVER;blend.BlendFlags=0;blend.SourceConstantAlpha=opacity;blend.AlphaFormat=Win32.AC_SRC_ALPHA;Win32.UpdateLayeredWindow(Handle,screenDc,reftopPos,refsize,memDc,refpointSource,0,refblend,Win32.ULW_ALPHA);}finally{Win32.ReleaseDC(IntPtr.Zero,screenDc);if(hBitmap!=IntPtr.Zero){Win32.SelectObject(memDc,oldBitmap);Win32。DeleteObject(hBitmap);}Win32.DeleteDC(memDc);}}API声明:classWin32{publicenumBool{False=0,True};[StructLayout(LayoutKind.Sequential)]publicstructPoint{publicInt32x;publicInt32y;publicPoint(Int32x,Int32y){this.x=x;this.y=y;}}[StructLayout(LayoutKind.Sequential)]publicstructSize{publicInt32cx;publicInt32cy;publicSize(Int32cx,Int32cy){this.cx=cx;this.cy=cy;}}[StructLayout(LayoutKind.Sequential,Pack=1)]structARGB{publicbyteBlue;publicbyteGreen;publicbyteRed;publicbyteAlpha;}[StructLayout(LayoutKind.Sequential,Pack=1)]publicstructBLENDFUNCTION{publicbyteBlendOp;publicbyteBlendFlags;publicbyteSourceConstantAlpha;publicbyteAlphaFormat;}publicconstInt32ULW_COLORKEY=0x00000001;publicconstInt32ULW_ALPHA=0x00000002;publicconstInt32ULW_OPAQUE=0x00000004;publicconstbyteAC_SRC_OVER=0x00;publicconstbyteAC_SRC_ALPHA=0x01;[DllImport("user32.dll",ExactSpelling=true,SetLastError=true)]publicstaticexternBoolUpdateLayeredWindow(IntPtrhwnd,IntPtrhdcDst,refPointpptDst,refSizepsize,IntPtrhdcSrc,refPointpprSrc,Int32crKey,refBLENDFUNCTIONpblend,Int32dwFlags);[DllImport("user32.dll",ExactSpelling=true,SetLastError=true)]publicstaticexternIntPtrGetDC(IntPtrhWnd);[DllImport("user32.dll",ExactSpelling=true)]publicstaticexternintReleaseDC(IntPtrhWnd,IntPtrhDC);[DllImport("gdi32.dll",ExactSpelling=true,SetLastError=true)]publicstaticexternIntPtrCreateCompatibleDC(IntPtrhDC);[DllImport("gdi32.dll",ExactSpelling=true,SetLastError=true)]publicstaticexternBoolDeleteDC(IntPtrhdc);[DllImport("gdi32.dll",ExactSpelling=true)]publicstaticexternDCIntPtrPtrSelecth(Int),IntPtrhObject);[DllImport("gdi32.dll",ExactSpelling=true,SetLastError=true)]publicstaticexternBoolDeleteObject(IntPtrhObject);[DllImport("user32.dll",EntryPoint="SendMessage")]publicstaticexternintSendMessage(inthWnd,intwMsg,intwParam,intlParam);[DllImport("user32.dll",EntryPoint="ReleaseCapture")]publicstaticexternintReleaseCapture();publicconstintWM_SysCommand=0x0112;publicconstintSC_MOVE=0xF012;publicconstintSC_MAXIMIZE=61488;publicconstintSC_MINIMIZE=61472;}当需要显示图片时,调用SetBitmap方法。只要优化一下,渲染效率比普通的Paint重绘方式高很多,而且不卡顿不闪烁,支持任意透明度。下面是自己开发的效果:这个是用OpenGL画的

最新推荐
猜你喜欢