透明背景形式

时间:2015-08-19 12:23:18

标签: c# winforms

我有自定义背景图片(png)的C#视觉表单包装,如果只启动应用程序,看起来不错,但是如果我移动窗口 - 会遇到麻烦。


    
        // import
        using System;
        using System.Collections.Generic;
        using System.Text;
        using System.Drawing;
        using System.Windows.Forms;
        using System.ComponentModel;
        using System.Drawing.Drawing2D;

        // window control
        class ZTWindow : Form {
            // variables

            private Point m_MousePosition;
            private Image m_Background;

            // initilization

            /* default constructor */
            public ZTWindow() {
                Initialize();
            }

            /* initilization constructor */
            public ZTWindow(string Title) {
                Initialize();
                Text = Title;
            }

            /* default destructor */
            ~ZTWindow() {}

            /* initilization */
            private void Initialize() {
                SetStyle(ControlStyles.DoubleBuffer, true);
                // 
                m_Background = Image.FromFile(@"template\background.png", true);        
                // 
                Width = m_Background.Width;
                Height = m_Background.Height;
                AutoScaleMode = AutoScaleMode.Font;
                FormBorderStyle = FormBorderStyle.None;
                CenterToScreen();
                //
                SetupEvents();        
            }

            // events

            /* initilization for events */
            private void SetupEvents() {
                MouseDown += OnMouseDown;
                MouseMove += OnMouseMove;
            }

            /* mouse down */
            private void OnMouseDown(object Sender, MouseEventArgs Event) {
                // change mouse state & setup position
                if (Event.Button == MouseButtons.Left) {
                    m_MousePosition = new Point(Event.X, Event.Y);
                }
            }

            /* mouse move */
            private void OnMouseMove(object Sender, MouseEventArgs Event) {
                // change window location
                if (Event.Button == MouseButtons.Left) {
                    Location = new Point(Location.X + (Event.X - m_MousePosition.X), Location.Y + (Event.Y - m_MousePosition.Y));
                }
            }

            // override

            /* paint event */
            protected override void OnPaint(PaintEventArgs Event) {
                Event.Graphics.DrawImage(m_Background, 0, 0, m_Background.Width, m_Background.Height);
                base.OnPaint(Event);
            }

            /* paint background event */
            protected override void OnPaintBackground(PaintEventArgs Event) {
                // we not use background
                //base.OnPaintBackground(Event);
            }
        }
    

原始背景图片: enter image description here

发布结果: enter image description here

移动窗口的结果: enter image description here

如何在背景上制作真正透明的图像或修复绘画更新?

更新 感谢@Bauss提供了良好的链接信息(http://www.codeproject.com/Articles/1822/Per-Pixel-Alpha-Blend-in-C),它真的很有帮助并且工作正常。

完成版本: 的 Window.cs


    
            // import
            using System;
            using System.Collections.Generic;
            using System.Text;
            using System.Drawing;
            using System.Windows.Forms;
            using System.ComponentModel;
            using System.Drawing.Imaging;

            // window control
            class ZTWindow : Form {
                // variables

                private Point m_MousePosition;
                private Image m_Background;
                private PictureBox m_Picture = new PictureBox();

                // initilization

                /* default constructor */
                public ZTWindow() {
                    Initialize();
                }

                /* initilization constructor */
                public ZTWindow(string Title) {
                    Initialize();
                    Text = Title;
                }

                /* default destructor */
                ~ZTWindow() {}

                /* initilization */
                private void Initialize() {
                    m_Background = Image.FromFile(@"template\background.png", true);
                    // 
                    Width = m_Background.Width;
                    Height = m_Background.Height;
                    AutoScaleMode = AutoScaleMode.Font;
                    FormBorderStyle = FormBorderStyle.None;
                    CenterToScreen();
                    //
                    SetupEvents();
                    SetupBackground(m_Background, 255);
                }

                // events

                /* initilization for events */
                private void SetupEvents() {
                    MouseDown += OnMouseDown;
                    MouseMove += OnMouseMove;
                }

                /* mouse down */
                private void OnMouseDown(object Sender, MouseEventArgs Event) {
                    // change mouse state & setup position
                    if (Event.Button == MouseButtons.Left) {
                        m_MousePosition = new Point(Event.X, Event.Y);
                    }
                }

                /* mouse move */
                private void OnMouseMove(object Sender, MouseEventArgs Event) {
                    // change window location
                    if (Event.Button == MouseButtons.Left) {
                        Location = new Point(Location.X + (Event.X - m_MousePosition.X), Location.Y + (Event.Y - m_MousePosition.Y));
                    }
                }

                // override

                /* object create property */
                protected override CreateParams CreateParams {
                    get {
                        CreateParams tmpInstance = base.CreateParams;
                        tmpInstance.ExStyle |= 0x00080000; // WS_EX_LAYERED
                        return tmpInstance;
                    }
                }

                // helpers

                /* setup alpha blend background (Copyright © 2002-2004 Rui Godinho Lopes ) */
                public void SetupBackground(Image BackgroundImage, byte Opacity) {
                    Bitmap bitmap = (Bitmap)BackgroundImage;
                    //
                    if (bitmap.PixelFormat != PixelFormat.Format32bppArgb) {
                        throw new ApplicationException("The bitmap must be 32ppp with 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));  // grab a GDI handle from this GDI+ bitmap
                        oldBitmap = Win32.SelectObject(memDc, hBitmap);
                        Win32.Size size = new Win32.Size(bitmap.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 pointSource, 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);
                    }
                }
            }
    

Win32.cs


    
            //
            // Copyright © 2002-2004 Rui Godinho Lopes 
            // All rights reserved.
            //
            // This source file(s) may be redistributed unmodified by any means
            // PROVIDING they are not sold for profit without the authors expressed
            // written consent, and providing that this notice and the authors name
            // and all copyright notices remain intact.
            //
            // Any use of the software in source or binary forms, with or without
            // modification, must include, in the user documentation ("About" box and
            // printed documentation) and internal comments to the code, notices to
            // the end user as follows:
            //
            // "Portions Copyright © 2002-2004 Rui Godinho Lopes"
            //
            // An email letting me know that you are using it would be nice as well.
            // That's not much to ask considering the amount of work that went into
            // this.
            //
            // THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
            // EXPRESS OR IMPLIED. USE IT AT YOUT OWN RISK. THE AUTHOR ACCEPTS NO
            // LIABILITY FOR ANY DATA DAMAGE/LOSS THAT THIS PRODUCT MAY CAUSE.
            //

            using System;
            using System.Drawing;
            using System.Drawing.Imaging;
            using System.Windows.Forms;
            using System.Runtime.InteropServices;

            // class that exposes needed win32 gdi functions.
            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);
            }
    

0 个答案:

没有答案