I'm in need of a way to make TextBox appear like a parallelogram but i can't figure out how to do so. I currently have this code:
private void IOBox_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
Point cursor = PointToClient(Cursor.Position);
Point[] points = { cursor, new Point(cursor.X + 50, cursor.Y), new Point(cursor.X + 30, cursor.Y - 20),
new Point(cursor.X - 20, cursor.Y - 20) };
Pen pen = new Pen(SystemColors.MenuHighlight, 2);
g.DrawLines(pen, points);
}
But apparently it's not working. Either i misplaced/misused it or i'm not doing something right.
This is the method that i use to add it.
int IOCounter = 0;
private void inputOutput_Click(object sender, EventArgs e)
{
IOBox box = new IOBox();
box.Name = "IOBox" + IOCounter;
IOCounter++;
box.Location = PointToClient(Cursor.Position);
this.Controls.Add(box);
}
Any idea how i can fix it? IOBox is a UserControl made by me which contains a TextBox. Is that rightful to do?
If its possible, you should make your application using WPF. WPF is designed to do exactly what you are trying to do.
However, it can be done in WinForms, though not easily. You will need to make a new class that inherits the TextBox WinForm control. Here is an example that makes a TextBox look like a circle:
public class MyTextBox : TextBox
{
public MyTextBox() : base()
{
SetStyle(ControlStyles.UserPaint, true);
Multiline = true;
Width = 130;
Height = 119;
}
public override sealed bool Multiline
{
get { return base.Multiline; }
set { base.Multiline = value; }
}
protected override void OnPaintBackground(PaintEventArgs e)
{
var buttonPath = new System.Drawing.Drawing2D.GraphicsPath();
var newRectangle = ClientRectangle;
newRectangle.Inflate(-10, -10);
e.Graphics.DrawEllipse(System.Drawing.Pens.Black, newRectangle);
newRectangle.Inflate(1, 1);
buttonPath.AddEllipse(newRectangle);
Region = new System.Drawing.Region(buttonPath);
base.OnPaintBackground(e);
}
}
Keep in mind that you will still have to do other things, such as clipping the text, etc. But this should get you started.
Related
I cannot figure how to get the red light on my code to flash with respect to an interval that I have set for it.
I've tried to use Invalidate and Update, along with Refresh and none of them seems to work. I'm very new to C# and coding in general so it could be that the code is deeply flawed and if that is the case don't hesitate to yell at me.
public class UI: Form
{
protected Label lights_title = new Label();
protected Button pause, resume, exit;
protected bool isPaint = true;
public static System.Timers.Timer g_shock = new System.Timers.Timer();
public UI()
{
// text initialization
this.Text = "Chukwudi's Flashing Red Light";
this.lights_title.Text = "Ikem's Emergency Lights!";
// size initialization - determine the size of the UI Form
this.lights_title.Size = new Size(700, 40);
this.Size = new Size(1920, 1080);
// location initialization (x,y) x pulls you right as the number increase, y pulls you down
this.lights_title.Location = new Point(598, 60);
// title config & background color
this.lights_title.BackColor = Color.Coral;
this.lights_title.TextAlign = (System.Drawing.ContentAlignment)HorizontalAlignment.Center;
this.BackColor = Color.DimGray;
Render();
g_shock.Enabled = false;
g_shock.Elapsed += ManageOnPaint;
g_shock.Enabled = true;
g_shock.Start();
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics shape = e.Graphics;
if (isPaint)
{
shape.FillRectangle(Brushes.Black, new Rectangle(598, 90, 700, 700));
shape.FillEllipse(Brushes.Red, new Rectangle(650, 140, 600, 600));
}
shape.FillRectangle(Brushes.Brown, new Rectangle(598, 785, 700, 60));
}
protected void ManageOnPaint(object sender, System.Timers.ElapsedEventArgs elapsed)
{
g_shock.Interval = 1000;
Invalidate();
Update();
// turn something to true
}
}
As Alex F pointed out, you're not toggling something to keep track of whether the control is red or not.
And you're not painting anything in the timereventhandler.
My suggestion is below, I left out bits that don't concern my point.
private bool isRed;
private static System.Timers.Timer g_shock = new System.Timers.Timer();
public UI()
{
g_shock.Elapsed += ManageOnPaint;
g_shock.Interval = 1000;
g_shock.Start();
}
private void ManageOnPaint(object sender, System.Timers.ElapsedEventArgs elapsed)
{
if (isRed)
{
// Set ellipse color non red
}
if (!isRed)
{
// Set ellipse color red
}
// Toggle isRed
isRed = !isRed;
}
protected override void OnPaint(PaintEventArgs e)
{
/// paint ellipse with current ellipse color
}
I have a WinForms application that interacts with a connection. If the connection is fine I want to show a green ("everything is fine") filled circle, if not I want to show a red filled circle.
I found no circle element in the toolbox so I think I have to draw it on my own.
I created a picture box called picBoxClientState and started with this code
public partial class FrmMain : Form
{
public void CheckSignedInState()
{
// some other code
DrawClientStateIcon(client.IsSignedIn);
}
private void DrawClientStateIcon(bool isSignedIn)
{
Point rectangleLocation = picBoxClientState.Location;
Size rectangleSize = picBoxClientState.Size;
Rectangle rectangle = new Rectangle(rectangleLocation, rectangleSize);
Color iconColor = isSignedIn ? Color.Green : Color.Red;
SolidBrush iconBrush = new SolidBrush(iconColor);
Graphics graphics = picBoxClientState.CreateGraphics();
graphics.FillEllipse(iconBrush, rectangle);
}
}
How can I draw on this picturebox whenever I call CheckSignedInState() ?
Maybe there is a better way instead of drawing? (I don't want to toggle two images because there might be more states to draw)
A simple example using a Label control to draw an ellipse.
You can use any control that has a Paint event to draw shapes.
It could also be a Panel, a PictureBox, a Button...
A bool variable (clientIsSignedIn) declared at Class scope is used to keep track of the current status, as reported by your client.IsSignedIn value.
When the status changes, update clientIsSignedIn and Invalidate() the Control that provides the visual aid.
bool clientIsSignedIn = false;
public void CheckSignedInState()
{
// some other code
clientIsSignedIn = client.IsSignedIn;
lblVisualStatus.Invalidate();
}
private void lblVisualStatus_Paint(object sender, PaintEventArgs e)
{
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
e.Graphics.FillEllipse((clientIsSignedIn) ? Brushes.Green : Brushes.Red, ((Control)sender).ClientRectangle);
}
I don't think picture box is necessary. You can try something like this:
private void button1_Click(object sender, EventArgs e)
{
System.Drawing.SolidBrush myBrush = new
System.Drawing.SolidBrush(System.Drawing.Color.Red);
System.Drawing.Graphics formGraphics;
formGraphics = this.CreateGraphics();
formGraphics.FillEllipse(myBrush, new Rectangle(200, 200, 30, 30));
myBrush.Dispose();
formGraphics.Dispose();
}
If you need to draw on picturebox be sure to call picturebox.Invalidate();
your code works, it did seem to draw a bit off center though but also the fact that you weren't disposing of the object could potentially cause issues too. Try using the code below as your DrawClientStateIcon method
Edit: full code example below. I added a button to toggle the state of the client and this works for me.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public class Client
{
public bool IsSignedIn { get; set; }
}
Client client = new Client()
{
IsSignedIn = false
};
public Form1()
{
InitializeComponent();
}
public void CheckSignedInState()
{
// some other code
DrawClientStateIcon(client.IsSignedIn);
}
private void DrawClientStateIcon(bool isSignedIn)
{
Point rectangleLocation = picBoxClientState.Location;
Size rectangleSize = picBoxClientState.Size;
Rectangle rectangle = new Rectangle(rectangleLocation, new Size(rectangleSize.Width / 2, rectangleSize.Height / 2));
Color iconColor = isSignedIn ? Color.Green : Color.Red;
using (SolidBrush iconBrush = new SolidBrush(iconColor))
{
using (Graphics graphics = picBoxClientState.CreateGraphics())
{
graphics.FillEllipse(iconBrush, rectangle);
}
}
}
private void button1_Click(object sender, EventArgs e)
{
client.IsSignedIn = !client.IsSignedIn;
CheckSignedInState();
}
}
}
You need to call it in Form Shown event.
private void FrmGraphics_Shown(object sender, EventArgs e)
{
DrawClientStateIcon(true);
}
private void DrawClientStateIcon(bool isSignedIn)
{
Point rectangleLocation = picBoxClientState.Location;
Size rectangleSize = picBoxClientState.Size;
Rectangle rectangle = new Rectangle(rectangleLocation, rectangleSize);
Color iconColor = isSignedIn ? Color.Green : Color.Red;
SolidBrush iconBrush = new SolidBrush(iconColor);
Graphics graphics = base.CreateGraphics();
graphics.FillEllipse(iconBrush, rectangle);
}
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.
How can I change the BorderColor of the Textbox when a user Clicks on it or focuses on it?
You can handle WM_NCPAINT message of TextBox and draw a border on the non-client area of control if the control has focus. You can use any color to draw border:
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class ExTextBox : TextBox
{
[DllImport("user32")]
private static extern IntPtr GetWindowDC(IntPtr hwnd);
private const int WM_NCPAINT = 0x85;
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_NCPAINT && this.Focused)
{
var dc = GetWindowDC(Handle);
using (Graphics g = Graphics.FromHdc(dc))
{
g.DrawRectangle(Pens.Red, 0, 0, Width - 1, Height - 1);
}
}
}
}
Result
The painting of borders while the control is focused is completely flicker-free:
BorderColor property for TextBox
In the current post I just change the border color on focus. You can also add a BorderColor property to the control. Then you can change border-color based on your requirement at design-time or run-time. I've posted a more completed version of TextBox which has BorderColor property:
in the following post:
BorderColor property for TextBox
try this
bool focus = false;
private void Form1_Paint(object sender, PaintEventArgs e)
{
if (focus)
{
textBox1.BorderStyle = BorderStyle.None;
Pen p = new Pen(Color.Red);
Graphics g = e.Graphics;
int variance = 3;
g.DrawRectangle(p, new Rectangle(textBox1.Location.X - variance, textBox1.Location.Y - variance, textBox1.Width + variance, textBox1.Height +variance ));
}
else
{
textBox1.BorderStyle = BorderStyle.FixedSingle;
}
}
private void textBox1_Enter(object sender, EventArgs e)
{
focus = true;
this.Refresh();
}
private void textBox1_Leave(object sender, EventArgs e)
{
focus = false;
this.Refresh();
}
This is an ultimate solution to set the border color of a TextBox:
public class BorderedTextBox : UserControl
{
TextBox textBox;
public BorderedTextBox()
{
textBox = new TextBox()
{
BorderStyle = BorderStyle.FixedSingle,
Location = new Point(-1, -1),
Anchor = AnchorStyles.Top | AnchorStyles.Bottom |
AnchorStyles.Left | AnchorStyles.Right
};
Control container = new ContainerControl()
{
Dock = DockStyle.Fill,
Padding = new Padding(-1)
};
container.Controls.Add(textBox);
this.Controls.Add(container);
DefaultBorderColor = SystemColors.ControlDark;
FocusedBorderColor = Color.Red;
BackColor = DefaultBorderColor;
Padding = new Padding(1);
Size = textBox.Size;
}
public Color DefaultBorderColor { get; set; }
public Color FocusedBorderColor { get; set; }
public override string Text
{
get { return textBox.Text; }
set { textBox.Text = value; }
}
protected override void OnEnter(EventArgs e)
{
BackColor = FocusedBorderColor;
base.OnEnter(e);
}
protected override void OnLeave(EventArgs e)
{
BackColor = DefaultBorderColor;
base.OnLeave(e);
}
protected override void SetBoundsCore(int x, int y,
int width, int height, BoundsSpecified specified)
{
base.SetBoundsCore(x, y, width, textBox.PreferredHeight, specified);
}
}
WinForms was never good at this and it's a bit of a pain.
One way you can try is by embedding a TextBox in a Panel and then manage the drawing based on focus from there:
public class BorderTextBox : Panel {
private Color _NormalBorderColor = Color.Gray;
private Color _FocusBorderColor = Color.Blue;
public TextBox EditBox;
public BorderTextBox() {
this.DoubleBuffered = true;
this.Padding = new Padding(2);
EditBox = new TextBox();
EditBox.AutoSize = false;
EditBox.BorderStyle = BorderStyle.None;
EditBox.Dock = DockStyle.Fill;
EditBox.Enter += new EventHandler(EditBox_Refresh);
EditBox.Leave += new EventHandler(EditBox_Refresh);
EditBox.Resize += new EventHandler(EditBox_Refresh);
this.Controls.Add(EditBox);
}
private void EditBox_Refresh(object sender, EventArgs e) {
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e) {
e.Graphics.Clear(SystemColors.Window);
using (Pen borderPen = new Pen(this.EditBox.Focused ? _FocusBorderColor : _NormalBorderColor)) {
e.Graphics.DrawRectangle(borderPen, new Rectangle(0, 0, this.ClientSize.Width - 1, this.ClientSize.Height - 1));
}
base.OnPaint(e);
}
}
Using OnPaint to draw a custom border on your controls is fine. But know how to use OnPaint to keep efficiency up, and render time to a minimum. Read this if you are experiencing a laggy GUI while using custom paint routines: What is the right way to use OnPaint in .Net applications?
Because the accepted answer of PraVn may seem simple, but is actually inefficient. Using a custom control, like the ones posted in the answers above is way better.
Maybe the performance is not an issue in your application, because it is small, but for larger applications with a lot of custom OnPaint routines it is a wrong approach to use the way PraVn showed.
set Text box Border style to None
then write this code to container form "paint" event
private void Form1_Paint(object sender, PaintEventArgs e)
{
System.Drawing.Rectangle rect = new Rectangle(TextBox1.Location.X,
TextBox1.Location.Y, TextBox1.ClientSize.Width, TextBox1.ClientSize.Height);
rect.Inflate(1, 1); // border thickness
System.Windows.Forms.ControlPaint.DrawBorder(e.Graphics, rect,
Color.DeepSkyBlue, ButtonBorderStyle.Solid);
}
With PictureBox1
.Visible = False
.Width = TextBox1.Width + 4
.Height = TextBox1.Height + 4
.Left = TextBox1.Left - 2
.Top = TextBox1.Top - 2
.SendToBack()
.Visible = True
End With
Here is my complete Flat TextBox control that supports themes including custom border colors in normal and focused states.
The control uses the same concept mentioned by Reza Aghaei https://stackoverflow.com/a/38405319/5514131 ,however the FlatTextBox control is more customizable and flicker-free.
The control handles the WM_NCPAINT window message in a better way to help eliminate flicker.
Protected Overrides Sub WndProc(ByRef m As Message)
If m.Msg = WindowMessage.WM_NCPAINT AndAlso _drawBorder AndAlso Not DesignMode Then 'Draw the control border
Dim w As Integer
Dim h As Integer
Dim clip As Rectangle
Dim hdc As IntPtr
Dim clientRect As RECT = Nothing
GetClientRect(Handle, clientRect)
Dim windowRect As RECT = Nothing
GetWindowRect(Handle, windowRect)
w = windowRect.Right - windowRect.Left
h = windowRect.Bottom - windowRect.Top
clip = New Rectangle(CInt((w - clientRect.Right) / 2), CInt((h - clientRect.Bottom) / 2), clientRect.Right, clientRect.Bottom)
hdc = GetWindowDC(Handle)
Using g As Graphics = Graphics.FromHdc(hdc)
g.SetClip(clip, CombineMode.Exclude)
Using sb = New SolidBrush(BackColor)
g.FillRectangle(sb, 0, 0, w, h)
End Using
Using p = New Pen(If(Focused, _borderActiveColor, _borderNormalColor), BORDER_WIDTH)
g.DrawRectangle(p, 0, 0, w - 1, h - 1)
End Using
End Using
ReleaseDC(Handle, hdc)
Return
End If
MyBase.WndProc(m)
End Sub
I have removed the default BorderStyle property and replaced it with a simple boolean DrawBorder property that controls whether to draw a border around the control or not.
Use the BorderNormalColor property to specify the border color when the TextBox has no focus, and the BorderActiveColor property to specify the border color when the control receives focus.
The FlatTextBox comes with two themes VS2019 Dark and VS2019 Light, use the Theme property to switch between them.
Complete FlatTextBox control code written in VB.NET
https://gist.github.com/ahmedosama007/37fe2004183a51a4ea0b4a6dcb554176
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.