C# progress bar bad render - c#

I created custom progress bar with image but i have problem. From 50% on progress bar are showing spaces.
Progress Bar here: http://i.stack.imgur.com/d686B.png
There is control library code:
public partial class UserControl1: UserControl
{
public UserControl1() : base()
{
InitializeComponent();
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
}
private void UserControl1_Load(object sender, EventArgs e)
{
}
bool _revealImage = true;
int _maximum = 100;
int _value = 0;
Image _progressbarImage = Properties.Resources.progress;
Color _progressbarColor = Color.Transparent;
protected override void OnResize(EventArgs e)
{
// Invalidate the control to get a repaint.
this.Invalidate();
}
protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
Graphics g = e.Graphics;
Rectangle r = this.ClientRectangle;
ControlPaint.DrawBorder(g, r, Color.Transparent, ButtonBorderStyle.Solid);
float percent = (float)_value / (float)(_maximum);
//r.Inflate(-1, -1);
r.Width = (int)((float)r.Width * percent);
if ((r.Width < 1))
{
return;
}
if (_progressbarImage == null)
{
using (SolidBrush b = new SolidBrush(_progressbarColor))
{
g.FillRectangle(b, r);
b.Dispose();
}
}
else
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
if (_revealImage)
{
g.DrawImage(_progressbarImage, r, r, GraphicsUnit.Pixel);
}
else
{
g.DrawImage(_progressbarImage, r);
}
}
g.Dispose();
}
public int Maximum
{
get
{
return _maximum;
}
set
{
_maximum = value;
this.Invalidate();
}
}
public int Value
{
get
{
return _value;
}
set
{
// _value = value;
int oldValue = _value;
// Make sure that the value does not stray outside the valid range.
if (value < 0)
{
_value = 0;
}
else if (value > Maximum)
{
_value = Maximum;
}
else
{
_value = value;
}
// Invalidate only the changed area.
float percent;
Rectangle newValueRect = this.ClientRectangle;
Rectangle oldValueRect = this.ClientRectangle;
// Use a new value to calculate the rectangle for progress.
percent = (float)(_value - 0) / (float)(Maximum - 0);
newValueRect.Width = (int)((float)newValueRect.Width * percent);
// Use an old value to calculate the rectangle for progress.
percent = (float)(oldValue - 0) / (float)(Maximum - 0);
oldValueRect.Width = (int)((float)oldValueRect.Width * percent);
Rectangle updateRect = new Rectangle();
// Find only the part of the screen that must be updated.
if (newValueRect.Width > oldValueRect.Width)
{
updateRect.X = oldValueRect.Size.Width;
updateRect.Width = newValueRect.Width - oldValueRect.Width;
}
else
{
updateRect.X = newValueRect.Size.Width;
updateRect.Width = oldValueRect.Width - newValueRect.Width;
}
updateRect.Height = this.Height;
// Invalidate the intersection region only.
this.Invalidate(updateRect);
}
}
public Image ProgressbarImage
{
get
{
return _progressbarImage;
}
set
{
_progressbarImage = value;
this.Invalidate();
}
}
public Color ProgressbarColor
{
get
{
return _progressbarColor;
}
set
{
_progressbarColor = value;
this.Invalidate();
}
}
public bool RevealImage
{
get
{
return _revealImage;
}
set
{
_revealImage = value;
this.Invalidate();
}
}
}
Thank you for help.

Related

Make a CustomListBox to add BorderColor then can't use ListBox normal properties/methods

I'm trying to change the border color of a ListBox.
I made this custom control where i have a function that makes the border by drawing.
After had it working, noticed that can't use ListBox.Items anymore, methods such as .Add() or .Clear().
Code of the Custom ListBox:
class CustomListBox : UserControl
{
//Fields
private Color borderColor = Color.MediumSlateBlue;
private int borderSize = 1;
//Items
private ListBox Listb;
//Properties
[Category("Custom")]
public Color BorderColor
{
get { return borderColor; }
set
{
borderColor = value;
}
}
[Category("Custom")]
public int BorderSize
{
get { return borderSize; }
set
{
borderSize = value;
this.Padding = new Padding(borderSize);//Border Size
AdjustListBoxDimensions();
}
}
public CustomListBox()
{
Listb = new ListBox();
this.SuspendLayout();
// ListBox
Listb.BorderStyle = BorderStyle.None;
Listb.DrawMode = DrawMode.OwnerDrawFixed;
Listb.ForeColor = Color.FromArgb(((int)(((byte)(249)))), ((int)(((byte)(249)))), ((int)(((byte)(249)))));
Listb.FormattingEnabled = true;
Listb.ItemHeight = 24;
Listb.Location = new Point(567, 64);
Listb.Name = "CustomListBox";
Listb.Size = new Size(235, 936);
Listb.DrawItem += new DrawItemEventHandler(Listb_DrawItem);
this.MinimumSize = new Size(200, 30);
this.Size = new Size(200, 30);
this.Padding = new Padding(borderSize);//Border Size
this.Font = new Font(this.Font.Name, 12F);
this.ResumeLayout();
AdjustListBoxDimensions();
}
// Highlight event
private void Listb_DrawItem(object sender, DrawItemEventArgs e)
{
Color backgroundColor = Color.FromArgb(50, 50, 50);
Color horizontalColor = Color.FromArgb(100, 100, 100);
if (e.Index >= 0)
{
SolidBrush sb = new SolidBrush(((e.State & DrawItemState.Selected) == DrawItemState.Selected) ? horizontalColor : backgroundColor);
e.Graphics.FillRectangle(sb, e.Bounds);
string text = Listb.Items[e.Index].ToString();
SolidBrush tb = new SolidBrush(e.ForeColor);
e.Graphics.DrawString(text, e.Font, tb, Listb.GetItemRectangle(e.Index).Location);
}
}
//Adjust Dimension (Still in test)
private void AdjustListBoxDimensions()
{
Listb.Location = new Point()
{
X = this.Width - this.Padding.Right - Listb.Width,
Y = Listb.Height
};
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics graph = e.Graphics;
//Draw border
using (Pen penBorder = new Pen(borderColor, borderSize))
{
penBorder.Alignment = PenAlignment.Inset;
graph.DrawRectangle(penBorder, 0, 0, this.Width - 0.5F, this.Height - 0.5F);
}
}
}
My problem is that i can't use the ListBox properties/methods, is there a way to inherit them?
Since you've made your own control, you have to make your own properties and methods, calling Listbox's methods and getters/setters
something like this:
public void Add(object item)
{
this.Listb.Items.Add(item);
}
public ObjectCollection ListItems
{
get
{
return this.Listb.Items;
}
set
{
this.Listb.Items.AddRange(value);
}
}
//etc...
public void Add(object item)
{
this.Listb.BeginUpdate();
this.Listb.Items.Add(item);
this.Listb.EndUpdate();
}
public void Clear()
{
this.Listb.BeginUpdate();
this.Listb.Items.Clear();
this.Listb.EndUpdate();
}
public int SelectedIndex()
{
return this.Listb.SelectedIndex;
}
public object Item(int index)
{
return this.Listb.Items[index];
}
Add to code:
Dock=Fill
This.control.add(listb)

Can't save forms with my custom userControl in it

After I created a userControl and established it in a Windows form, this form could no longer be saved. When I press Ctrl + S or the Save button nothing happens, the small * on the form file name suggests that it was not saved. Also, my form contains a property for a color. When I change this, the color doesn't change and the property window doesn't seem to respond anymore.
Code of custom userControl
namespace FlowGui
{
public partial class FlowProgressBar: UserControl
{
// Public Variables with Setters
private int maxValue;
[Bindable(true), Category("Behavior")]
public int Maximum
{
get
{
return maxValue;
}
set
{
maxValue = value;
DrawBar();
}
}
private int minValue;
[Bindable(true), Category("Behavior")]
public int Minimum
{
get
{
return minValue;
}
set
{
minValue = value;
DrawBar();
}
}
private int currentValue;
[Bindable(true), Category("Behavior")]
public int Value
{
get
{
return currentValue;
}
set
{
currentValue = value;
DrawBar();
}
}
private Color barColor;
[Bindable(true), Category("Appearance")]
public Color BarColor
{
get
{
return barColor;
}
set
{
barColor = value;
CreateBarImage();
DrawBar();
}
}
// private Values for Drawing
private Image canvas;
private Graphics gfx;
private Bitmap barImage;
public FlowProgressBar()
{
InitializeComponent();
}
// Load
private void FlowProgressBar_Load(object sender, EventArgs e)
{
maxValue = 100;
minValue = 0;
currentValue = 0;
barColor = Color.LightBlue;
// Init Graphic
InitGraphics();
CreateBarImage();
DrawBar();
}
private void CreateBarImage()
{
barImage = new Bitmap(10, 50);
Bitmap currentBarImage = Properties.Resources.BarImage_Basic;
for(int x=0; x<10; x++)
{
for (int y = 0; y < 50; y++)
{
Color barPreColor = currentBarImage.GetPixel(x, y);
int r = barPreColor.R * barColor.R / 255;
int g = barPreColor.G * barColor.G / 255;
int b = barPreColor.B * barColor.B / 255;
Color pixelColor = Color.FromArgb(r,g,b);
currentBarImage.SetPixel(x, y, pixelColor);
}
}
}
private void InitGraphics()
{
canvas = new Bitmap(pictureBoxBar.Width, pictureBoxBar.Height);
gfx = Graphics.FromImage(canvas);
}
private void DrawBar()
{
int barWidth = pictureBoxBar.Width;
int barHeight = pictureBoxBar.Height;
Image bgImage = Properties.Resources.BarBG_Raised_Grey;
gfx.DrawImage(bgImage,-200,0,barWidth+400,barHeight);
gfx.DrawImage(barImage, 0, 0, 100, barHeight);
pictureBoxBar.Image = canvas;
}
// Behaviour
private void FlowProgressBar_SizeChanged(object sender, EventArgs e)
{
InitGraphics();
DrawBar();
}
private void pictureBoxBar_Paint(object sender, PaintEventArgs e)
{
InitGraphics();
DrawBar();
}
}
}
My first thought was that it could be because the userControll is in another project and only linked. But even after I implemented the userControll in the main project, my described problems occurred. So I undo this.
I have no idea what I'm doing wrong. Thank you very much for your help.
Solved!
The problem was the pictureBoxBar_Paint() event. After I removed it from the userControl everything runs.

How can make adorner below of controlcontent in canvas?

I use this program: https://www.codeproject.com/Articles/24681/WPF-Diagram-Designer-Part-4 and change it a bit to make a new program to draw graph(mathmatical graph) but not completed.
for each DesignerItem I add a Text as Adorner(TextAdorner class), you can see this at: https://i.stack.imgur.com/VDvGQ.png
but when two or more DesignerItems overlaped all text mixed together, because Adorner is top of all DesignerItems in canvas.
There is a way to make an adorner below of a DesignerItem in canvas?
You can see TextAdorner class below.
class TextAdorner : Adorner
{
VisualCollection _visualChildren;
Path _textGeometry;
TexFormula formula;
TexFormulaParser parser;
public Brush ForeColor
{ get; set; }
public double FontSize
{ get; set; }
public TextAdorner(UIElement adornedElement)
: base(adornedElement)
{
_visualChildren = new VisualCollection(this);
this.Tag = #"v^{b_i}_{c_j}";
parser = new TexFormulaParser();
formula = parser.Parse(this.Tag.ToString());
_textGeometry=new Path();
this.ForeColor = Brushes.Black;
this.FontSize = 32;
_textGeometry.Fill = this.ForeColor;
_textGeometry.Stroke = this.ForeColor;
_textGeometry.StrokeThickness = 1;
_visualChildren.Add(_textGeometry);
this.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
}
protected override Size ArrangeOverride(Size finalSize)
{
double _left;
double _top;
_textGeometry.Data = formula.GetRenderer(TexStyle.Display, this.FontSize, "Times New Roman").RenderToGeometry(0, 0);
switch (this.HorizontalAlignment)
{
case System.Windows.HorizontalAlignment.Left:
{
_left = 0;
break;
}
case System.Windows.HorizontalAlignment.Right:
{
_left = AdornedElement.RenderSize.Width - _textGeometry.RenderedGeometry.Bounds.Width;
break;
}
default:
{
_left = AdornedElement.RenderSize.Width / 2 - _textGeometry.RenderedGeometry.Bounds.Width / 2;
break;
}
}
switch (this.VerticalAlignment)
{
case System.Windows.VerticalAlignment.Top:
{
_top = 0;
break;
}
case System.Windows.VerticalAlignment.Bottom:
{
_top = AdornedElement.RenderSize.Height- _textGeometry.RenderedGeometry.Bounds.Height;
break;
}
default:
{
_top = AdornedElement.RenderSize.Height / 2 - _textGeometry.RenderedGeometry.Bounds.Height/ 2;
break;
}
}
Rect _leftTopRect = new Rect(_left,_top,AdornedElement.RenderSize.Width,AdornedElement.RenderSize.Height);
_textGeometry.Arrange(_leftTopRect);
return finalSize;
}
protected override int VisualChildrenCount
{
get { return _visualChildren.Count; }
}
protected override Visual GetVisualChild(int index)
{
return _visualChildren[index];
}
}

How to put some color on image

I have here the circle image, what I want to do is to put some color in specific position.. For example, when I click the button1, the left side of the circle will be filled by red, and when I click the button2, the right side will be filled by as well, and when I click the button1 again, the color will be removed, and so on...
I've done some research about it, and found out 2 ways to do it. First is, to layover the circle with another image. Second is to draw, and use the Graphics class in C#..
Now, my question is, is there another possible way to do it? What is the best way?
P.S: The purpose of this is for the tooth chart. :)
Here's a Resizable, Clickable, UserControl based on qing`s post. You can click on the regions directly to toggle them, or change them via code.
public partial class ToothChart : UserControl
{
public ToothChart()
{
InitializeComponent();
this.DoubleBuffered = true;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (this.ParentForm != null)
{
this.ParentForm.FormClosing += (s, evt) => { OnHandleDestroyed(new EventArgs()); };
}
}
protected override void OnHandleDestroyed(EventArgs e)
{
base.OnHandleDestroyed(e);
if (this._pathTop != null)
{
this._pathTop.Dispose();
this._pathTop = null;
}
if (this._pathRight != null)
{
this._pathRight.Dispose();
this._pathRight = null;
}
if (this._pathBottom != null)
{
this._pathBottom.Dispose();
this._pathBottom = null;
}
if (this._pathLeft != null)
{
this._pathLeft.Dispose();
this._pathLeft = null;
}
if (this._pathCenter != null)
{
this._pathCenter.Dispose();
this._pathCenter = null;
}
}
private GraphicsPath _pathTop = null;
private GraphicsPath _pathLeft = null;
private GraphicsPath _pathBottom = null;
private GraphicsPath _pathRight = null;
private GraphicsPath _pathCenter = null;
private bool _TopRegion = false;
public bool TopRegion
{
get
{
return _TopRegion;
}
set
{
if (_TopRegion != value)
{
_TopRegion = value;
this.Invalidate();
}
}
}
private bool _RightRegion = false;
public bool RightRegion
{
get
{
return _RightRegion;
}
set
{
if (_RightRegion != value)
{
_RightRegion = value;
this.Invalidate();
}
}
}
private bool _BottomRegion = false;
public bool BottomRegion
{
get
{
return _BottomRegion;
}
set
{
if (_BottomRegion != value)
{
_BottomRegion = value;
this.Invalidate();
}
}
}
private bool _LeftRegion = false;
public bool LeftRegion
{
get
{
return _LeftRegion;
}
set
{
if (_LeftRegion != value)
{
_LeftRegion = value;
this.Invalidate();
}
}
}
private bool _CenterRegion = false;
public bool CenterRegion
{
get
{
return _CenterRegion;
}
set
{
if (_CenterRegion != value)
{
_CenterRegion = value;
this.Invalidate();
}
}
}
protected override void OnSizeChanged(EventArgs e)
{
base.OnSizeChanged(e);
if (this.IsHandleCreated && this._pathTop != null)
{
this.UpdateRegions();
}
}
private void UpdateRegions()
{
int diameterBig = Math.Min(this.Width, this.Height) - 10;
int diameterSmall = Math.Min(this.Width, this.Height) / 3;
if (diameterBig > 0 && diameterSmall > 0)
{
Point _centerPoint = new Point(this.Width / 2, this.Height / 2);
Rectangle rectangle = new Rectangle(_centerPoint.X - diameterBig / 2, _centerPoint.Y - diameterBig / 2, diameterBig, diameterBig);
Rectangle rectangle2 = new Rectangle(_centerPoint.X - diameterSmall / 2, _centerPoint.Y - diameterSmall / 2, diameterSmall, diameterSmall);
_pathTop.Reset();
_pathTop.AddArc(rectangle, 225, 90);
_pathTop.AddArc(rectangle2, -45, -90);
_pathLeft.Reset();
_pathLeft.AddArc(rectangle, 135, 90);
_pathLeft.AddArc(rectangle2, -135, -90);
_pathBottom.Reset();
_pathBottom.AddArc(rectangle, 45, 90);
_pathBottom.AddArc(rectangle2, -225, -90);
_pathRight.Reset();
_pathRight.AddArc(rectangle, -45, 90);
_pathRight.AddArc(rectangle2, -315, -90);
_pathCenter.Reset();
_pathCenter.AddEllipse(rectangle2);
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
if (this.IsHandleCreated)
{
if (this._pathTop == null)
{
this._pathTop = new GraphicsPath();
this._pathRight = new GraphicsPath();
this._pathBottom = new GraphicsPath();
this._pathLeft = new GraphicsPath();
this._pathCenter = new GraphicsPath();
this.UpdateRegions();
}
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
if (this.TopRegion)
{
e.Graphics.FillPath(Brushes.Blue, _pathTop);
}
e.Graphics.DrawPath(Pens.Black, _pathTop);
if (this.RightRegion)
{
e.Graphics.FillPath(Brushes.DarkRed, _pathRight);
}
e.Graphics.DrawPath(Pens.Black, _pathRight);
if (this.BottomRegion)
{
e.Graphics.FillPath(Brushes.Teal, _pathBottom);
}
e.Graphics.DrawPath(Pens.Black, _pathBottom);
if (this.LeftRegion)
{
e.Graphics.FillPath(Brushes.Yellow, _pathLeft);
}
e.Graphics.DrawPath(Pens.Black, _pathLeft);
if (this.CenterRegion)
{
e.Graphics.FillPath(Brushes.LightGreen, _pathCenter);
}
e.Graphics.DrawPath(Pens.Black, _pathCenter);
}
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
Point p = new Point(e.X, e.Y);
if (this._pathTop.IsVisible(p))
{
this.TopRegion = !this.TopRegion;
}
else if (this._pathRight.IsVisible(p))
{
this.RightRegion = !this.RightRegion;
}
else if (this._pathBottom.IsVisible(p))
{
this.BottomRegion = !this.BottomRegion;
}
else if (this._pathLeft.IsVisible(p))
{
this.LeftRegion = !this.LeftRegion;
}
else if (this._pathCenter.IsVisible(p))
{
this.CenterRegion = !this.CenterRegion;
}
}
}

Custom combobox control border flickers when mouse hovers in and out

I am developing a custom combobox control dervied from the standard combobox that will look flat and borderless based on the article here:
http://www.codeproject.com/Articles/6971/Making-Standard-ComboBox-appear-flat
According to various sources I will have to override the windows procedure to do that so here is my WndProc override where I have blocked several messages from reaching the control:
protected override void WndProc(ref Message m)
{
IntPtr hDC = IntPtr.Zero;
Graphics gdc = null;
switch (m.Msg)
{
// Block these messages
case WM_CHANGEUISTATE:
case WM_MOUSEACTIVATE:
case WM_MOUSEFIRST:
case WM_MOUSELAST:
case WM_MOUSEHOVER:
case WM_MOUSELEAVE:
m.Result = (IntPtr)1;
break;
// Here we paint the border when non-client paint is received
case WM_NC_PAINT:
hDC = GetWindowDC(this.Handle);
gdc = Graphics.FromHdc(hDC);
SendMessage(this.Handle, WM_ERASEBKGND, hDC, 0);
SendPrintClientMsg(); // Send to draw client area
PaintFlatControlBorder(this, gdc);
m.Result = (IntPtr) 1; // Indicate message has been processed
ReleaseDC(m.HWnd, hDC);
gdc.Dispose();
break;
case WM_PAINT:
base.WndProc(ref m);
// Flatten the border area again
hDC = GetWindowDC(this.Handle);
gdc = Graphics.FromHdc(hDC);
Pen p = new Pen((this.Enabled? BackColor:SystemColors.Control), 2);
gdc.DrawRectangle(p, new Rectangle(2, 2, this.Width-3, this.Height-3));
PaintFlatDropDown(this, gdc);
PaintFlatControlBorder(this, gdc);
ReleaseDC(m.HWnd, hDC);
gdc.Dispose();
break;
default:
base.WndProc(ref m);
break;
}
}
Here is my constructor:
public FlatComboBox() : base()
{
this.FlatStyle = FlatStyle.Flat;
this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.ResizeRedraw, true);
}
What other wndproc messages do I have to block or is there another way around this?
Here is a good reference of all wndproc messages:
https://www.autoitscript.com/autoit3/docs/appendix/WinMsgCodes.htm
I am using .NET v4.5.
Thanks in advance.
I have done this before with a combo box to give it a customisable flat appearance, I am showing the full code so that is easier to get the idea of how it works, however it uses a custom drop down menu and menu items to complete the appearance.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace Custom.Controls
{
public class CustomComboBox : UserControl
{
private const int DEFAULT_WIDTH = 121;
private const int DEFAULT_HEIGHT = 20;
private CustomContextMenuStrip _popupControl;
private CustomToolStripMenuItem _selectedItem;
private bool _bDroppedDown;
private Color _borderColour;
private Color _dropDownButtonColour;
private Color _droppedDownArrowColour;
private Color _closedArrowColour;
private Color _dropDownBackColour;
private Color _dropDownForeColour;
private Color _dropDownBorderColour;
public Color BorderColour
{
get
{
return _borderColour;
}
set
{
_borderColour = value;
this.Invalidate();
}
}
public Color ClosedArrowColour
{
get
{
return _closedArrowColour;
}
set
{
_closedArrowColour = value;
this.Invalidate();
}
}
public Color DroppedDownArrowColour
{
get
{
return _droppedDownArrowColour;
}
set
{
_droppedDownArrowColour = value;
this.Invalidate();
}
}
public Color DropDownButtonColour
{
get
{
return _dropDownButtonColour;
}
set
{
_dropDownButtonColour = value;
this.Invalidate();
}
}
public Color DropDownBorderColour
{
get
{
return _dropDownBorderColour;
}
set
{
_dropDownBorderColour = value;
_popupControl.BorderColour = value;
this.Invalidate();
}
}
public Color DropDownBackColour
{
get
{
return _dropDownBackColour;
}
set
{
_dropDownBackColour = value;
_popupControl.BackColor = value;
this.Invalidate();
}
}
public Color DropDownForeColour
{
get
{
return _dropDownForeColour;
}
set
{
_dropDownForeColour = value;
_popupControl.ForeColor = value;
this.Invalidate();
}
}
public bool DropShadowEnabled
{
get
{
return _popupControl.DropShadowEnabled;
}
set
{
_popupControl.DropShadowEnabled = value;
this.Invalidate();
}
}
public bool DroppedDown
{
get
{
return _bDroppedDown;
}
set
{
_bDroppedDown = value;
if (value)
{
_popupControl.Show(this, new Point(0, this.Height), ToolStripDropDownDirection.BelowRight);
}
else
{
_popupControl.Hide();
}
this.Invalidate();
}
}
public ToolStripItemCollection Items
{
get
{
return _popupControl.Items;
}
}
public CustomToolStripMenuItem SelectedItem
{
get
{
return _selectedItem;
}
}
public CustomComboBox()
{
this.SetStyle(ControlStyles.ResizeRedraw, true);
this.SetStyle(ControlStyles.Selectable, true);
this.SetStyle(ControlStyles.UserMouse, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.SuspendLayout();
this.ResumeLayout(false);
_popupControl = new CustomContextMenuStrip();
_popupControl.BackColor = this.BackColor;
_popupControl.Closed += new ToolStripDropDownClosedEventHandler(PopupControl_Closed);
_popupControl.ItemClicked += new ToolStripItemClickedEventHandler(PopupControl_ItemClicked);
this.Width = DEFAULT_WIDTH;
this.Height = DEFAULT_HEIGHT;
_selectedItem = null;
_bDroppedDown = false;
this.BackColor = SystemColors.Control;
this.ForeColor = SystemColors.ControlText;
_borderColour = SystemColors.ActiveBorder;
_dropDownButtonColour = SystemColors.ButtonFace;
_droppedDownArrowColour = SystemColors.ControlLight;
_closedArrowColour = SystemColors.ControlDark;
//Set these via the properties so they take effect on _popupControl
this.DropDownBackColour = SystemColors.Control;
this.DropDownForeColour = SystemColors.ControlText;
this.DropDownBorderColour = SystemColors.ActiveBorder;
}
protected override void OnFontChanged(EventArgs e)
{
_popupControl.Font = this.Font;
base.OnFontChanged(e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
this.Invalidate();
this.DroppedDown = !this.DroppedDown;
base.OnMouseDown(e);
}
protected override void OnMouseWheel(MouseEventArgs e)
{
int nIndex = this.Items.IndexOf(_selectedItem);
if (e.Delta < 0)
{
if (nIndex < (this.Items.Count - 1))
{
_selectedItem = (CustomToolStripMenuItem)this.Items[nIndex + 1];
OnSelectedItemChanged(EventArgs.Empty);
this.Invalidate();
}
}
else if (e.Delta > 0)
{
if (nIndex > 0)
{
_selectedItem = (CustomToolStripMenuItem)this.Items[nIndex - 1];
OnSelectedItemChanged(EventArgs.Empty);
this.Invalidate();
}
}
base.OnMouseWheel(e);
}
protected override void OnPaint(PaintEventArgs e)
{
Rectangle boundingRect = new Rectangle(0, 0, this.Width, this.Height);
using (SolidBrush brush = new SolidBrush(this.BackColor))
{
e.Graphics.FillRectangle(brush, boundingRect);
}
ControlPaint.DrawBorder(e.Graphics, boundingRect, _borderColour, ButtonBorderStyle.Solid);
//Draw the dropdown button background
int nButtonWidth = SystemInformation.VerticalScrollBarWidth + SystemInformation.VerticalFocusThickness;
Rectangle dropDownButtonRect = new Rectangle(this.Width - nButtonWidth, 0, nButtonWidth, this.Height);
using (SolidBrush brush = new SolidBrush(_dropDownButtonColour))
{
e.Graphics.FillRectangle(brush, dropDownButtonRect);
}
//Draw the dropdown button arrow
using (GraphicsPath path = new GraphicsPath())
{
Point pTopLeft = new Point()
{
X = (int)Math.Round((float)dropDownButtonRect.X + ((float)dropDownButtonRect.Width * 0.30f)),
Y = (int)Math.Round((float)dropDownButtonRect.Y + ((float)dropDownButtonRect.Height * 0.35f))
};
Point pTopRight = new Point()
{
X = (int)Math.Round((float)dropDownButtonRect.X + ((float)dropDownButtonRect.Width * 0.70f)),
Y = (int)Math.Round((float)dropDownButtonRect.Y + ((float)dropDownButtonRect.Height * 0.35f))
};
Point pBottom = new Point()
{
X = (int)Math.Round((float)dropDownButtonRect.X + ((float)dropDownButtonRect.Width * 0.5f)),
Y = (int)Math.Round((float)dropDownButtonRect.Y + ((float)dropDownButtonRect.Height * 0.65f))
};
path.AddLine(pTopLeft, pTopRight);
path.AddLine(pTopRight, pBottom);
SmoothingMode previousSmoothingMode = e.Graphics.SmoothingMode;
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
{
using (SolidBrush brush = new SolidBrush(_bDroppedDown ? _droppedDownArrowColour : _closedArrowColour))
{
e.Graphics.FillPath(brush, path);
}
}
e.Graphics.SmoothingMode = previousSmoothingMode;
}
if (_selectedItem != null)
{
using (SolidBrush brush = new SolidBrush(this.ForeColor))
{
SizeF stringSize = e.Graphics.MeasureString(_selectedItem.Text, this.Font);
e.Graphics.DrawString(_selectedItem.Text, this.Font, brush, new Point(0, (this.Height / 2) - ((int)stringSize.Height / 2)));
}
}
}
protected override void OnSizeChanged(EventArgs e)
{
if (_popupControl != null)
{
_popupControl.MaximumItemSize = new Size(this.Width - 1, _popupControl.MaximumItemSize.Height);
_popupControl.Width = this.Width;
}
base.OnSizeChanged(e);
}
private void OnSelectedItemChanged(EventArgs e)
{
if (SelectedItemChanged != null)
{
SelectedItemChanged(this, e);
}
}
public void SelectFirstItem()
{
if (this.Items != null && this.Items.Count > 0)
{
_selectedItem = (CustomToolStripMenuItem)this.Items[0];
OnSelectedItemChanged(EventArgs.Empty);
}
}
public event EventHandler SelectedItemChanged;
private void PopupControl_Closed(object sender, ToolStripDropDownClosedEventArgs e)
{
this.DroppedDown = false;
this.Invalidate(true);
}
private void PopupControl_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
_selectedItem = (CustomToolStripMenuItem)e.ClickedItem;
OnSelectedItemChanged(EventArgs.Empty);
}
}
}

Categories