|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionThis code shows you how to build a fast and performing control using C# and .NET 2.0. I wrote a similar control as an ActiveX once, using C++, ATL, and GDI, and wondered if it is possible to write performing code using .NET and GDI+. I needed it for another project. So I wrote this little control to show that it actually works. How the code worksThe code consists of a C# application and a custom control. The custom control really is the interesting part. Deriving from ControlWe derive from public partial class AGauge : Control
Dealing with propertiesHiding, shadowing unwanted propertiesWell, there are still properties that show up in the designer that are not necessary. In C#, you can use the public new Boolean AllowDrop, AutoSize, ForeColor, ImeMode
Overriding useful propertiesFor properties that you want to use but with a different behaviour, you can use the public override System.Drawing.Color BackColor..
public override System.Drawing.Font Font..
public override System.Windows.Forms.ImageLayout BackgroundImageLayout..
Custom propertiesTo be able to further customize the control in the designer, we need to add some properties of our own. E.g., [System.ComponentModel.Browsable(true),
System.ComponentModel.Category("AGauge"),
System.ComponentModel.Description("The value.")]
public Single Value..
The Events and DelegatesAn event can carry additional information that is sent to the "listening" program, e.g., the form's event handler for this event. Custom event argumentsWe want the event to carry the number of the range the needle is in (if it changes from being in one range to being in another). To add some data to the event, we derive from the standard event args and add a variable which is initialized in the constructor. This will hold the extra information sent along. public class ValueInRangeChangedEventArgs : EventArgs
{
public Int32 valueInRange;
public ValueInRangeChangedEventArgs(Int32 valueInRange)
{
this.valueInRange = valueInRange;
}
}
Event delegateThe event handler "listening" for our event needs to be of a type that "understands" our event. With the delegate statement, we define this type. public delegate void ValueInRangeChangedDelegate(Object sender,
ValueInRangeChangedEventArgs e);
And the event[Description("This event is raised if the value falls into a defined range.")]
public event ValueInRangeChangedDelegate ValueInRangeChanged;
The event is of the type we defined in the delegate statement. The ConstructorThe constructor is called when the control is created, e.g., before it will be shown in the designer. Here, we set the style of the control to enable double buffering. This isn't really necessary since we will do our own double buffering, but it doesn't hurt to do so. public AGauge()
{
InitializeComponent();
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
}
Overriding member functionsWe need to override some of the member functions. First, we override protected override void OnPaintBackground(PaintEventArgs pevent)
{
}
If the control is resized, we need to refresh it. So we override protected override void OnResize(EventArgs e)
{
drawGaugeBackground = true;
Refresh();
}
The global variable " Finally, we need to override This is what our control really does, it shows the output to the user. It doesn't handle user input like a scrollbar would do. A scrollbar would override protected override void OnPaint(PaintEventArgs pe)
ConclusionSo it really is possible to write fast and performing controls with GDI+ if we use double buffering and blitting ( If you like VB better than C#, you can search for "SpeedyHMI" on SourceForge, this project I wrote contains this gauge written in VB. Download, build, run and, Enjoy!
|
||||||||||||||||||||||