I created a UserControl called Switch.
I built my project and this UC successfully shown in my toolbox.
So I tried to add it to my frmMain by dragging it to the form. But at this moment, Visual Studio always shows an error message:
A new guard page for the stack cannot be created.
After clicking OK, devenv.exe crashes.
I have to mention, that I have another user control in the same namespace and folder as Switch. This UC works fine.
This is the code of my Switch user control:
public partial class Switch : UserControl
{
private Rectangle switchRectangle;
private int xOn = 0; // switchRectangle x position, when switch is on
private int xOff = 0; // switchRectangle x position, when switch is off
private Color SwitchColor = Color.Black;
private Color OuterRectangleColor = Color.DarkGray;
private Color InnerRectangleColor
{
get { return this.On ? Color.DodgerBlue : InnerRectangleColor; }
}
public bool On { get; set; }
public Switch()
{
InitializeComponent();
ReloadSwitchRectangle();
xOn = this.Width - switchRectangle.Width;
}
private void Switch_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(this.BackColor);
// Create inner rectangle, on every side by 2px smaller than ClientRectangle
const int amountToDecrease = 2;
Rectangle innerRectangle = new Rectangle(this.ClientRectangle.X + amountToDecrease, this.ClientRectangle.Y + amountToDecrease,
this.ClientRectangle.Width - amountToDecrease * 2, this.ClientRectangle.Height - amountToDecrease * 2);
ReloadSwitchRectangle();
e.Graphics.DrawRectangle(new Pen(OuterRectangleColor), this.ClientRectangle); // Draw outer rectangle
e.Graphics.FillRectangle(new SolidBrush(InnerRectangleColor), innerRectangle); // Fill inner rectangle
e.Graphics.FillRectangle(new SolidBrush(SwitchColor), switchRectangle);
}
private void ReloadSwitchRectangle()
{
int x = this.On ? xOn : xOff;
switchRectangle = new Rectangle(x, 0, this.Width / 5, this.Height);
}
}
This is the problem:
private Color InnerRectangleColor
{
get { return this.On ? Color.DodgerBlue : InnerRectangleColor; }
}
You have infinite recursion here when this.On is set to false.
Thanks to Sriram Sakthivel, I solved my problem like this:
private Color InnerRectangleColor
{
get { return this.On ? Color.DodgerBlue : OuterRectangleColor; }
}
Related
I am making a trying to make this combo box: see picture attached. For the LineStyle combo box.
Here's the code I have so far
public partial class frmDlgGraphOptions : Form
public partial class frmDlgGraphOptions : Form
{
public frmDlgGraphOptions()
{
InitializeComponent();
CmbBoxlineStyles.DropDownStyle = ComboBoxStyle.DropDownList;
}
public override void OnDrawItem(DrawItemEventArgs e)
{
// Get the item.
var item = this.CmbBoxlineStyles.SelectedIndex.ToString();
if(item == null)
return;
int startX = e.Bounds.X;
int startY = (e.Bounds.Y + 1);
int endX = e.Bounds.X + 5;
int endY = (e.Bounds.Y + 1);
//Draw the lines
Pen pen = new Pen(Color.Blue);
e.Graphics.DrawLine(pen, new Point(startX, startY), new Point(endX, endY));
}
}
I am getting this error: Error 1 'Fdrc.frmDlgGraphOptions.OnDrawItem(System.Windows.Forms.DrawItemEventArgs)': no suitable method found to override
Thank you
Sun
The form doesn't have an OnDrawItem event, so there is nothing to override.
Instead, you need to use the DrawItem event of the combobox:
public frmDlgGraphOptions()
{
InitializeComponent();
CmbBoxlineStyles.DropDownStyle = ComboBoxStyle.DropDownList;
CmbBoxlineStyles.DrawMode = DrawMode.OwnerDrawFixed;
CmbBoxlineStyles.DrawItem += CmbBoxlineStyles_DrawItem;
}
void CmbBoxlineStyles_DrawItem(object sender, DrawItemEventArgs e) {
// draw
}
Make sure you set the DrawMode property so that the control knows to call your draw method.
If you are trying to make your own ComboBox control that draws those line items, I suspect this might be what you are looking for:
public class MyCombo : ComboBox {
public MyCombo() {
this.DropDownStyle = ComboBoxStyle.DropDownList;
this.DrawMode = DrawMode.OwnerDrawFixed;
}
protected override void OnDrawItem(DrawItemEventArgs e) {
if (e.Index > -1) {
int startX = e.Bounds.Left + 5;
int startY = (e.Bounds.Y + e.Bounds.Height / 2);
int endX = e.Bounds.Right - 5;
int endY = (e.Bounds.Y + e.Bounds.Height / 2);
using (Pen p = new Pen(Color.Blue, (Int32)this.Items[e.Index])) {
e.Graphics.DrawLine(p, new Point(startX, startY), new Point(endX, endY));
}
}
base.OnDrawItem(e);
}
}
Then you just add your pen size numbers when using the control:
MyCombo CmbBoxlineStyles = new MyCombo();
CmbBoxlineStyles.Items.Add(1);
CmbBoxlineStyles.Items.Add(2);
CmbBoxlineStyles.Items.Add(3);
CmbBoxlineStyles.Items.Add(4);
Resulting in:
The Form type doesn't have a OnDrawItem method hence there is nothing to override. In order to override the method you will need to inherit directly from the ComboBox type.
You are trying to override a method of the Form, but what you need to do is to change the behaviour of the ComboBox control. So either create a descendant ComboBox class and override the method there, or add a event handler to CmbBoxlineStyles.DrawItem event (this can be done using the designer) and implement your code there.
I have 3 pictures, each one has a colored circle in it. The 3 pictures are red, green and yellow.
I'm putting it in a PictureBox in a windows form. I want to switch these images from green to yelow to red or otherwise.
Is there anything I can make them fade to each other instead of switching them the normal way?
I know this could be done using flash/j-query easily, but I was wondering how far I can achieve .
Something similar in windows forms using normal windows forms functionality.
Note: I'm using .net framework 4 and windows forms.
See Transition of images in Windows Forms Picture box. There is a solution that transitions the images using a timer on this page.
Code from site:
public class BlendPanel : Panel
{
private Image mImg1;
private Image mImg2;
private float mBlend;
public BlendPanel()
{
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint |
ControlStyles.OptimizedDoubleBuffer, true);
}
public Image Image1
{
get { return mImg1; }
set { mImg1 = value; Invalidate(); }
}
public Image Image2
{
get { return mImg2; }
set { mImg2 = value; Invalidate(); }
}
public float Blend
{
get { return mBlend; }
set { mBlend = value; Invalidate(); }
}
protected override void OnPaint(PaintEventArgs e)
{
if (mImg1 == null || mImg2 == null)
{
e.Graphics.FillRectangle(new SolidBrush(this.BackColor),
new Rectangle(0, 0, this.Width, this.Height));
}
else
{
Rectangle rc = new Rectangle(0, 0, this.Width, this.Height);
ColorMatrix cm = new ColorMatrix();
ImageAttributes ia = new ImageAttributes();
cm.Matrix33 = mBlend;
ia.SetColorMatrix(cm);
e.Graphics.DrawImage(mImg2, rc, 0, 0, mImg2.Width,
mImg2.Height, GraphicsUnit.Pixel, ia);
cm.Matrix33 = 1F - mBlend;
ia.SetColorMatrix(cm);
e.Graphics.DrawImage(mImg1, rc, 0, 0, mImg1.Width,
mImg1.Height, GraphicsUnit.Pixel, ia);
}
base.OnPaint(e);
}
}
Build your project. You can now drop a BlendPanel from the top of the toolbox onto your form. Here's a sample program that uses it:
namespace WindowsApplication1
{
public partial class Form1 : Form
{
private float mBlend;
private int mDir = 1;
public Form1()
{
InitializeComponent();
timer1.Interval = 30;
timer1.Tick += BlendTick;
blendPanel1.Image1 = Bitmap.FromFile(#"c:\temp\test1.bmp");
blendPanel1.Image2 = Bitmap.FromFile(#"c:\temp\test2.bmp");
timer1.Enabled = true;
}
private void BlendTick(object sender, EventArgs e)
{
mBlend += mDir * 0.02F;
if (mBlend < 0) { mBlend = 0; mDir = 1; }
if (mBlend > 1) { mBlend = 1; mDir = -1; }
blendPanel1.Blend = mBlend;
}
}
}
You'll need to modify the Bitmap.FromFile() calls. Build and run. You should see the displayed image smoothly morph from your first image to your second image without any flickering. Lots of ways to tweak the code, have fun.
I don't know if it is a good idea, but i would go for 2 image boxes, one to fade in, other to fade out, and change alpha when time passes.
Like what #Igoris suggested, You need to use two controls overlap each other, and you should define a timer so when you want to fade in or out, start the timer and in its tick decrease the Transparent of the first control and increase it on the second one... , the problem is that the ordinary controls does not support transparent by default. so you have to inherit it and apply transparent here is a custom TransparentPictureBox that inherited from PictureBox:
public class TransparentPictureBox : System.Windows.Forms.PictureBox
{
/// <summary>
/// Initialize new instance of this class.
/// </summary>
public TransparentPictureBox()
: base()
{
DoubleBuffered = true;
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
this.SetStyle(ControlStyles.UserPaint, true);
this.BackColor = Color.Transparent;
}
}
I have a class that extends TabControl, basically to have one with the tabs down the left hand side instead of along the top. To do I have set it to be custom drawn.
The problem is when this is put onto a form via the designer, it easily makes the designer loose track of itself and just give up and display nothing. To fix it I have to close the designer and re-open it and then everything is fine until I hit debug, or I go to a code window for a while and come back, where it gives up again.
Is there anything I can do to help visual studio a bit? As while its not throwing errors, it is getting a little tedious now. I'm using visual studio 2008.
Here is the code that extends the tab control, if anyone sees any issues that could be causing this it'd be very appreciated.
public class VerticalTabControl : TabControl
{
private Color tabColour1 = Color.AliceBlue;
public Color TabColour1
{
get { return tabColour1; }
set { tabColour1 = value; this.Refresh(); }
}
private Color tabColour2 = Color.White;
public Color TabColour2
{
get { return tabColour2; }
set { tabColour2 = value; this.Refresh(); }
}
private Color selectedTabColor1 = Color.AliceBlue;
public Color SelectedTabColor1
{
get { return selectedTabColor1; }
set { selectedTabColor1 = value; this.Refresh(); }
}
private Color selectedTabColor2 = Color.White;
public Color SelectedTabColor2
{
get { return selectedTabColor2; }
set { selectedTabColor2 = value; this.Refresh(); }
}
private Color backgroundColour = Color.White;
public Color BackgroundColour
{
get { return backgroundColour; }
set { backgroundColour = value; this.Refresh(); }
}
private Color tabTextColour = Color.Black;
public Color TabTextColour
{
get { return tabTextColour; }
set { tabTextColour = value; this.Refresh(); }
}
protected override void OnParentChanged(EventArgs e)
{
base.OnParentChanged(e);
this.Parent.Resize += new EventHandler(Parent_Resize);
}
void Parent_Resize(object sender, EventArgs e)
{
this.Refresh();
}
public VerticalTabControl()
: base()
{
this.Alignment = TabAlignment.Left;
this.SizeMode = TabSizeMode.Fixed;
this.ItemSize = new Size(50, 120);
this.DrawMode = TabDrawMode.OwnerDrawFixed;
this.DrawItem += new DrawItemEventHandler(VerticalTabControl_DrawItem);
}
void VerticalTabControl_DrawItem(object sender, DrawItemEventArgs e)
{
Graphics g = e.Graphics;
TabControl ctrl = sender as TabControl;
String sText = ctrl.TabPages[e.Index].Text;
Rectangle r = new Rectangle(e.Bounds.Left, e.Bounds.Top, e.Bounds.Width, e.Bounds.Height);
if (e.Index == ctrl.SelectedIndex)
{
using (LinearGradientBrush gb = new LinearGradientBrush(r, this.selectedTabColor1, this.selectedTabColor2, LinearGradientMode.Horizontal))
{
e.Graphics.FillRectangle(gb, r);
}
}
else
{
using (LinearGradientBrush gb = new LinearGradientBrush(r, this.tabColour1, this.tabColour2, LinearGradientMode.Horizontal))
{
e.Graphics.FillRectangle(gb, r);
}
}
// Set up the page and the various pieces.
TabPage page = ctrl.TabPages[e.Index];
// Set up the offset for an icon, the bounding rectangle and image size and then fill the background.
int iconOffset = 0;
Rectangle tabBackgroundRect = e.Bounds;
// If we have images, process them.
if (this.ImageList != null)
{
// Get sice and image.
Size size = this.ImageList.ImageSize;
Image icon = null;
if (page.ImageIndex > -1)
icon = this.ImageList.Images[page.ImageIndex];
else if (page.ImageKey != "")
icon = this.ImageList.Images[page.ImageKey];
// If there is an image, use it.
if (icon != null)
{
Point startPoint = new Point(tabBackgroundRect.X + 6,
tabBackgroundRect.Y + 2 + ((tabBackgroundRect.Height - size.Height) / 2));
e.Graphics.DrawImage(icon, new Rectangle(startPoint, size));
iconOffset = size.Width + 4;
}
}
// Draw out the label.
SizeF sizeText = g.MeasureString(sText, ctrl.Font);
int iX = e.Bounds.Left + 6 + iconOffset;
int iY = e.Bounds.Top + (e.Bounds.Height / 2) - (int)(sizeText.Height / 2);
using (Brush ForeBrush = new SolidBrush(tabTextColour))
{
g.DrawString(sText, ctrl.Font, ForeBrush, iX, iY);
}
Rectangle rec = ctrl.GetTabRect(ctrl.TabPages.Count - 1);
Rectangle recF = new Rectangle(0, rec.Bottom, this.ItemSize.Height, ctrl.Height - rec.Bottom);
using (SolidBrush bb = new SolidBrush(backgroundColour))
{
g.FillRectangle(bb, recF);
}
}
}
turns out this was the offending bit of code
protected override void OnParentChanged(EventArgs e)
{
base.OnParentChanged(e);
this.Parent.Resize += new EventHandler(Parent_Resize);
}
'this.Parent' was sometimes null and so an exception would have been thrown which would have caused the designer to fail.
Have now fixed this and also tidied up the event hooking so I didn't leave hooks everywhere. Seems to work fine now. Thanks for your help whoever answered this and deleted their answer for some reason.
I want to customize ToolStripMenuItem by overriding OnPaint function. This is a MyToolStripMenuItem:
public class MyToolStripMenuItem : ToolStripMenuItem
{
public MyToolStripMenuItem()
:base()
{
}
public MyToolStripMenuItem(string t)
:base(t)
{
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
Rectangle r = this.Bounds;
g.FillRectangle(Brushes.Blue, r);
g.DrawString(this.Text, this.Font, Brushes.Red, r);
}
}
In my code, I will fill a blue color in item's bound. Now, I will create a list of items on menustrip:
MyToolStripMenuItem1
|___MyToolStripMenuItem2
|___MyToolStripMenuItem3
I don't know why MyToolStripMenuItem3 don't have a blue background.
This is my source code:
http://www.mediafire.com/?2qhmjzzfzzn
Please help me. Thanks.
It's not the way it is done with a ToolStripMenuItem. You give the MenuStrip a custom renderer. For example:
For example:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
menuStrip1.Renderer = new MyRenderer();
}
private class MyRenderer : ToolStripProfessionalRenderer {
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) {
if (!e.Item.Selected) base.OnRenderMenuItemBackground(e);
else {
Rectangle rc = new Rectangle(Point.Empty, e.Item.Size);
e.Graphics.FillRectangle(Brushes.Beige, rc);
e.Graphics.DrawRectangle(Pens.Black, 1, 0, rc.Width - 2, rc.Height - 1);
}
}
}
}
The problem with using OnRenderMenuItemBackground() is that it applies to the whole menu and not just the one ToolStripMenuItem.
The error in the code lies in Rectangle r = this.Bounds; which produces the wrong area. Change this to Rectangle r = e.ClipRectangle and it should work ok. (For some reason the Bounds has the wrong Y component).
I don't like the AutoSize property of the Label control. I have a custom Label that draws a fancy rounded border among other things. I'm placing a AutoSize = false in my constructor, however, when I place it in design mode, the property always is True.
I have overridden other properties with success but this one is happily ignoring me. Does anybody has a clue if this is "by MS design"?
Here's the full source code of my Label in case anyone is interested.
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace Dentactil.UI.WinControls
{
[DefaultProperty("TextString")]
[DefaultEvent("TextClick")]
public partial class RoundedLabel : UserControl
{
private static readonly Color DEFAULT_BORDER_COLOR = Color.FromArgb( 132, 100, 161 );
private const float DEFAULT_BORDER_WIDTH = 2.0F;
private const int DEFAULT_ROUNDED_WIDTH = 16;
private const int DEFAULT_ROUNDED_HEIGHT = 12;
private Color mBorderColor = DEFAULT_BORDER_COLOR;
private float mBorderWidth = DEFAULT_BORDER_WIDTH;
private int mRoundedWidth = DEFAULT_ROUNDED_WIDTH;
private int mRoundedHeight = DEFAULT_ROUNDED_HEIGHT;
public event EventHandler TextClick;
private Padding mPadding = new Padding(8);
public RoundedLabel()
{
InitializeComponent();
}
public Cursor TextCursor
{
get { return lblText.Cursor; }
set { lblText.Cursor = value; }
}
public Padding TextPadding
{
get { return mPadding; }
set
{
mPadding = value;
UpdateInternalBounds();
}
}
public ContentAlignment TextAlign
{
get { return lblText.TextAlign; }
set { lblText.TextAlign = value; }
}
public string TextString
{
get { return lblText.Text; }
set { lblText.Text = value; }
}
public override Font Font
{
get { return base.Font; }
set
{
base.Font = value;
lblText.Font = value;
}
}
public override Color ForeColor
{
get { return base.ForeColor; }
set
{
base.ForeColor = value;
lblText.ForeColor = value;
}
}
public Color BorderColor
{
get { return mBorderColor; }
set
{
mBorderColor = value;
Invalidate();
}
}
[DefaultValue(DEFAULT_BORDER_WIDTH)]
public float BorderWidth
{
get { return mBorderWidth; }
set
{
mBorderWidth = value;
Invalidate();
}
}
[DefaultValue(DEFAULT_ROUNDED_WIDTH)]
public int RoundedWidth
{
get { return mRoundedWidth; }
set
{
mRoundedWidth = value;
Invalidate();
}
}
[DefaultValue(DEFAULT_ROUNDED_HEIGHT)]
public int RoundedHeight
{
get { return mRoundedHeight; }
set
{
mRoundedHeight = value;
Invalidate();
}
}
private void UpdateInternalBounds()
{
lblText.Left = mPadding.Left;
lblText.Top = mPadding.Top;
int width = Width - mPadding.Right - mPadding.Left;
lblText.Width = width > 0 ? width : 0;
int heigth = Height - mPadding.Bottom - mPadding.Top;
lblText.Height = heigth > 0 ? heigth : 0;
}
protected override void OnLoad(EventArgs e)
{
UpdateInternalBounds();
base.OnLoad(e);
}
protected override void OnPaint(PaintEventArgs e)
{
SmoothingMode smoothingMode = e.Graphics.SmoothingMode;
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
int roundedWidth = RoundedWidth > (Width - 1)/2 ? (Width - 1)/2 : RoundedWidth;
int roundedHeight = RoundedHeight > (Height - 1)/2 ? (Height - 1)/2 : RoundedHeight;
GraphicsPath path = new GraphicsPath();
path.AddLine(0, roundedHeight, 0, Height - 1 - roundedHeight);
path.AddArc(new RectangleF(0, Height - 1 - 2*roundedHeight, 2*roundedWidth, 2*roundedHeight), 180, -90);
path.AddLine(roundedWidth, Height - 1, Width - 1 - 2*roundedWidth, Height - 1);
path.AddArc(new RectangleF(Width - 1 - 2*roundedWidth, Height - 1 - 2*roundedHeight, 2*roundedWidth, 2*roundedHeight), 90, -90);
path.AddLine(Width - 1, Height - 1 - roundedHeight, Width - 1, roundedHeight);
path.AddArc(new RectangleF(Width - 1 - 2*roundedWidth, 0, 2*roundedWidth, 2*roundedHeight), 0, -90);
path.AddLine(Width - 1 - roundedWidth, 0, roundedWidth, 0);
path.AddArc(new RectangleF(0, 0, 2*roundedWidth, 2*roundedHeight), -90, -90);
e.Graphics.DrawPath(new Pen(new SolidBrush(BorderColor), BorderWidth), path);
e.Graphics.SmoothingMode = smoothingMode;
base.OnPaint(e);
}
protected override void OnResize(EventArgs e)
{
UpdateInternalBounds();
base.OnResize(e);
}
private void lblText_Click(object sender, EventArgs e)
{
if (TextClick != null)
{
TextClick(this, e);
}
}
}
}
(there are some issues with Stack Overflow's markup and the Underscore, but it's easy to follow the code).
I have actually removed that override some time ago when I saw that it wasn't working. I'll add it again now and test. Basically I want to replace the Label with some new label called: IWillNotAutoSizeLabel ;)
I basically hate the autosize property "on by default".
I've seen similar behaviour when setting certain properties of controls in the constructor of the form itself. They seem to revert back to their design-time defaults.
I notice you're already overriding the OnLoad method. Have you tried setting AutoSize = false there? Or are you mainly concerned with providing a default value of false?
I spent a lot of time with it and this finally works! (my code is vb.net but is simple to convert it)
Private _Autosize As Boolean
Public Sub New()
_Autosize=False
End Sub
Public Overrides Property AutoSize() As Boolean
Get
Return MyBase.AutoSize
End Get
Set(ByVal Value As Boolean)
If _Autosize <> Value And _Autosize = False Then
MyBase.AutoSize = False
_Autosize = Value
Else
MyBase.AutoSize = Value
End If
End Set
End Property
Your problem could be that you're not actually overriding Autosize in your code (ie, in the same way that you're overriding Font or ForeColor).
I don't see this.AutoSize = false in your constructor. Your class is marked as partial -- perhaps you have a constructor in another file with that line. The visual studio designer will call that parameterless constructor you've got there.
I managed to disable the Autosize feature of my personal label by overriding the "OnCreateControl()" method, as simple as that:
protected override void OnCreateControl()
{
AutoSize = false;
}
I hope it worked for you :)