using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
 
namespace alphatest
{
    public class AlphaWindow : Form
    {
        private Timer t;
        private Bitmap b, ob;
        public AlphaWindow(Bitmap bitmap)
        {
            b = bitmap;
            TopMost = true;
            ShowInTaskbar = false;
            Size = bitmap.Size;
            StartPosition = FormStartPosition.CenterScreen;
            Show();			
 
            t = new Timer {Interval = 50};
            t.Tick += t_Tick;
            ob = new Bitmap(b.Width, b.Height);
            t.Start();
        }
 
        private float op = 0.00001f;
        void t_Tick(object sender, EventArgs e)
        {
            Graphics g = Graphics.FromImage(ob);
            if(op<1)op *= 1.2f;
            ColorMatrix m = new ColorMatrix { Matrix33 = op };
 
            ImageAttributes at = new ImageAttributes();
            at.SetColorMatrix(m, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
            g.Clear(Color.Transparent);
            g.DrawImage(b, new Rectangle(0, 0, b.Width, b.Height), 0, 0, b.Width, b.Height, GraphicsUnit.Pixel, at);
            SelectBitmap(ob);
            g.Dispose();
        }
 
        public void SelectBitmap(Bitmap bitmap)
        {
            if (bitmap.PixelFormat != PixelFormat.Format32bppArgb)
            {
                throw new ApplicationException("The bitmap must be 32bpp with alpha-channel.");
            }
            IntPtr screenDc = APIHelp.GetDC(IntPtr.Zero);
            IntPtr memDc = APIHelp.CreateCompatibleDC(screenDc);
            IntPtr hBitmap = IntPtr.Zero;
            IntPtr hOldBitmap = IntPtr.Zero;
            try
            {
                // Get handle to the new bitmap and select it into the current device context
                hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
                hOldBitmap = APIHelp.SelectObject(memDc, hBitmap);
 
                // Set parameters for layered window update
                APIHelp.Size newSize = new APIHelp.Size(bitmap.Width, bitmap.Height);	// Size window to match bitmap
                APIHelp.Point sourceLocation = new APIHelp.Point(0, 0);
                APIHelp.Point newLocation = new APIHelp.Point(Left, Top);		// Same as this window
                APIHelp.BLENDFUNCTION blend = new APIHelp.BLENDFUNCTION
                                                  {
                                                      BlendOp = APIHelp.AC_SRC_OVER,
                                                      BlendFlags = 0,
                                                      SourceConstantAlpha = 255,
                                                      AlphaFormat = APIHelp.AC_SRC_ALPHA
                                                  };
 
                // Update the window
                APIHelp.UpdateLayeredWindow(Handle, screenDc, ref newLocation, ref newSize,
                    memDc, ref sourceLocation, 0, ref blend, APIHelp.ULW_ALPHA);
            }
            finally
            {
                // Release device context
                APIHelp.ReleaseDC(IntPtr.Zero, screenDc);
                if (hBitmap != IntPtr.Zero)
                {
                    APIHelp.SelectObject(memDc, hOldBitmap);
                    APIHelp.DeleteObject(hBitmap);										// Remove bitmap resources
                }
                APIHelp.DeleteDC(memDc);
            }
 
        }
        Point p = new Point(-1, -1);
 
 
        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (p.X == -1)
                    p = e.Location;
                else
                    Location = new Point(Location.X + (e.X - p.X), Location.Y + (e.Y - p.Y));
            }
            else
            {
                p = new Point(-1, -1);
            }
            base.OnMouseMove(e);
        }
 
        protected override CreateParams CreateParams
        {
            get
            {
                // Add the layered extended style (WS_EX_LAYERED) to this window
                CreateParams createParams = base.CreateParams;
                createParams.ExStyle |= APIHelp.WS_EX_LAYERED;
                return createParams;
            }
        }
 
        // Let Windows drag this window for us (thinks its hitting the title bar of the window)
        //protected override void WndProc(ref Message message)
        //{
        //    if (message.Msg == APIHelp.WM_NCHITTEST)
        //    {
        //        // Tell Windows that the user is on the title bar (caption)
        //        //message.Result = (IntPtr)APIHelp.HTCAPTION;
        //    }
        //    /*else if(message.Msg == 3)
        //    {
        //        return;
        //    }*/
        //    else
        //    {
        //        base.WndProc(ref message);
        //    }
        //}
        private void InitializeComponent()
        {
            SuspendLayout();
            // 
            // AlphaWindow
            // 
            AutoValidate = AutoValidate.EnablePreventFocusChange;
            ClientSize = new Size(284, 262);
            FormBorderStyle = FormBorderStyle.None;
            Name = "AlphaWindow";
            ShowInTaskbar = false;
            Load += Splash_Load;
            MouseDown += AlphaWindow_MouseDown;
            MouseMove += AlphaWindow_MouseMove;
            ResumeLayout(false);
 
        }
 
        private void Splash_Load(object sender, EventArgs e)
        {
 
        }
 
        protected override void OnClick(EventArgs e)
        {
            base.OnClick(e);
            //Close();
        }
 
        private void AlphaWindow_MouseDown(object sender, MouseEventArgs e)
        {
            OnDragOver(null);
        }
 
        private void AlphaWindow_MouseMove(object sender, MouseEventArgs e)
        {
        }
 
    }
 
    // Class to assist with Win32 API calls
    class APIHelp
    {
        // Required constants
        public const Int32 WS_EX_LAYERED = 0x80000;
        public const Int32 HTCAPTION = 0x02;
        public const Int32 WM_NCHITTEST = 0x84;
        public const Int32 ULW_ALPHA = 0x02;
        public const byte AC_SRC_OVER = 0x00;
        public const byte AC_SRC_ALPHA = 0x01;
 
        public enum Bool
        {
            False = 0,
            True = 1
        }
 
        [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;
        }
 
        [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("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
 
        [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 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);
 
    }
}