Introduction
I am developing custom controls [Here: Form] with custom 3D shape and PathGradient colors. everything is working very smoothly and even I had achieved what I exactly want
And the whole code to generate this form is given below :-
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.ComponentModel;
namespace CustomControls
{
public class SplashFORM : Form
{
[Description("If True then user can close the form by pressing Alt + F4 while it is focused.")]
public bool CanClose { get; set; } = false;
private readonly Timer Drawer = new Timer();
public SplashFORM()
{
FormBorderStyle = FormBorderStyle.None;
StartPosition = FormStartPosition.CenterScreen;
}
protected override void OnFormClosing(FormClosingEventArgs FCEArgs)
{
if (!CanClose) { FCEArgs.Cancel = true; return; }
base.OnFormClosing(FCEArgs);
}
protected override void OnResize(EventArgs e)
{
Invalidate();
base.OnResize(e);
}
protected override void OnLoad(EventArgs EArgs)
{
if (!DesignMode)
{
DrawForm(null, null);
}
base.OnLoad(EArgs);
}
private void DrawForm(object _, EventArgs __)
{
using (Bitmap BackIMG = new Bitmap(Width, Height))
{
using (Graphics Gfx = Graphics.FromImage(BackIMG))
{
Gfx.SmoothingMode = SmoothingMode.HighQuality;
FillRoundedRectangle(Gfx);
foreach (Control C in Controls)
{
using (Bitmap BitMP = new Bitmap(C.Width, C.Height))
{
Rectangle Rect = new Rectangle(0, 0, C.Width, C.Height);
C.DrawToBitmap(BitMP, Rect);
Gfx.DrawImage(BitMP, C.Location);
}
}
SetBitmap(BackIMG, Left, Top, Handle);
}
}
}
protected override void OnPaint(PaintEventArgs PEArgs)
{
if (DesignMode)
{
Graphics Gfx = PEArgs.Graphics;
Gfx.SmoothingMode = SmoothingMode.HighQuality;
FillRoundedRectangle(Gfx);
}
base.OnPaint(PEArgs);
}
protected override CreateParams CreateParams
{
get
{
CreateParams Params = base.CreateParams;
Params.ClassStyle = 0x00020000;
Params.Style |= 0x00020000;
if (!DesignMode) { Params.ExStyle |= 0x00080000; }
return Params;
}
}
protected override void OnPaintBackground(PaintEventArgs PEArgs)
{
using (Brush GPBrush = Helper.Get_SplashBrush(new Rectangle(0, 0, Width - 1, Height - 1)))
{ PEArgs.Graphics.FillRectangle(GPBrush, ClientRectangle); }
}
private void SetBitmap(Bitmap BitMP, int CLeft, int CTop, IntPtr CHndl)
{
if (BitMP.PixelFormat != PixelFormat.Format32bppArgb) throw new ApplicationException("The BitMP must be 32ppp with alpha-channel.");
IntPtr ScrnDC = Win32.GetDC(IntPtr.Zero);
IntPtr MemDC = Win32.CreateCompatibleDC(ScrnDC);
IntPtr HBitMP = IntPtr.Zero;
IntPtr OBitMP = IntPtr.Zero;
byte OPCity = 255;
try
{
HBitMP = BitMP.GetHbitmap(Color.FromArgb(0));
OBitMP = Win32.SelectObject(MemDC, HBitMP);
Win32.Size _Size = new Win32.Size(BitMP.Width, BitMP.Height);
Win32.Point _PointSource = new Win32.Point(0, 0);
Win32.Point _TopPos = new Win32.Point(CLeft, CTop);
Win32.BLENDFUNCTION _Blend = new Win32.BLENDFUNCTION
{
BlendOp = Win32.AC_SRC_OVER,
BlendFlags = 0,
SourceConstantAlpha = OPCity,
AlphaFormat = Win32.AC_SRC_ALPHA
};
Win32.UpdateLayeredWindow(CHndl, ScrnDC, ref _TopPos, ref _Size, MemDC, ref _PointSource, 0, ref _Blend, Win32.ULW_ALPHA);
}
finally
{
Win32.ReleaseDC(IntPtr.Zero, ScrnDC);
if (HBitMP != IntPtr.Zero)
{
Win32.SelectObject(MemDC, OBitMP);
Win32.DeleteObject(HBitMP);
}
Win32.DeleteDC(MemDC);
}
}
private GraphicsPath RoundedRect()
{
Rectangle _2DSize = new Rectangle(0, 0, Width - 1, Height - 1);
int Diameter = 50 * 2;
Size _Size = new Size(Diameter, Diameter);
Rectangle _Arc = new Rectangle(_2DSize.Location, _Size);
GraphicsPath _Path = new GraphicsPath();
_Path.AddArc(_Arc, 180, 90);
_Arc.X = _2DSize.Right - 50;
_Path.AddArc(_Arc, 270, 90);
_Arc.Y = _2DSize.Bottom - 5;
_Path.AddArc(_Arc, 0, 90);
_Arc.X = _2DSize.Left - Diameter;
_Path.AddArc(_Arc, 90, 90);
_Path.CloseFigure();
return _Path;
}
private void FillRoundedRectangle(Graphics Gfx)
{
if (Gfx == null) throw new ArgumentNullException("Graphics supplied is null");
using (GraphicsPath GPth = RoundedRect())
{
var Bnds = new Rectangle(0, 0, Width - 1, Height - 1);
PointF[] PT = new PointF[]
{
new PointF(-50, -50),
new PointF(Bnds.Right, 0),
new PointF(Bnds.Right, Bnds.Bottom),
new PointF(40, Bnds.Bottom),
new PointF((float)((float)Bnds.Right / 2 - ((float)Bnds.Bottom * 0.15)), (float)((float)Bnds.Bottom / 2 + ((float)Bnds.Bottom * 0.35)))
};
Brush GPBrush = Helper.Get_SplashBrush(Bnds);
//
Gfx.FillPath(GPBrush, GPth);
Region = new Region(GPth);
//using (Brush GPBrush = Helper.Get_SplashBrush(new Rectangle(0, 0, Width - 1, Height - 1)))
//{ Gfx.FillPath(GPBrush, GPth); }
}
}
}
internal class Win32
{
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);
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)]
public struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}
}
internal class Helper
{
public static Brush Get_SplashBrush(Rectangle Bnds)
{
PointF[] PTsGH;
Color[] CLRsGH;
PathGradientBrush PGB;
PTsGH = new PointF[]
{
new PointF(-50, -50),
new PointF(Bnds.Right, 0),
new PointF(Bnds.Right, Bnds.Bottom),
new PointF(40, Bnds.Bottom),
new PointF((float)((float)Bnds.Right / 2 - ((float)Bnds.Bottom * 0.15)), (float)((float)Bnds.Bottom / 2 + ((float)Bnds.Bottom * 0.35)))
};
CLRsGH = new Color[]
{
Color.FromArgb(120,40,40),
Color.FromArgb(60, 100, 40),
Color.FromArgb(50, 50, 120),
Color.FromArgb(0, 60, 100),
Color.FromArgb(240, 120, 20, 40)
};
PGB = new PathGradientBrush(PTsGH)
{
SurroundColors = CLRsGH,
CenterColor = Color.FromArgb(160, 124, 20)
};
return PGB;
}
public enum BrushType
{
Linear, Path, Solid
}
public enum ShapeType
{
Rectangular, Circular, Triangular, SplashSpecial
}
}
}
The Problem
Everything is very fine till now but when I try to change the opacity of the form by using this code
protected override void OnClick(EventArgs e)
{
Opacity -= 0.05;
base.OnClick(e);
}
then the form becomes opaque and looks very dirty
I want to change the opacity of the form using a timer to show a fade in and fade out effect!
I tried to use Invalidate()
, Update()
and Refresh()
on the form after changing the opacity but still no luck :(
Is there a way to solve this issue, or is there any alternative to what I want to achieve?
User contributions licensed under CC BY-SA 3.0