Changing Windows Form - c#

I'm looking into a way of altering the frame around a windows form box. I want to make it either transparent, or get rid of it entirely. I managed to get rid of the icon, and get rid of the maximize button, as well as restrict the user's ability to resize the window. The bar clashes with the visual theme I'm trying to implement.
So question - Is there any good way customizing the form border & the top bar in a Windows Form application?

Select the correct value for FormBorderStyle, like None.

This might be overkill for what you're asking, but here goes... This was a quick application I created with a circular border. It's not the entire code, but maybe you'll get the idea from it.
First, I remove the FormBorderStyle (Set it equal to None) and add a mouse handler to allow movement of the form. Code below...
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImportAttribute("user32.dll")]
public static extern bool ReleaseCapture();
public const int WM_NCLBUTTONDOWN = 0xA1;
public const int HT_CAPTION = 0x2;
private void Form1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
}
}
Then I created a pink mesh to display as the form background. and set the TransparencyKey property to the RGB value of the background color I wanted to be transparent (in this case 255,15,255).
Then I drew the literal controls with a graphics module.
private void Form1_Paint(object sender, PaintEventArgs e)
{
// Set the starting coordinants for our graphics drawing
int y = 0;
int x = 0;
// Set the end coordinants for our graphics drawing
int width = this.Size.Width;
int height = this.Size.Height;
// Set our graphics options
e.Graphics.InterpolationMode = XGraphics.xInterpolation;
e.Graphics.SmoothingMode = XGraphics.xSmoothingMode;
e.Graphics.CompositingMode = XGraphics.xComposingMode;
e.Graphics.CompositingQuality = XGraphics.xComposingQuality;
e.Graphics.PixelOffsetMode = XGraphics.xPixelOffsetMode;
// Set the colors, positions, and gradient directions then draw our background
using (LinearGradientBrush gpxBrush = XGraphics.GradientBrushOrientation(0, x, y, width, height))
{
// Create our color blender object
ColorBlend gpxBlend = null;
gpxBlend = new ColorBlend(4);
gpxBlend.Colors = new Color[] { Color.FromArgb(255, 0, 100, 255), Color.FromArgb(205, 255, 240, 240),
Color.FromArgb(255, 20, 100, 230), Color.FromArgb(105, 105, 100, 255) };
gpxBlend.Positions = new float[] { 0.0F, .45F, .55F, 1.0F };
gpxBrush.InterpolationColors = gpxBlend;
// Draw our background
e.Graphics.FillEllipse(gpxBrush, x, y, width, height);
}
// Set the end coordinants for our graphics drawing
width = this.Size.Width-5;
height = this.Size.Height-5;
using (LinearGradientBrush gpxBrush = XGraphics.GradientBrushOrientation(0, x, y, width, height))
{
// Create our color blender object
ColorBlend gpxBlend = null;
gpxBlend = new ColorBlend(2);
gpxBlend.Colors = new Color[] { Color.White, Color.Gray };
gpxBlend.Positions = new float[] { 0.0F, 1.0F };
gpxBrush.InterpolationColors = gpxBlend;
// Draw our background
e.Graphics.FillEllipse(gpxBrush, x+5, y+5, width-5, height-5);
}
width = this.Size.Width / 2;
height = this.Size.Height / 2;
using (LinearGradientBrush gpxBrush = XGraphics.GradientBrushOrientation(0, x, y, width, height))
{
// Create our color blender object
ColorBlend gpxBlend = null;
gpxBlend = new ColorBlend(2);
gpxBlend.Colors = new Color[] { Color.White, Color.Gray };
gpxBlend.Positions = new float[] { 0.0F, 1.0F };
gpxBrush.InterpolationColors = gpxBlend;
// Draw our background
e.Graphics.FillEllipse(gpxBrush, x + width / 2, y + height / 2, width, height);
}
width = (this.Size.Width / 2) - 5;
height = (this.Size.Height / 2) - 5;
using (LinearGradientBrush gpxBrush = XGraphics.GradientBrushOrientation(0, x, y, width-5, height-5))
{
// Create our color blender object
ColorBlend gpxBlend = null;
gpxBlend = new ColorBlend(4);
gpxBlend.Colors = new Color[] { Color.FromArgb(255, 0, 100, 255), Color.FromArgb(205, 255, 240, 240),
Color.FromArgb(255, 20, 100, 230), Color.FromArgb(105, 105, 100, 255) };
gpxBlend.Positions = new float[] { 0.0F, .45F, .55F, 1.0F };
gpxBrush.InterpolationColors = gpxBlend;
// Draw our background
e.Graphics.FillEllipse(gpxBrush, (x + width / 2) +7, (y + height / 2) + 7, width - 5, height - 5);
}
}
As you can see, there is no border now and the edges are transparent. Just make sure to add a button to exit the application since there isn't an 'X' option anymore! ;)
Hope this helps you somewhat!

Related

How to avoid visual artifacts of colored border of zoomable UserControl with rounded corners?

I have a Form which contains:
a TrackBar (minimum = 1, maximum = 200, represents zoom percent);
a UserControl with BorderStyle = BorderStyle.None.
Relevant code
Form1
From designer code
trackBar1.Value = 100;
BackColor = Color.Gray;
From code-behind
private void trackBar1_Scroll(object sender, EventArgs e)
{
userControl11.SetZoomFactor(trackBar1.Value / 100F);
}
UserControl1
internal float MyBaseWidth;
public UserControl1()
{
InitializeComponent();
MyBaseWidth = Width;
SetZoomFactor(1);
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
Pen p = new Pen(Color.Yellow);
e.Graphics.DrawPath(p, GraphicsPathWithBorder);
}
internal GraphicsPath GraphicsPathWithBorder;
internal void SetZoomFactor(float z)
{
Width = (int)(MyBaseWidth * z);
GraphicsPathWithBorder = RoundedCornerRectangle(ClientRectangle);
Region = new Region(GraphicsPathWithBorder);
}
internal static GraphicsPath RoundedCornerRectangle(Rectangle r)
{
GraphicsPath path = new GraphicsPath();
float size = 10 * 2F;
path.StartFigure();
path.AddArc(r.X, r.Y,
size, size, 180, 90);
path.AddArc((r.X + (r.Width - size)), r.Y,
size, size, 270, 90);
path.AddArc((r.X + (r.Width - size)), (r.Y + (r.Height - size)),
size, size, 0, 90);
path.AddArc(r.X, (r.Y + (r.Height - size)),
size, size, 90, 90);
path.CloseFigure();
return path;
}
Initial screenshot
Screenshot after using the trackbar
The right side of the yellow border becomes invisible after zooming out, and when zooming in there are multiple yellow borders on the right side.
Update:
The answer Works, but there is a part of the control that goes beyond the border. Screenshot for top-right corner, for curveSize = 20:
and for curveSize = 24:
I suggest a slightly different method to draw the Border and the content of the User Control that should also cure the artifacts generated when the control is redrawn.
When you create a Region for a Control and then you paint the Region as it is, the outer borders of the painting are not anti-aliased: the aliased pixels fall outside the Region. The same effect of course is applied when a border is painted around the bounds of the Region.
Here, I apply a Scale Matrix and a Translate Matrix that scale and move the bounds of the Region on the inside of the outer Region that defines the control's bounds.
The size of the scale and the translate transformations are determined by the Pen size.
More information on the Matrix usage here: Flip the GraphicsPath
In this case, when the borders are painted, the outer, anti-aliased, section of the border is inside the Region bounds and the anti-aliasing is preserved.
The background color of the Control is set to Color.Transparent (a User Control supports color transparency on its own).
I've also added a couple of (non decorated) properties that allow to define the inner Color (the Control's BackColor) and Size and Color of the Border. The rest is more or less what it was before.
Sample results:
using System.Drawing;
using System.Drawing.Drawing2D;
public partial class RoundControl : UserControl
{
private GraphicsPath GraphicsPathWithBorder;
private float MyBaseWidth;
private float m_PenSize = 2f;
private Color m_BorderColor = Color.Yellow;
private Color m_FillColor = Color.Green;
public RoundControl()
{
ResizeRedraw = true;
InitializeComponent();
MyBaseWidth = Width;
}
public float BorderSize
{
get => m_PenSize;
set {
m_PenSize = value;
Invalidate();
}
}
public Color BorderColor
{
get => m_BorderColor;
set {
m_BorderColor = value;
Invalidate();
}
}
public Color FillColor
{
get => m_FillColor;
set {
m_FillColor = value;
Invalidate();
}
}
protected override void OnLayout(LayoutEventArgs e) {
UpdateRegion();
base.OnLayout(e);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
RectangleF rect = GraphicsPathWithBorder.GetBounds();
float scaleX = 1 - ((m_PenSize + 1) / rect.Width);
float scaleY = 1 - ((m_PenSize + 1) / rect.Height);
using (Pen pen = new Pen(m_BorderColor, m_PenSize))
using (Brush brush = new SolidBrush(m_FillColor))
using (Matrix mx = new Matrix(scaleX, 0, 0, scaleY, pen.Width / 2, pen.Width / 2))
{
e.Graphics.Transform = mx;
e.Graphics.FillPath(brush, GraphicsPathWithBorder);
e.Graphics.DrawPath(pen, GraphicsPathWithBorder);
}
base.OnPaint(e);
}
internal void SetZoomFactor(float z) {
int newWidth = (int)(MyBaseWidth * z);
if (newWidth <= (30 + m_PenSize * 2)) return;
Width = newWidth;
UpdateRegion();
}
private void UpdateRegion() {
GraphicsPathWithBorder = RoundedCornerRectangle(ClientRectangle);
Region = new Region(GraphicsPathWithBorder);
Invalidate();
}
private GraphicsPath RoundedCornerRectangle(Rectangle r)
{
GraphicsPath path = new GraphicsPath();
// Fixed curve size since we only scale on X-dimension
// Otherwise, adjust also considering the height
float curveSize = 10 * 2.4F;
path.StartFigure();
path.AddArc(r.X, r.Y, curveSize, curveSize, 180, 90);
path.AddArc(r.Right - curveSize, r.Y, curveSize, curveSize, 270, 90);
path.AddArc(r.Right - curveSize, r.Bottom - curveSize, curveSize, curveSize, 0, 90);
path.AddArc(r.X, r.Bottom - curveSize, curveSize, curveSize, 90, 90);
path.CloseFigure();
return path;
}
}

Fill Panel with gradient in three colors

I'm working on project and I have to do kind of color picker using C#.
So I've decided that it will be a Panel with this background in Win Forms App.
Background should have gradient with three colors in rgb: red (0 - 255), blue (0 - 255) and green = 0.
But I can't find any information about what I should use for this.
I tried to write some code and here is what I've done.
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
panel1.Paint += new PaintEventHandler(panel1_Paint);
panel1.Refresh();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
Point startPoint = new Point(0, 0);
Point endPoint = new Point(150, 150);
LinearGradientBrush lgb =
new LinearGradientBrush(startPoint, endPoint, Color.FromArgb(255, 255, 0, 0), Color.FromArgb(255, 255, 255, 0));
Graphics g = e.Graphics;
g.FillRectangle(lgb, 0, 0, 150, 150);
// g.DrawLine(new Pen(Color.Yellow, 1.5f), startPoint, endPoint);
}
}
}
And now I have panel with this gradient
What I should use to get gradient at first picture?
And second question: What should I do to get the pixel color after clicking on this background?
Here is an example for using a multicolor LinearGradientBrush in the Paint event:
LinearGradientBrush linearGradientBrush =
new LinearGradientBrush(panel4.ClientRectangle, Color.Red, Color.Yellow, 45);
ColorBlend cblend = new ColorBlend(3);
cblend.Colors = new Color[3] { Color.Red, Color.Yellow, Color.Green };
cblend.Positions = new float[3] { 0f, 0.5f, 1f };
linearGradientBrush.InterpolationColors = cblend;
e.Graphics.FillRectangle(linearGradientBrush, panel4.ClientRectangle);
You can freely vary the number of colors, the angle or the spread of the stop points. Just make sure you always have the same number of colors and stop points and let them start at 0 and end at 1.
The colors in the constructor are ignored, btw..
To get a clicked color you can code the MouseClick:
Color clickedColor = Color.Empty;
private void panel_MouseClick(object sender, MouseEventArgs e)
{
using (Bitmap bmp = new Bitmap( panel.ClientSize.Width, panel4.ClientSize.Height))
{
panel.DrawToBitmap(bmp,panel.ClientRectangle);
clickedColor = bmp.GetPixel(e.X, e.Y);
}
}
If you want to catch many clicks it may be better to keep the Bitmap in a class level variable instead of recreating it all the time.. Setting it as the Panel's BackgroundImage, as Kala's answer assumes may also be a good option..
This should answer the question in the title. However your first image doesn't show a gradient with three colors. It shows a 2D gradient with four colors. For such a more expensive coloring method you should put the colors in a Bitmap and set it as the Panel's BackgroundImage..
Update1 Here is a piece of code that creates a 2D Gradient:
Bitmap Gradient2D(Rectangle r, Color c1, Color c2, Color c3, Color c4)
{
Bitmap bmp = new Bitmap(r.Width, r.Height);
float delta12R = 1f * (c2.R - c1.R) / r.Height;
float delta12G = 1f * (c2.G - c1.G) / r.Height;
float delta12B = 1f * (c2.B - c1.B) / r.Height;
float delta34R = 1f * (c4.R - c3.R) / r.Height;
float delta34G = 1f * (c4.G - c3.G) / r.Height;
float delta34B = 1f * (c4.B - c3.B) / r.Height;
using (Graphics G = Graphics.FromImage(bmp) )
for (int y = 0; y < r.Height; y++)
{
Color c12 = Color.FromArgb(255, c1.R + (int)(y * delta12R),
c1.G + (int)(y * delta12G), c1.B + (int)(y * delta12B));
Color c34 = Color.FromArgb(255, c3.R + (int)(y * delta34R),
c3.G + (int)(y * delta34G), c3.B + (int)(y * delta34B));
using ( LinearGradientBrush lgBrush = new LinearGradientBrush(
new Rectangle(0,y,r.Width,1), c12, c34, 0f) )
{ G.FillRectangle(lgBrush, 0, y, r.Width, 1); }
}
return bmp;
}
Here is how you use it:
public Form1()
{
InitializeComponent();
panel.BackgroundImage = Gradient2D(panel.ClientRectangle,
Color.Black, Color.FromArgb(255, 0, 255, 0), Color.Red, Color.Yellow);
}
This uses simple LinearGradientBrushes without an extra colors list going down over the height of the Panel.
Note that Color.Green is a rather dark hue, so I used FromRgb for a brighter green. If your Panel is greater than 256 pixels you may want to optimze by filling larger stripes; if it is vertical you may want to change the loop to go over x instead of y..
Here is the result:
To pick with a click you now simply read out the color from the BackgroundImage:
private void panel_MouseClick(object sender, MouseEventArgs e)
{
clickedColor = ((Bitmap)panel.BackgroundImage).GetPixel(e.X, e.Y);
}
Update 2:
When looking over this MSDN page we can find that there actually is a built-in tool to create 2D gradients.
It is the PathGradientBrush
Here is an example..:
.. and the code:
Bitmap Gradient2D(Rectangle r, Color c1, Color c2, Color c3, Color c4)
{
List<Color> colors = new List<Color> { c1, c3, c4, c2 };
Bitmap bmp = new Bitmap(r.Width, r.Height);
using (Graphics g = Graphics.FromImage(bmp))
for (int y = 0; y < r.Height; y++)
{
using (PathGradientBrush pgb = new PathGradientBrush(getCorners(r).ToArray()))
{
pgb.CenterColor = medianColor(colors);
pgb.SurroundColors = colors.ToArray();
g.FillRectangle(pgb, 0, y, r.Width, 1);
}
}
return bmp;
}
This uses two simple helper functions. One returns the corner points of a rectangle:
public List<PointF> getCorners(RectangleF r)
{
return new List<PointF>() { r.Location, new PointF(r.Right, r.Top),
new PointF(r.Right, r.Bottom), new PointF(r.Left, r.Bottom)};
}
The other calculates a median color from a List<Color>. This is used as the CenterColor..:
public static Color medianColor(List<Color> cols)
{
int c = cols.Count;
return Color.FromArgb(cols.Sum(x => x.A) / c, cols.Sum(x => x.R) / c,
cols.Sum(x => x.G) / c, cols.Sum(x => x.B) / c);
}
The result pretty much identical to the one from using stripes of LinearGradientBrushes. It is simpler and should perform a bit better; it is what I would recommend obviously..
Note the changed order of the colors (or corners)! The SurroundColors apply to opposing corners of the rectangle..
Note:
When studying that page one can find that there actually are four different uses for that brush.
They differ in how to set it up (GraphicsPath or Point[]), which color collections to fill (SurroundColors or InterpolationColors.Colors) and how to call it (with a shape or a path). And the results also differ a lot.
Also note that only three results of the four ways are shown, although code for all four is provided!..
From the mouse click event argument e, you can get the Point with the exact co-ordinates of the click:
Point clickPoint = e.GetPosition(backgroundControlWithImg);
Then get the colour of the image at that position using something like:
System.Drawing.Image image = backgroundControl.BackgroundImage;
Bitmap _bitmap = new Bitmap(image);
Color _color = bitmap.GetPixel(Point.x, Point.y);
Something like that. What are you using for the Color Picker, WPF or?

Draw a polyline with a linear gradient along it's stroke width in GDI+

Is it possible to draw a polyline that has a linear gradient along it's stroke width? That is, if you have a gradient with black on 0 and 100% and white 50%, the black will always be on the edge of the line and the white in the middle, regardless of the angle. Think of it as some sort of 3D pipes. Of course, the line will have a stroke width of at least 10px. All the questions here ask how to fill a line between it's ends. I'm definitely not interested in that. I'm working in C# using GDI+, can be any .NET version.
I think this is what you want:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode=SmoothingMode.AntiAlias;
DrawPipe(e.Graphics, 10f, new PointF(10, 10), new PointF(250, 80), Color.White, Color.Black);
DrawPipe(e.Graphics, 10f, new PointF(15, 60), new PointF(280, 120), Color.BlueViolet, Color.Black);
}
private void DrawPipe(Graphics g, float width, PointF p1, PointF p2, Color mid_color, Color edge_color)
{
SizeF along=new SizeF(p2.X-p1.X, p2.Y-p1.Y);
float mag=(float)Math.Sqrt(along.Width*along.Width+along.Height*along.Height);
along=new SizeF(along.Width/mag, along.Height/mag);
SizeF perp=new SizeF(-along.Height, along.Width);
PointF p1L=new PointF(p1.X+width/2*perp.Width, p1.Y+width/2*perp.Height);
PointF p1R=new PointF(p1.X-width/2*perp.Width, p1.Y-width/2*perp.Height);
PointF p2L=new PointF(p2.X+width/2*perp.Width, p2.Y+width/2*perp.Height);
PointF p2R=new PointF(p2.X-width/2*perp.Width, p2.Y-width/2*perp.Height);
GraphicsPath gp=new GraphicsPath();
gp.AddLines(new PointF[] { p1L, p2L, p2R, p1R});
gp.CloseFigure();
Region region=new Region(gp);
using(LinearGradientBrush brush=new LinearGradientBrush(
p1L, p1R, Color.Black, Color.Black))
{
ColorBlend color_blend=new ColorBlend();
color_blend.Colors=new Color[] { edge_color, mid_color, edge_color };
color_blend.Positions=new float[] { 0f, 0.5f, 1f };
brush.InterpolationColors=color_blend;
g.FillRegion(brush, region);
}
}
}
Edit 1
An alternative is to use a PathGradientBrush
GraphicsPath gp = new GraphicsPath();
gp.AddLines(new PointF[] { p1, p1L, p2L, p2, p2R, p1R });
gp.CloseFigure();
Region region = new Region(gp);
using (PathGradientBrush brush = new PathGradientBrush(gp))
{
brush.CenterColor = mid_color;
brush.SurroundColors = new Color[]
{
mid_color, edge_color,edge_color,mid_color,edge_color,edge_color
};
g.FillRegion(brush, region);
}
Edit 2
To make the edges smoother use some alpha transparency:
using(LinearGradientBrush brush=new LinearGradientBrush(
p1L, p1R, Color.Black, Color.Black))
{
ColorBlend color_blend=new ColorBlend();
color_blend.Colors=new Color[] {
Color.FromArgb(0, edge_color), edge_color, mid_color,
edge_color, Color.FromArgb(0, edge_color) };
color_blend.Positions=new float[] { 0f, 0.1f, 0.5f, 0.9f, 1f };
brush.InterpolationColors=color_blend;
g.FillRegion(brush, region);
}
Edit 3
With some artifacts multiple lines are drawing, by rendering circles between then first and then the lines
private void DrawPipes(Graphics g, float width, PointF[] points, Color mid_color, Color edge_color)
{
for (int i = 0; i < points.Length; i++)
{
using (GraphicsPath gp = new GraphicsPath())
{
gp.AddEllipse(points[i].X - width / 2, points[i].Y - width / 2, width, width);
using (PathGradientBrush brush = new PathGradientBrush(gp))
{
brush.CenterColor = mid_color;
brush.SurroundColors = new Color[] { edge_color };
brush.CenterPoint = points[i];
g.FillPath(brush, gp);
}
}
if (i > 0)
{
DrawPipe(g, width, points[i - 1], points[i], mid_color, edge_color);
}
}
}

Animated bar in progress bar winform

I'm writing an extended progress bar control at present, 100% open source and I've created some basic styles with gradients and solid colours.
One of the options I wanted to add was animation to the bar, prety much like the windows 7 and vista green progress bar. So I need to add a moving "Glow" to the % bar, however my attempt at this looks terrible.
My method is to draw an ellipse with set size and move it's x position until it reaches the end were the animation starts again.
First of does anyone have nay links or code to help me achieve the current windows 7 glow effect using GDI or some similar method?
I have several other animations that will also be added the the bar hence the GDI.
private void renderAnimation(PaintEventArgs e)
{
if (this.AnimType == animoptions.Halo)
{
Rectangle rec = e.ClipRectangle;
Rectangle glow = new Rectangle();
//SolidBrush brush = new SolidBrush(Color.FromArgb(100, Color.White));
//int offset = (int)(rec.Width * ((double)Value / Maximum)) - 4;
int offset = (int)(rec.Width / Maximum) * Value;
if (this.animxoffset > offset)
{
this.animxoffset = 0;
}
glow.Height = rec.Height - 4;
if (this.animxoffset + glow.X > offset)
{
glow.Width = offset - (this.animxoffset + 50);
}
else
{
glow.Width = 50;
}
glow.X = this.animxoffset;
LinearGradientBrush brush = new LinearGradientBrush(glow, Color.FromArgb(0, Color.White), Color.FromArgb(100, Color.White), LinearGradientMode.Horizontal);
e.Graphics.FillEllipse(brush, this.animxoffset, 2, glow.Width, glow.Height);
brush.Dispose();
string temp = offset.ToString();
e.Graphics.DrawString(temp + " : " + glow.X.ToString(), DefaultFont, Brushes.Black, 2, 2);
animTimer = new System.Timers.Timer();
animTimer.Interval = 10;
animTimer.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
animTimer.Start();
}
}
void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this.animTimer.Stop();
this.animxoffset += 2;
Invalidate();
}
This is just an example glow iterating through a pen array.
You could also use a transparent image (although it could have a performance impact).
Pen[] gradient = { new Pen(Color.FromArgb(255, 200, 200, 255)), new Pen(Color.FromArgb(150, 200, 200, 255)), new Pen(Color.FromArgb(100, 200, 200, 255)) };
int x = 20;
int y = 20;
int sizex = 200;
int sizey = 10;
int value = 25;
//draw progress bar basic outline (position - 1 to compensate for the outline)
e.Graphics.DrawRectangle(Pens.Black, new Rectangle(x-1, y-1, sizex, sizey));
//draw the percentage done
e.Graphics.FillRectangle(Brushes.AliceBlue, new Rectangle(x, y, (sizex/100)*value, sizey));
//to add the glow effect just add lines around the area you want to glow.
for (int i = 0; i < gradient.Length; i++)
{
e.Graphics.DrawRectangle(gradient[i], new Rectangle(x - (i + 1), y - (i + 1), (sizex / 100) * value + (2 * i), sizey + (2 * i)));
}

Clicking a control and causing it to shade

In windows when you click on an icon on your desktop, the icon darkens with a shade that is based on your windows theme that is currently used.
I have a custom control that displays an image. I would like to have the same functionality as the windows icon click. How do I obtain the same result in WinForms by selecting my custom control?
Windows implements alpha-blending for selected icons since Windows XP. If you want to achieve similar look you must draw your image with alpha blending:
public static void DrawBlendImage(Graphics canvas, Image source, Color blendColor, float blendLevel, int x, int y)
{
Rectangle SourceBounds = new Rectangle(x, y, source.Width, source.Height);
ColorMatrix MaskMatrix = new ColorMatrix();
MaskMatrix.Matrix00 = 0f;
MaskMatrix.Matrix11 = 0f;
MaskMatrix.Matrix22 = 0f;
MaskMatrix.Matrix40 = (float)blendColor.R / byte.MaxValue;
MaskMatrix.Matrix41 = (float)blendColor.G / byte.MaxValue;
MaskMatrix.Matrix42 = (float)blendColor.B / byte.MaxValue;
ImageAttributes MaskAttributes = new ImageAttributes();
MaskAttributes.SetColorMatrix(MaskMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
ColorMatrix TransparentMatrix = new ColorMatrix();
TransparentMatrix.Matrix33 = blendLevel;
ImageAttributes TransparentAttributes = new ImageAttributes();
TransparentAttributes.SetColorMatrix(TransparentMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
canvas.DrawImage(source, SourceBounds, 0, 0, source.Width, source.Height, GraphicsUnit.Pixel, MaskAttributes);
canvas.DrawImage(source, SourceBounds, 0, 0, source.Width, source.Height, GraphicsUnit.Pixel, TransparentAttributes);
}
In your case you can use SystemColors.Highlight as blendColor.
You can use System.Drawing.KnownColor to get the proper colors for the user's theme.
Right now I'm using the following code... if anyone has something better, I'll be glad to change it!
private void drawAndShadeTheImage(Graphics g)
{
//if the image is null then there is nothing to do.
if (Image != null)
{
Bitmap bitMap = new Bitmap(Image);
//if this control is selected, shade the image to allow the user to
//visual identify what is selected.
if (ContainsFocus)
{
//The delta is the percentage of change in color shading of
//the image.
int delta = 70;
//zero is the lowest value (0 - 255) that can be represented by
//a color component.
int zero = 0;
//Get each pixel in the image and shade it.
for (int y = 0; y < bitMap.Height; y++)
{
for (int x = 0; x < bitMap.Width; x++)
{
Color oColor = bitMap.GetPixel(x, y);
//Lime is the background color on the image and should
//always be transparent, if this check is removed the
//background will be displayed.
if (oColor.ToArgb() != Color.Lime.ToArgb())
{
int oR = oColor.R - delta < zero ? zero :
oColor.R - delta;
int oG = oColor.G - delta < zero ? zero :
oColor.G - delta;
int oB = oColor.B - delta < zero ? zero :
oColor.B - delta;
int oA = oColor.A - delta < zero ? zero :
oColor.A - delta;
Color nColor = Color.FromArgb(oA, oR, oG, oB);
bitMap.SetPixel(x, y, nColor);
}
}
}
}
//Make the background of the image transparent.
bitMap.MakeTransparent();
g.DrawImage(bitMap, this.ClientRectangle);
}
}

Categories

Resources