C # Winform implements a cool and transparent animation Interface
Anyone who has done. NET Winform form beautification should be familiar with UpdateLayeredWindow. UpdateLayeredWindow can achieve any transparency of the form, with good results and no edges. However, after using this API, there will be a problem that common controls cannot be used and there is no Paint message. There are two ways to solve this problem. 1. Use a double-layer form. The underlying form uses UpdateLayeredWindow as the background. The upper form uses a common form and can use TransparencyKey or Region to remove unnecessary form content, allows the upper-layer form to see the lower-layer form. 2. Use the DrawToBitmap of the control to draw the control image to the form of UpdateLayeredWindow. However, this problem also exists: 1. The control content cannot be automatically updated. 2. The efficiency is low. Many controls use DrawToBitmap to draw incomplete images, or even unable to draw images. For example, the TextBox cannot display the cursor, And the WebBrowser cannot display the content. 3. Use DirectUI technology to rewrite all basic controls. The best effect, but the heavy workload. When UpdateLayeredWindow is used, it is generally necessary to cache Bitmap and improve the efficiency by setting the editing area and partial re-painting. In addition, it can also be asynchronously re-painted to simulate failure to re-painting of Winform. Some people may say why not use WPF directly. Wpf and Winform have their own advantages and disadvantages and adapt to different occasions. Winform is easier to use and has lower system requirements. Of course, we need to look at people's habits and what they are good. UpdateLayeredWindow basic usage: override the CreateParams attribute of the form.
Protected override CreateParams {get {CreateParams cp = base. CreateParams; cp. ExStyle | = 0x00080000; // WS_EX_LAYERED extended Style return cp ;}}
API call:
Public void SetBitmap (Bitmap bitmap, byte opacity) {if (bitmap. PixelFormat! = PixelFormat. format32bppArgb) throw new ApplicationException ("the bitmap must be a 32-bit alpha Channel"); IntPtr screenDc = Win32.GetDC (IntPtr. zero); IntPtr memDc = Win32.CreateCompatibleDC (screenDc); IntPtr hBitmap = IntPtr. zero; IntPtr oldBitmap = IntPtr. zero; try {hBitmap = bitmap. getHbitmap (Color. fromArgb (0); // create a GDI bitmap handle with low efficiency oldBitmap = Win32.SelectObject (memDc, hBitmap); Win32.Size size = new Win32.Size (bi Tmap. width, bitmap. height); Win32.Point pointSource = new Win32.Point (0, 0); Win32.Point topPos = new Win32.Point (Left, Top); Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION (); blend. blendOp = Win32.AC _ SRC_OVER; blend. blendFlags = 0; blend. sourceConstantAlpha = opacity; blend. alphaFormat = Win32.AC _ SRC_ALPHA; Win32.UpdateLayeredWindow (Handle, screenDc, ref topPos, ref size, memDc, ref poin TSource, 0, ref blend, Win32.ULW _ ALPHA);} finally {Win32.ReleaseDC (IntPtr. Zero, screenDc); if (hBitmap! = IntPtr. Zero) {Win32.SelectObject (memDc, oldBitmap); Win32.DeleteObject (hBitmap);} Win32.DeleteDC (memDc );}}
API declaration:
class Win32 { public enum Bool { False = 0 , True } ; [StructLayout(LayoutKind.Sequential)] public struct Point { public Int32 x; public Int32 y; public Point(Int32 x, Int32 y) { this .x = x; this .y = y; } } [StructLayout(LayoutKind.Sequential)] public struct Size { public Int32 cx; public Int32 cy; public Size(Int32 cx, Int32 cy) { this .cx = cx; this .cy = cy; } } [StructLayout(LayoutKind.Sequential, Pack = 1 )] struct ARGB { public byte Blue; public byte Green; public byte Red; public byte Alpha; } [StructLayout(LayoutKind.Sequential, Pack = 1 )] public struct BLENDFUNCTION { public byte BlendOp; public byte BlendFlags; public byte SourceConstantAlpha; public byte AlphaFormat; } public const Int32 ULW_COLORKEY = 0x00000001 ; public const Int32 ULW_ALPHA = 0x00000002 ; public const Int32 ULW_OPAQUE = 0x00000004 ; public const byte AC_SRC_OVER = 0x00 ; public const byte AC_SRC_ALPHA = 0x01 ; [DllImport( " user32.dll " , ExactSpelling = true , SetLastError = true )] public static extern Bool UpdateLayeredWindow(IntPtr hwnd, IntPtr hdcDst, ref Point pptDst, ref Size psize, IntPtr hdcSrc, ref Point pprSrc, Int32 crKey, ref BLENDFUNCTION pblend, Int32 dwFlags); [DllImport( " user32.dll " , ExactSpelling = true , SetLastError = true )] public static extern IntPtr GetDC(IntPtr hWnd); [DllImport( " user32.dll " , ExactSpelling = true )] public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC); [DllImport( " gdi32.dll " , ExactSpelling = true , SetLastError = true )] public static extern IntPtr CreateCompatibleDC(IntPtr hDC); [DllImport( " gdi32.dll " , ExactSpelling = true , SetLastError = true )] public static extern Bool DeleteDC(IntPtr hdc); [DllImport( " gdi32.dll " , ExactSpelling = true )] public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject); [DllImport( " gdi32.dll " , ExactSpelling = true , SetLastError = true )] public static extern Bool DeleteObject(IntPtr hObject); [DllImport( " user32.dll " , EntryPoint = " SendMessage " )] public static extern int SendMessage( int hWnd, int wMsg, int wParam, int lParam); [DllImport( " user32.dll " , EntryPoint = " ReleaseCapture " )] public static extern int ReleaseCapture(); public const int WM_SysCommand = 0x0112 ; public const int SC_MOVE = 0xF012 ; public const int SC_MAXIMIZE = 61488 ; public const int SC_MINIMIZE = 61472 ;}