Creating Controls
Lesson 1 – GDI+
-
GCI+ = .net managed implementation of GDI
System.Drawing Namespace
-
Summary
-
System.Drawing – most of classes actually involved with rendering to screen
-
System.Drawing.Design – extend design time UI
-
System.Drawing.2D – advanced visual effects
-
System.Drawing.Imaging – manipulation of image files
-
System.Drawing.Printing – print support
-
System.Drawing.Text – font manipulation
-
System.Drawing.Graphics Object
-
Principle object in rendering graphics
-
Represents drawing surface of visual element, e.g. form, control, Image, etc.
-
Can not directly instantiate – call CreateGraphics method on class deriving from Control
-
When working with Image can obtain from static Graphics.FromImage method
System.Drawing.Graphics myFormGraphics;
myFormGraphics = myForm.CreateGraphics();
Bitmap myImage = new Bitmap(“C:\\myImage.bmp”);
System.Drawing.Graphics myBmpGraphics;
myBmpGraphics = Graphics.FromImage(myImage);
Coordinates
-
Rendering occurs in region set by control bounds
-
Origin = upper left hand corner
-
Measured in screen pixels
-
Variety of structures describe location in region
-
Point – single point with int values for X and Y
-
PointF – single point with float values for X and Y
-
Size – rectangular size consisting of paired height and width values as integers
-
SizeF - rectangular size consisting of paired height and width values as float
-
Rectangle – top, bottom, left and right edges specified by int values
-
RectangleF – top, bottom, left and right edges specified by float values
-
-
Integral locations can be implicitly converted to floating-point counterparts
-
To convert floating-point to integer locations must explicitly convert each point
-
Note size structure indicate size, but not position
-
Create rectangle by supplying Size and Point (upper left hand corner)
Point myOrigin = new Point(10,10);
Size mySize = new Size(20,20);
Rectangle myRectangle = new Rectangle(myOrigin, mySize);
Drawing Shapes
-
Graphics object contains many methods to render shapes on screen
-
Those beginning Draw, e.g. DrawArc, DrawPie, draw line structures, outlines, etc.
-
Those beginning Fill, e.g. FillRegion, FillRectangle, render solid shapes
-
Methods take parms specifying coordinates and location of shape to draw. Also require object to perform rendering – a Pen for Draw… and Brush for Fill…
Colors, Brushes, Pens
-
System.Drawing.Color represent single color. Specified by 4 values – alpha which specifies transparency and Red, Green and blue values. Each value in range 0 to 255
-
Can also specify named colours, e.g. Color.Tomato
-
All brushes derive from abstract Brush class
-
System.Drawing.SolidBrush – single solid colour
-
System.Drawing.TextureBrush – fills object with an image
-
System.Drawing.Drawing2D.HatchBrush – fills with hatch pattern
-
System.Drawing.Drawing2D.LinearGradientBrush – blends 2 colours along a gradient
-
System.Drawing.Drawing2D.PathGradientBrush – render complex gradient
-
-
Only one Pen class and it cannot be inherited. When create specify colour and width
-
Use SystemColors, SystemPens and SystemBrushes class to ensure UI has same look and feel as rest of system, e.g. Highlight text colour available from System.Colors.HighlightText
Rendering
-
Always Dispose of graphics objects when finished – use a lot of resources, failure to do so -> application degredation
SolidBrush myBrush = new SolidBrush(Color.MintCream);
Graphics g = this.CreateGraphics();
Rectangle myRectangle = new Rectangle(0, 0, 30, 20);
g.FillElipse(myBrush, myRectangle);
g.Dispose();
myBrush.Dispose();
-
To render text
-
Create Font and Brush objects
-
Obtain reference to Graphics object
-
Call Graphics.DrawString specifying string, font, brush and location
-
Dispose of objects
-
-
Complex Shapes
-
Obtain reference to Graphics object
-
Create instance of GraphicsPath class
-
Add figures to GraphicsPath
-
Call Graphics.DrawPath to draw path outline or Graphics.FillPath to fill shape
-
Dispaose of Graphics object
-
-
The GraphicsPath object describes any complex closed shape or set of shapes
GraphicsPath myPath = new GraphicsPath(new Point[] {new Point(1,1), new Point(32,54), new Point(33,5)}, new byte[] {(byte)PathPointType.Start, (byte)PathPointType.Line, (byte)PathPoint.Bezier});
-
Add figures to path using methods such as
-
GraphicsPath.AddClosedCurve
-
GraphicsPath.AddElipse
-
GraphicsPath.AddPie
-
GraphicsPath.AddString
-
…
-
-
Can create figures by adding lines, arcs, curves, etc.
-
Begin by calling GraphicsPath.StartFigure
-
Add lines
-
AddArc
-
AddCurve
-
AddLine
-
-
Optionally call GraphicsPath.CloseFigure (if not called figure is closed at run time by drawing line from first point to last)
-
Lesson 2 – Authoring Controls
Inheritance
-
All controls inherit (directly or indirectly) from Control class
-
Provides low level logic for UI and common control methods
-
No code to render control
-
No code to provide unique functionality
-
-
Inherit from existing control = easiest way create new control
-
Inherits functionality and appearance
-
Can inherit from most Windows Forms controls (other than those marked sealed)
-
Use if retaining look and functionality of existing control but with some custom additions
-
Use if wish to retain functionality of existing control but a new look
-
Do not use if need radically different functionality
-
-
Inherit from UserControl
-
Single control may not provide all functionality required, e.g. want control bound to data source that shows first name, last name and phone number in separate TextBox
-
Rather than implement logic in form can group multiple Windows Form controls into single unit (User Control)
-
Sometimes called Composite Control
-
UserControl provides base functionality
-
UserControl designer allows other Windows Form controls to be added and custom functionality implemented
-
Limited customisation of UI – just configuring ands positioning constituent controls
-
-
Use when need to combine functionality of multiple existing controls and additional logic as single unit
-
-
Inherit from Control
-
Create custom control if rich UI or functionality unachievable via other inheritance mencahisms
-
Must program logic specific to control and code required to render visual representation
-
-
Additional members
-
Add to control in same way as add to class (at any access level)
-
Form hosting control has access to public members
-
Public properties are automatically displayed in Properties window (unless Browsable attribute is false)
-
[System.ComponentModel.Browsable(false)]
public int StockNumber
{
}
Create Inherited Control
-
Can either add new functionality or override members exposed by base class
public class NumberBox : System.Windows.Forms.TextBox
{
protected override void
OnKeyPress(KeyPressEventArgs e)
{
if(char.IsNumber(e.KeyChar) == false)
e.Handled = true;
}
}
-
Override OnPaint method to modify control appearance, e.g to create button rendered as string of text
public class Wowbutton : System.Windows.Forms.Button
{
protected override void
OnPaint(PaintEventArgs pe)
{
System.Drawing.Drawing2D.GraphicsPath myPath = new System.Drawing.Drawing2D.GraphicsPath();
myPath.AddString(“Wow!”, Font.Family, (int)Font.Style, 72, new PointF(0,0), StringFormat.GenericDefault);
Region myRegion = new Region(myPath);
this.Region = myRegion;
}
}
-
Note some controls, e.g. TextBox, drawn by form they exist on and not by the control itself, thus Paint() never called.
Creating UserControl
-
Create class derived from UserControl
-
Add Windows Form controls via UserControl designer
-
Expose any appropriate properties from constituent controls
-
Write custom functionality for user control
-
Constituent controls are treated as private
-
If want to allow other developers to change properties of constituent controls must selectively expose them through properties of the user control
public color ButtonColor
{
get
{
return Button1.BackColor;
}
set
{
Button1.BackColor = value;
}
}
-
Can expose entire constituent control by changing Modifiers property to desired access level. Property only available in Properties window – does not exist at runtime.
Creating Custom Control
-
Most customisable and configurable, but most time consuming to develop
-
Must write all code to render visual representation – most time-intensive part of control development
-
Default handler for Paint event is OnPaint() method
-
Coordinates measured relative to upper left corner of control
protected override void OnPaint(PaintEventArgs e)
{
Brush aBrush = new SolidBrush(Color.Red);
Rectangle clientRectangle = new Rectangle(new
Point(0,0), this.Size);
e.Graphics.FillEllipse(aBrush, clientRectangle);
}
-
When control resized ClipRectangle resized but control not necessarily redrawn. Can force redraw by using Control.SetStyle to set ResizeRedraw flag to true
-
Can manually cause redraw by calling Refesh method
Lesson 3 – Using Controls
Adding to Toolbox
-
Right click toolbox, choose Customize
-
Choose .NET Framework Components Tab and click Browse
-
Select DLL or EXE containing control
-
Control is added to toolbox
Providing Toolbox Bitmap
-
VisualStudio provide default icon bitmap for custom controls in toolbox
-
Specify custom bitmap viaToolboxBitmapAttribute class
-
Specify 16 by 16 pixel bitmap to use or
-
[ToolboxBitmap(@”C:\Pasta.bmp”)
public class PastaMaker : Control
{
}
-
Specify a type – custom control will have same Toolbox bitmap as that of specified type
[ToolboxBitmpa(typeof(Button))]
public class myButton : Button
{
}
Debugging Control
-
Controls are not stand-alone projects – must be hosted within Windows Form project while debugging
-
If control part of executable project – add new Windows Form to project to hold control
-
If control part of non-executable project (e.g. class library) – add additional project to solution to test control
Licensing
-
.NET provides built-in license management
-
Default licensing model requires any control to be licensed to have LicenseProviderAttribute applied to it
-
Specifies LicenseProvider to use for validating license
-
LicenseProvider = abstract class providing standard interface for validation
-
In control constructor call LicenseManager.Validate to return reference to valid license – if control not licensed it will fail to load
-
-
LicenseManager.Validate validates license by calling LicenseProvider.GetLicense – retrieves license and checks validity by calling LicenseProvider.IsKeyvalid
-
Validation scheme depends on LicenseProvider implementation
-
.NET Framework includes implementation of LicesneProvider called LicFileLicenseProvider
-
GetLicense method of LicFileLicenseProvider searches for text file named <FullName>.LIC (where FullName = fully qualified control name)
-
Can override to provide own validation logic
-
Implement dispose for every licensed control
-
[LicenseProvider(typeof(LicFileLicenseProvider))]
public class Widget : System.Windows.Forms.Control
{
private License myLicense;
public Widget()
{
myLicense =
LicenseManager.Validate(typeof(Widget),
this);
}
protected override void Dispose(bool Disposing)
{
if(myLicense != null)
{
myLicense.Dispose();
myLicense = null;
}
}
}
Hosting in IE
-
Every Windows Forms control can be hosted within IE
-
To host in IE, control must be installed in
-
Global Assembly cache
-
same virtual directory as HTML page it is declared in
-
-
Add to HTML page via <OBJECT> tag which specifies controls classid
-
Classid = 2 parts
-
Path to file containing control
-
Fully qualified name of control
-
<OBJECT id=”myControl” classid=”http:ControlLibrary.dll#ControlLibrary1.myControl” VIEWASTEXT>
</OBJECT>