Website of Markus Griesser
Latest Update: 29.12.2007
The goal of this article is to create a simple user control which can be
added to a windows form and sends an event to the main form to react on changes
in the user control. Some portions of the code are based on
Drawing flicker free with GDI+. We start with the same form as in the referred articel
and add a panel to the bottom. It should look like this:
In the next step we will add a user control to our project. When done your project
tree should look like this:
I want to create a user control for changing an angle several ways. Therefor I will
add a big label for drawing, some others for clicking a specific angle (0°, 45°, 90°, etc.)
and a Textbox (numeric up/down) for manually changing the value. In the designer my
control now looks like this:
The control will have one private variable m_Anlge. Its value will be accessible by a
property which is implemented as follows.
private double m_Angle = 0;
public double Angle {
get {
return m_Angle;
}
set {
m_Angle = value;
textBox1.Value = Convert.ToDecimal(m_Angle);
DrawAngleControl();
OnAngleChanged();
}
}
When setting the property it does many things. At first assigning the value to the
variable. Then updating the Textbox-Value, drawing the angle in the lable and firing
the event. The DrawAngleControl functions looks like this:
private void DrawAngleControl() {
Bitmap bmp = new Bitmap(label1.Width, label1.Height);
Graphics g = Graphics.FromImage(bmp);
System.Drawing.Drawing2D.LinearGradientBrush newBrush =
new System.Drawing.Drawing2D.LinearGradientBrush(
new Point(0, 0),
new Point(label1.Width, label1.Height),
Color.WhiteSmoke,
Color.DarkGray);
g.FillRectangle(newBrush, new Rectangle(
0, 0, label1.Width, label1.Height));
PointF startPoint = new PointF(
label1.Width / 2,
label1.Height / 2);
double dAngleRad = (m_Angle / 360.0) * 2 * Math.PI;
PointF endPoint = new PointF(
startPoint.X + (float)Math.Cos(dAngleRad) * label1.Width,
startPoint.Y - (float)Math.Sin(dAngleRad) * label1.Width);
g.DrawLine(Pens.Blue, startPoint, endPoint);
label1.Image = bmp;
}
For firing the event I will add a custom eventhandler. To do so, I have to prepare several things. At first I create my own EventArgs class, derived from the System.EventArgs class:
public class AngleEventArgs : EventArgs{
public AngleEventArgs(double dNewAngle){
m_Angle = dNewAngle;
}
private double m_Angle;
public double Angle{
get{ return m_Angle;}
}
}
Make sure, that any new class is on bottom of the usercontrol code. Because the designer has a problem if it is not like this. The constructor simply takes one argument and has a puplic property to access the variable. Now we add a delegate on the outside of the class (directly in the namespace and not in any class):
public delegate void AngleChangedEventHandler(object sender,
AngleEventArgs e);
Finally we add the event and the eventhandler function, which will be accessible from the outside. In the main form we will use it to get informed when the (above mentioned) Angle-Property changes. The code is as follows:
public event AngleChangedEventHandler AngleChanged;
public virtual void OnAngleChanged() {
if (AngleChanged != null) {
AngleEventArgs e = new AngleEventArgs(m_Angle);
AngleChanged(this, e);
}
}
That's it. Now take a look at main form, how to add this user-control. Create a private variable in form1.cs.
private MyControl myControl;
In the formload function we create the control and add it to the panel.
private void Form1_Load(object sender, EventArgs e) {
myControl = new MyControl();
myControl.AngleChanged +=
new AngleChangedEventHandler(myControl_AngleChanged);
panel1.Controls.Add(myControl);
}
void myControl_AngleChanged(object sender, AngleEventArgs e) {
label2.Text = e.Angle.ToString();
}
The result now looks like this: