Archive for February, 2006

How to grab input keys (Tab, Cursors Keys) in a control

As default, systems keys such as tab, return, up, down, left and right are handled by the form to move between controls. To enable theses keys to be raised as key down, up and pressed events, you need to override the IsInpuKey method and return true for the keys you wish your control to process.

e.g. to get a control to process the Tab key.

 
protected override bool IsInputKey(System.Windows.Forms.Keys keyData)
{
	switch (keyData)
	{
		case Keys.Tab: return (true);
		default:
			return (base.IsInputKey(keyData));
	}
}

How to create a bit-based enumeration

If you want to create an enumeration that acts like a set, where the value of the enumeration can be a combination of any of the members of the enumeration then you C# allows you to do this using the FlagsAttribute.

Simply add the attribute to the start of the enumeration and the enumeration values will be treated as bit flags instead.

 
[FlagsAttribute]
enum Colors : short
{
	None = 0,
	Red = 1,
	Green = 2,
	Blue = 4,
	White = 7
};

You can use bitwise operators Not, And, Or and XOR on the enumeration.

e.g. to see if an enumeration value is set

 
if ( Colors & Red == Red)
{
	// do something
}

Note that the not (!) does not work on bitwise operations so the complement(~) operator is required.

So to remove a the red and green flag from the set…

Colors = Colors & ~(Red | Green);

Creating a transparent UserControl

If you want to create a user control that is not rectangular and shows the parent control surface then you have to make the control transparent.

This can be achieved by adding the following to the UserControl’s constructor.

[csharp]

SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.DoubleBuffer, true);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);

[/csharp]

Rendering standard visual style control elements

.Net provides a single class that can render most standard control elements such as Buttons, 3d rectangles checkboxes, etc using the current theme services.

This class is the static ControlPaint class. Some of the methods include:

  • DrawBorder(Graphics graphics, Rectangle bounds, Color color, ButtonBorderStyle style);
  • DrawBorder3D(Graphics graphics, Rectangle rectangle);
  • DrawButton(Graphics graphics, int x, int y, int width, int height, ButtonState state);
  • DrawCheckBox(Graphics graphics, int x, int y, int width, int height, ButtonState state);
  • DrawRadioButton(Graphics graphics, Rectangle rectangle, ButtonState state);
  • DrawSizeGrip(Graphics graphics, Color backColor, Rectangle bounds);

See the documentation for more methods.

In addition there are specific static Renderer classes availablehat provide measuring routines and rendering routines as well, such as:

  • ButtonRenderer
  • CheckBoxRenderer
  • TabRenderer
  • TextBoxRender
  • TextRenderer
  • ScrollBarRenderer
  • ToolStripRenderer

For a full list type renderer into the object browser in Visual studio.

How to create a curved tab and fill with a gradiant

ExampleIf you want to create a curved tab style control similar to the control on the right, then you can use the path functionallity of the graphics class to produce the rectangle with rounded corners at the top.

A linear gradiant brush finishes off the nice rendering effect.

[csharp]

Rectangle rc = new Rectangle(0, 0, this.Width, _CaptionHeight+1);
LinearGradientBrush b = new LinearGradientBrush(rc,
_CaptionLeftColor, _CaptionRightColor,
LinearGradientMode.Vertical);

// Now draw the caption areas with the rounded corners at the top
GraphicsPath path = new GraphicsPath();
path.AddLine(_CurveRadius, 0, this.Width -
(_CurveRadius * 2), 0);
path.AddArc(this.Width – (_CurveRadius * 2) – 1, 0,
(_CurveRadius * 2), (_CurveRadius * 2), 270, 90);
path.AddLine(this.Width-1, _CurveRadius,this.Width-1, _CaptionHeight);
path.AddLine(this.Width, _CaptionHeight+1, 0, _CaptionHeight+1);
path.AddLine(0, _CaptionHeight, 0, _CurveRadius);
path.AddArc(0, 0, (_CurveRadius * 2),
(_CurveRadius * 2), 180, 90);

// Remove jaggies
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;

// Smooooth fill
e.Graphics.FillPath(b, path);
e.Graphics.DrawPath(new Pen(_PanelOutlineColor), path);

[/csharp]

Drawing trimmed text with ellipsis …

I have been writing a mulit-columnal control that rendered it’s text using the graphics.DrawString method and formatted to add the ellipsis characters if the text was too long for the output rect. However, as the column was resized, the text inter-character spacing changed, giving a very disconcerting wobble to the text.
To correctly output trimmed text I had to use the TextRenderer.DrawText method.

[csharp]

TextFormatFlags flags = new TextFormatFlags();
flags = TextFormatFlags.EndEllipsis | TextFormatFlags.Left | TextFormatFlags.VerticalCenter ;
TextRenderer.DrawText(g, text, font, rect, SystemColors.ControlText,flags);
[/csharp>

Please Note : microsoft recommend using TextRedner for drawing text…

System.Drawing.Graphics class presents some limitations—it is based on GDI+ and currently has limited support for complex scripts. For more information see MSDN article http://msdn.microsoft.com/msdnmag/issues/06/03/TextRendering/default.aspx

How to override constructors and pass extra parameters

If you want to descend from a class that requires parameters passed in its constructor, and you wish to introduce extra parameters in the descedants constructor then when you define the derived classes constructor, simply add : base() to the constructors signiture to get c# to call the inherited constructor.

If you need to pass parameters through to the inherited call, use :base(param1, param2)

As soon as you add a descendant that overrides the parameter list for a classes constructor, any other descendant classes will have to have a constructor implementation, similar to the Derived class below, to let the compiler know which of the inherited constructors needs calling when the descendant class is created. Otherwise a “No overload for method ‘x’ takes ‘0′ arguments” error may occur

How to check object instances are of a specific class or inherited from a specific class

You can determine if an object is of a specific class by using the typeof keyword.

[csharp]

if (myObj.GetType() == typeof(MyClass))
{
// Do something

}[/csharp]

If you want to check to see if an object is of a specific type, or can be cast to a specific type then use the is operator.
[csharp]

if (myObj is MyClass)
{
// Do something
}
[/csharp]

How to access resources, eg use a resource image

In Visual Studio 2005, (im not sure about other versions), simply choose properties on the Assembly and add the Resources you need under the resource tab.
In the class file you want to access the resources in, add a using statement
[csharp]using MyProject.Properties;[/csharp]
You can now access the resources in code by using the static Resource class.

[csharp]MyGraphics.DrawImage(Resources.MyImageResourceName, new Point(0,0));[/csharp]

How to get Mouse Position and Cursor information

If you want to set or retrieve the current mouse position, or turn the cursor on or off, use the static Cursor class.

Point CursorPos = Cursor.Position