Windows Forms Development

Embed Size (px)

Citation preview

  • 8/9/2019 Windows Forms Development

    1/51

    Page 1 of 55 

    WINDOWS FORMS DEVELOPMENT (with an introduction to ASP.NET)

    ByDr Kieran F. Mulchrone,School of Mathematical Sciences,

    UCC

    January, 2010.

  • 8/9/2019 Windows Forms Development

    2/51

    Page 2 of 55 

    CONTENTS Developing Simple Single Form Applications ....................................................................................... 4 

    Introduction ............................................................................................................................... 4 

    Getting Started ........................................................................................................................... 5 

    Delving a little deeper .................................................................................................................. 7 

    Buttons and messageboxes ....................................................................................................... 7 

    Adding a pair of numbers .......................................................................................................... 8 

    Standard and Custom Dialog Boxes .............................................................................................. 10 

    Standard Dialog Boxes ............................................................................................................ 10 

    Custom Dialog Boxes .............................................................................................................. 10 

    Resources ................................................................................................................................ 12 

    Common Components/Controls ................................................................................................... 13 

    Button .................................................................................................................................. 14 

    Checkbox .............................................................................................................................. 14 

    RadioButton .......................................................................................................................... 14 

    ListBox, ComboBox and CheckedListBox .................................................................................... 14 

    DateTimePicker ...................................................................................................................... 16 

    ErrorProvider ......................................................................................................................... 16 

    PictureBox............................................................................................................................. 16 

    ImageList.............................................................................................................................. 16 

    ListView ................................................................................................................................ 17 

    ProgressBar ........................................................................................................................... 17 

    Various Other Controls ............................................................................................................ 18 

    ToolStrips, Menus, Serialization, Data-Binding and MDI Applications..................................................... 19 

    ToolStrips................................................................................................................................. 19 

    Menus ..................................................................................................................................... 19 

    Normal Menus ....................................................................................................................... 20 

    Context Menus ....................................................................................................................... 20 

    Serialization ............................................................................................................................. 20 

    Data Binding ............................................................................................................................. 23 

    MDI Applications ....................................................................................................................... 25 

    Introduction .......................................................................................................................... 25 

    Menu Merging ........................................................................................................................ 25 

    Document-View Architecture or Model View Controller ................................................................. 27 

    Data Binding and Enabling Menu Options ...................................................................................... 29 

    Example Problem ................................................................................................................... 29 

    Making Menus Bind Data ......................................................................................................... 30 

    Make the Form and Menu ........................................................................................................ 31 

  • 8/9/2019 Windows Forms Development

    3/51

    Page 3 of 55 

    Code the Application ............................................................................................................... 31 

    Menu Control ......................................................................................................................... 34 

    Bouncing Balls, Boids and GDI+ ...................................................................................................... 36 

    Introduction ............................................................................................................................. 36 

    Basic GDI+ ............................................................................................................................... 36 

    Introduction .......................................................................................................................... 36 

    A Basic Example .................................................................................................................... 37 

    Tools of the Trade .................................................................................................................. 38 

    Coordinate Systems and Transformations ..................................................................................... 40 

    Introduction .......................................................................................................................... 40 

    Device Coordinates ................................................................................................................. 41 

    Page Transformation ............................................................................................................... 41 

    World Transformations ............................................................................................................ 42 

    Exercise 3.1 Create a graph of the above data in a form. ............................................................... 46 

    Images, Mice, Keyboards and Panning .......................................................................................... 46 

    Exercise 3.2 Modify the above code so that the image jars at each end and top and bottom i.e. the

    image cannot escape from the panning window. ............................................................................ 49 

    Animations and Breakout ............................................................................................................ 49 

    Exercise 3.3 Modify the code so that instead of drawing a line with the mouse move event it can be used

    to move the ball into a suitable starting position (i.e. inside the frame) by the user. Add code which

    checks to see if the paddle has been moved to a position to take the bounce and if not put up a suitable

    message for the user ie. YOU LOSE!! ............................................................................................ 51 

    The Chaotic Waterwheel and Letting Mathematica to do the Hard Work ................................................ 52 

    Introduction ............................................................................................................................. 52 

    Using Mathematica in .NET ......................................................................................................... 52 

    IMathLink and IKernelLink ....................................................................................................... 52 

    MathLinkFactory ..................................................................................................................... 52 

    Using IKernelLink ................................................................................................................... 53 

    Using the MathKernel Object .................................................................................................... 53 

    Organising our Work in Mathematica ............................................................................................ 54 

    Solving the Chaotic Waterwheel Problem ...................................................................................... 54 

    Implementing the Solution of the Chaotic Waterwheel Problem ........................................................ 54 

    Patterns and the Swift-Hohenberg Equation ...................................................................................... 55 

    Data Access ................................................................................................................................. 55 

    A Very Brief Tour of ASP.NET.......................................................................................................... 55 

  • 8/9/2019 Windows Forms Development

    4/51

    Page 4 of 55 

    DEVELOPING SIMPLE SINGLE FORM APPLICATIONS 

    INTRODUCTION Windows forms is essentially a collection of objects and classes which work together to produce applications

    which run primarily on Windows operating systems. The form part of the .NET framework and can be

    programmed in any supported language, although here C# is used. Together with the class collection there

    is an IDE (Visual Studio) which simplifies much of the development process. In this chapter simple

    applications are developed as a means of introduction to the IDE. It is assumed throughout that a firm

    grounding in the C# language has been obtained previously by the reader. Much of what the IDE does (e.g.

    production of code automatically) behind the scenes should be readily understood in terms of raw C# code,

    i.e. you should be able to program this up manually without too much difficulty except perhaps that you

    may not be able to remember all of it too easily.

    FIGURE 0-1 THE DEFAULT SITUATION AFTER CREATING A WINDOWS FORMS APPLICATION.

  • 8/9/2019 Windows Forms Development

    5/51

    Page 5 of 55 

    There is a great amount of detail associated with Windows Forms programming. This text will not be a direct

    transcription of the help file associated with Visual Studio. Key ideas will be introduced here but you may

    have to consult supplementary materials.

    GETTING STARTED 

    To begin, let’s create the default Windows Forms project, do nothing and see what we get for free. I’m usingVisual C# 2008 Express Edition (it’s free to download!).

    1) Select the File -> New Project menu option.

    2) Select the Windows Forms Application and type in a project name (I chose HelloWorld).

    3) Click OK.

    You are presented with something quite different to what you may be used to with console applications (see

    Figure 0-1). Turn your attention to the solution explorer. There are two *.cs files one is called Form1.cs and

    one is called Program.cs.

    Form1.cs can be viewed in one of two ways 1) designer mode – this is a visual interactive way of coding and

    2) code mode – looking directly at the code. These are two views of the same thing. Modifying one modifiesthe other and vice versa. Different people find it easier to work in different ways, but at some stage code

    has to written. You can switch between the different modes by making sure Form1.cs is selected in the

    solution explorer and using the menu option View -> Code (F7) or View -> Designer (Shift + F7). The code

    in Form1.cs is as follows:

    usi ng Syst em;usi ng System. Col l ect i ons. Gener i c;usi ng Syst em. ComponentModel ;usi ng Syst em. Data;usi ng Syst em. Dr awi ng;usi ng Syst em. Li nq;usi ng Syst em. Text ;usi ng Syst em. Wi ndows. For ms;

    namespace Hel l oWor l d{

    publ i c par t i al cl ass For m1 : For m  {

    publ i c Form1( ){

    I ni t i al i zeComponent ( ) ;}

    }} 

    This seems strange at first sight. There is a method called I ni t i al i zeComponent ( ) ;  which is not defined

    anywhere. The explanation is simple. Note that the class Form1 is being prefixed by the keyword partial and

    this means that the class can be defined over multiple files. Next note that if you click on the X next to the

    Form1.cs icon in the solution explorer there is a file called Form1.Designer.cs. This file completes the

    definition of the Form1 class.

    Open Form1.Designer.cs and click on the “Windows Form Designer Generated Code” text to fully expose all

    code in the file. The code is:

    namespace Hel l oWor l d{

    par t i al cl ass For m1{

    / / /

  • 8/9/2019 Windows Forms Development

    6/51

    Page 6 of 55 

    / / / Requi red desi gner vari abl e./ / /

      pr i vat e Syst em. ComponentModel . I Cont ai ner components = nul l ;

    / / /   / / / Cl ean up any r esour ces bei ng used.

    / / /   / / / t r ue i f managed r esour ces shoul d be di sposed;

    other wi se, f al se.   pr ot ect ed over r i de voi d Di spose(bool di sposi ng)

    {i f ( di sposi ng && ( component s ! = nul l ) ){

    components . Di spose( ) ;}base. Di spose( di sposi ng) ;

    }

    #r egi on Wi ndows For m Desi gner gener at ed code

    / / /   / / / Requi r ed method f or Desi gner suppor t - do not modi f y

    / / / t he cont ent s of t hi s met hod wi t h t he code edi t or ./ / /

      pr i vat e voi d I ni t i al i zeComponent ( ){

    t hi s. components = new Syst em. ComponentModel . Cont ai ner ( ) ;t hi s. AutoScal eMode = Syst em. Wi ndows. Forms. AutoScal eMode. Font ;t hi s. Text = "Form1";

    }

    #endr egi on}

    }

    Now we see the definition of I ni t i al i zeComponent ( )  and that nothing magical is occurring.

    The idea here is subdivide the code into that concerned with visual presentation (Form1.Designer.cs) and

    that concerned with functionality or behaviour or real programming (Form1.cs). The recommended way ofediting/creating the visual interface is by using the Designer Interface (although you can directly edit the

    code, this is tedious and error-prone). Form1.cs is where the real coding occurs, however in this visual

    environment this usually amounts to small segments of code executed in response to events.

    The other file Program.cs corresponds to that in a console application and is where the application begins.

    Its code is as follows:

    usi ng Syst em;usi ng System. Col l ect i ons. Gener i c;usi ng Syst em. Li nq;usi ng Syst em. Wi ndows. For ms;

    namespace Hel l oWor l d

    { st at i c cl ass Pr ogr am  {

    / / /   / / / The mai n ent r y poi nt f or t he appl i cat i on.

    / / /   [ STAThr ead]

    stati c voi d Mai n( ){

    Appl i cat i on. Enabl eVi sual St yl es() ;Appl i cat i on. Set Compat i bl eTextRender i ngDef aul t ( f al se) ;

  • 8/9/2019 Windows Forms Development

    7/51

    Page 7 of 55 

    Appl i cat i on. Run( new For m1( ) ) ;}

    }} 

    Run the application now as you would any application. We get a simple form which does nothing. However ti

    can be resized and moved around the screen and it has a caption along the top of “Form1”.

    Exercise 1.1 Can you directly modify the code to change the caption of the Form?

    DELVING A LITTLE DEEPER 

    BUTTONS AND MESSAGEBOXES There are two types of entities that can be added to a form (and we will use both in this section). A control

    has a visual appearance at run time such as a button to initiate an action, or a text box for inputting data or

    a label for displaying text. On the other hand a component is non-visual (cannot be seen at runtime). Both

    entities are object instances and support properties, methods and event. Sometimes I may use the terms

    interchangeably as they are essentially identical form a coding perspective.

    Following on from the application created previously we add some functionality in this section. First let’s

    consider the objects being used in the code listed above. Form1 is derived from a base class called Form.This automatically provides access to a rich collection of behaviours (some of which we will learn along the

    way). In addition there are events generated by the operating system (though the user) which the form may

    be interested in subscribing to (it is the programmer who decides on this behaviour).On the other hand in

    the Program.cs file we access some methods of the static class Application. For the moment the important

    line here is:

    Appl i cati on. Run(new For m1() ) ;  

    This line creates a new Form1 object and then passes it as an argument to Run() to get the application

    going.

    Let’s now add a component to the form. A component is an object with a visual aspect, properties and

    methods. Additionally just like a form each component may wish to subscribe to particular events. Let’s adda button component to our form and wire up an event.

    1)  In the designer view click on the toolbox located on the left hand side (usually). You may want to

    pin it.

    2)  Here you can see the bewildering array of components that come for free with visual studio (there is

    a lucrative business in developing components for software development companies).

    3)  Click to select the button control and then drag it into place on the form. It is called button1 by

    default. By the way it is good practice to rename components straight away as it can be confusing

    dealing with lots of button1, button2 etc. components. Names should be meaningful and it is also

    important to change the name immediately because it is used by default in code related to events.

    Thus things can get very confusing very quickly if they are changed later on in the development

    process.

    Take a look at the file Form1.Designer.cs. Code relating to the button has been added to the “Windows Form

    Designer Generated Code” section.

    We can modify the properties of either the Form1 or Button1 using the properties section. If you cannot see

    it then right click button1 and select properties from the menu. If button1 is select it displays it’s properties,

    if Form1 is selected it displays it’s properties. There are four buttons at the top of the properties section

    which represent from left to right 1) categorised, 2) alphabetical, 3) properties view of the properties; the

    fourth button looks like a lightening flash and displays a list of events the component (or form) is usually

    interested in. As we saw from the previous course we can hook any object up to any event (i.e. Microsoft

  • 8/9/2019 Windows Forms Development

    8/51

    Page 8 of 55 

    are just guiding us a little here). Change the name property to btHello (it is a useful convention to keep the

    first few letters of the name to indicate the type of component being used – bt == button). Change the text

    property to ‘Hello’ and note that it updates straight away in the designer, this is WYSIWYG (what you see is

    what you get) designing.

    Next we need to hook up an event. The most common thing that happens is that the user clicks on it with

    the mouse pointer. Make sure the button is selected in the designer and go to the events section of the

    properties area (i.e. selected the lightning bolt). A long list of events to which the button can subscribe is

    displayed. Find the event called click. Now in the space opposite it you can type the name of the method

    (anything you like) or you can double click in the space and the event handler is automatically named as a

    combination of the component name and the event (in my case btHello_Click(object sender, EventArgs e)).

    You will be automatically taken to the section in Form1.cs where the code to execute when the event occurs

    should be written. However, if you look in Form1.Designer.cs you should find the code hooking up the

    event:

    t hi s. btHel l o. Cl i ck += new  Syst em. EventHandl er ( t hi s. btHel l o_Cl i ck) ;  

    this should seem familiar. btHello publishes a Click event and the btHello_Click wants to be informed when it

    occurs. Here is my code:

    pri vat e  voi d  bt Hel l o_Cl i ck( obj ect   sender, EventAr gs  e){

    Di al ogResul t   d = MessageBox. Show( "You cl i cked bt Hel l o" ,"Cl i ck occur r ed" ,MessageBoxBut t ons. OKCancel ,MessageBoxI con. Excl amat i on,MessageBoxDef aul t But t on. But t on1) ;

    i f   ( d == Di al ogResul t . Cancel )MessageBox. Show( "You Cancel l er " ) ;

    I am using the static method MessageBox.Show() to display some information for the user. There are 21

    overloads to this method and you can have as little or as much control over its appearance as you require.

    You should play with it a bit. The action a user takes in regards to a MessageBox is returned as DialogResult

    object which simply tells you which button on the MessageBox was clicked. You can then decide what action

    to take after that, I have just taken the senseless action of displaying another MessageBox if they press the

    Cancel button.

    ADDING A PAIR OF NUMBERS Let’s create a very simple application now which expects the user to input two numbers and then the result

    of adding them together is displayed. This covers basic interactions with users. Next we need to get input

    from the user. This involves adding more components (often referred to as controls) to the existing form

    and it is probably worthwhile briefly mentioning layout. Good layout of controls on Forms makes the user’s

    experience more pleasurable and Visual Studio provides a number of tools to support this activity. You can

    use the Tools -> Options Dialog Box to modify how the IDE works. Select “Windows Forms Designer” in the

    left panel and in LayoutMode you can specify SnapToGrid (all controls are aligned with the grid) or

    SnapToLines (controls are easy to align). You can also specify the grid size (default 8 by 8), whether to snap

    to the grid or even show the grid. Annoyingly, changes made here do not show up until you restart visualstudio. There are many options available under the Format menu to help you align, size and space

    components is an aesthetically pleasing manner.

    Another point is that users expect that by pressing the tab key the focus moves from component to

    component in a logical manner (by focus, I mean when a component has focus then any input (e.g.

    keyboard) is directed to that component). Ordering of this tabbing process is controlled by select the View -

    > Tab Order menu option and by clicking the components in the order you would like the tabbing to follow,

    it is done.

  • 8/9/2019 Windows Forms Development

    9/51

    Page 9 of 55 

    The original form was named Form1 by default. Let’s rename it to frmAddNumbers; this is more descriptive.

    Now lets get down to business. Modify btHello to make its text read “Calculate”. Change the Form caption to

     “Add Numbers”. Select the TextBox component and draw two onto the form. Name them txtNum1 and

    txtNum2. These will take the user input. Create two label controls called lblNum1 and lblNum2 which are

    used to describe the purpose of the TextBoxes. Change their text to read First Number: and Second

    Number: respectively. Finally we need somewhere for the answer to be placed. Place a suitably name Label

    and TextBox on the Form (lblAnswer, txtAnswer). Make the TextBox readonly (properties) so that the

    answer can’t be modified. Make sure the tab order is logical.

    The code is in response the click event of the Button component. The idea is that the user enters two

    numbers and then clicks calculate and the answer appears in the txtAnswer TextBox. There is huge scope

    for the user to make mistakes, but let’s not worry about that yet. Here’s the code

    pri vate  voi d  bt Hel l o_Cl i ck( obj ect   sender , EventAr gs  e){

    doubl e  num1 = Convert . ToDoubl e( t hi s. t xtNum1. Text) ;doubl e  num2 = Convert . ToDoubl e( t hi s. t xtNum2. Text) ;doubl e  answer = num1 + num2;t hi s. t xtAnswer. Text = s t r i ng. Format ( "{0: ##. 00}", answer ) ;

    Look up composite formatting or formatting types on the help system for more information on formatting

    with string.Format.

    This code works if the user cooperates. If the user does not cooperate i.e. fails to enter a number then the

    code fails. So what can we do? I hate to say it, but you can spend a huge amount of time trying to second

    guess the user and cattle-railing them into a particular course of action. Anyway we have a number of

    options available to us:

    1)  Use the exception mechanism to catch these errors and give appropriate feedback.

    2)  Use the MaskedTextBox for user input which essentially control the input side of the task.

    3)  Use validation/error controls to catch errors and give feedback.

    Exercise 1.2 Implement methods 1 and 2 above for catching user errors.

    We will use the validation/error control mechanism. Drop an Error Provider component on to the form.

    Notice that there is no visual representation on the form only a red icon on a grey bar beneath it. This is

    because this is a component in the strict sense as opposed to a control. Change it’s name to errorProvider.

    Next implement the “validated” event for both the txtNum1 and txtNum2 controls. This event occurs (is

    raised) after the content of the control has been validated (validation should occur in the Validating event –

    no need to worry about this now). In each event put code similar to the following:

    doubl e  d;bool   bTest = doubl e. TryParse( t xt Num1. Text , out   d ) ;i f   ( bTest == true)

    t hi s. er r or Provi der . Set Er r or ( t xtNum1, " ") ;el se

    t hi s. er r or Provi der . Set Er r or ( t xtNum1, "Thi s f i el d must cont ai n a number " ) ;  

    here we check to see if the text in the textbox can be converted to a double. If it can use errorProvider

    SetError method to assign an empty string associated with txtNum1, if it is erroneous set it to an error

    message. Porivde similar code for txtNum2. Play with this app now for a while. Notice that you can still click

    the Calculate Button and generate an error. We can avoid this by doing modifying the click code as follows:

    i f   ( ( ( er rorProvi der. Get Er ror( t xtNum1) ) . Lengt h ! = 0) | |( ( er r or Provi der . Get Er r or ( t xtNum2) ) . Lengt h ! = 0) )

    {MessageBox. Show( "I nput must be corr ected bef ore cal cul ati on can occur " ) ;

  • 8/9/2019 Windows Forms Development

    10/51

  • 8/9/2019 Windows Forms Development

    11/51

    Page 11 of 55 

    Naturally when we write our own applications there will be many instances when the standard dialogs will

    not fit our purpose. Thus the need arises frequently to create our own custom dialogs. .NET provides plenty

    of support for this endeavour. You should have noticed by now that all our dialogs and message boxes

    behave in such a way that until the user responds to the dialog nothing else can happen in the application.

    This is called modal behaviour. There is also the possibility of modeless behaviour (i.e. you can do other task

    while a dialog is open), but this is only warranted quite rarely.

    A custom dialog is essentially a form customised to behave in a modal manner. As a simple but contrived

    example suppose we wish to have a Get Name Dialog. Create a new form in the last project and name it

    dlgGetName (right-clickt he project name and select add new item – select windows form). Add OK (btOK)

    and Cancel (btCancel) Buttons. In the form set the AcceptButton property to btOK (this means that pressing

    the enter key is the same as clicking on the OK button) and set the CancelButton property to btCancel (this

    maps pressing the escape key to pressing the cancel button). Add a text box (txtName) and label. Wire up

    the click events of the buttons as follows:

    pri vat e  voi d  btOK_Cl i ck(obj ect   sender, EventAr gs  e){

    t hi s. Di al ogResul t = Di al ogResul t . OK;t hi s. Cl ose( ) ;

    }

    pri vate  voi d  btCancel _Cl i ck( obj ect   sender, EventAr gs  e){

    t hi s. Di al ogResul t = Di al ogResul t . Cancel ;t hi s. Cl ose( ) ;

    Note that by default the controls on a form are private. Hence we cannot read the value of the txtName

    textbox directly. It is a good idea to wrap it in a property. The code in dlgGetName is:

    publ i c  s t r i ng  t heName{

    get   { return  t xt Name. Text ; }set   { txt Name. Text = val ue; }

    }publ i c  dl gGet Name( )

    {I ni t i al i zeComponent ( ) ;/ / i ni t i al i se to bl ank st r i ng/ / must be af t er I ni t i al i zeComponentt heName = "" ;  

    Let’s put a property called name into our dialog. On the original form put a button called btGetName. Wire

    up the click event and code as follows:

    pri vat e  voi d  bt Get Name_Cl i ck( obj ect   sender, Event Ar gs  e){

    dl gGet Name  g = new  dl gGet Name( ) ;/ / usi ng ShowDi al og makes i t modal

    Di al ogResul t   d = g. ShowDi al og( ) ;i f   ( d == Di al ogResul t . OK){

    MessageBox. Show( s t r i ng. Format ( "You entered {0}", g. t heName), "Get NameReport " ) ;

    }} 

    Using ShowDialog() makes it modal. If Show() were used then it would be modeless.

  • 8/9/2019 Windows Forms Development

    12/51

    Page 12 of 55 

    Of course the perennial problem with all of this is making sure the user is doing what they are supposed to

    do. Thus a common task in custom dialogs is double checking that the data entered is valid – a process

    called validation. We saw earlier how to do this with an ErrorProvider control in the Validated event. The

    Validated is really the last part of the validation process and if this event occurs then it means that

    validation has been completed successfully. Our previous implementation kind of side stepped the validation

    process. Here’s how it is supposed to work.

    1)  When moving focus from a one control to another and both controls have CausesValidation set to

    true (the default setting) the Validating event is raised.

    2)  Implement the Validating event for each control you need to check. If the input is valid do nothing –

    if it is incorrect use the incoming e argument (CancelEventArgs e) to specify this e.g. e.Cancel =

    true. This prevents the user from progressing and focus remains in the control they have put bad

    data into.

    3)  Naturally you should always set the Cancel button’s CausesValidation property to false so that the

    user can exit the dialog at any time.

    Of course this approach can drive the user crazy if they don’t know what’s wrong or they may want to fill in

    everything else and then come back to the problematic input. The approach is flexible and you should reflect

    on which way is best.

    Exercise 1.4 Create a dialog which gets the user’s firstname, surname, date of birth and IQ. Make sure the

    data is completely validated.

    RESOURCES This is a fairly advanced topic and could easily be worth a whole chapter to itself. Resources are binary data,

    text files, audio or video files, string tables, icons, images, XML files, or any other type of data that your

    application requires. The general approach is to store these resources inside the application executable (best

    performance) or as a separate file. This all happens when the application is built. This approach also has

    implications for software localisation. Using string tables the text assigned to labels, form headings,

    message boxes etc. can be changed into a different language simply by changing the associated resource

    file. There is excellent support for this type of activity in Visual Studio. However, this is beyond the scope of

    the present document. Using resources prevents errors due to images not being present or not being in the

    expected place etc.

    Let’s add some resources to our project. Key resources for a project are stored under the project name ->

    Properties -> Resources.resx, then right click and select open. You should be presented with the following

    screen.

  • 8/9/2019 Windows Forms Development

    13/51

    Page 13 of 55 

    FIGURE 0-2 ADDING RESOURCES TO A PROJECT

    Concentrating on the central screen area, then on the left hand vertical panel the resource tab should be

    selected. Along the top the first button allows you to select the type of resource to be added (above it is set

    to images). If you select the arrow on this button the options are Strings, Images, Icons, Audio, Files and

    Other. The next button is entitled “Add Resource”. If you click on the arrow the options are Add Existing File,

    Add New string, New Image and Add New Text File. Typically most resources are copied from existing files.

    Visual Studio (full edition) ships with a large collection of ready to use resources. They are usually located in

    c:\Program Files\Microsoft Visual Studio 2009\Common

    7\VS2008ImageLibrary\1033\VS2008ImageLibrary.zip. For the moment we will just import an image and

    create a string table. Import an image and look at the properties of it in the bottom RHS of the screen.

    Importantly, it has a name and a persistence (linked or embedded). Create a few strings. Each string has a

    name and value. We will see how to use these in the next section (by the way my image is named tmp and I

    created two strings named Hello and Doodle).

    COMMON COMPONENTS /CONTROLS 

    There are lots of components and controls available for use in development. Microsoft provide a default

    selection but third party software house provide many more which are customized for particular tasks. For

    example controls that simplify the task of interacting with a database or a control which allows users to

    input using an excel-style spreadsheet. In this section a very brief introduction to the common controls and

    components is given. You are strongly encouraged to play with them all.

  • 8/9/2019 Windows Forms Development

    14/51

    Page 14 of 55 

    BUTTON Buttons are usually used by the user to indicate a choice or initiate some course of action. On a form with

    buttons it is common that pressing the enter key automatically simulates the clicking of one particular

    button called the default button. This functionality is provided by setting the AcceptButton property of the

    Form to the Button to be automatically pressed. The accept button is then outlined more heavily to indicate

    its functionality to the user. Try it out! Buttons can display both text and images. The image associated with

    a button is set by modifying the image* properties. This happens by setting a specific image (i.e. imageproperty) or by selecting an image from an associated imagelist component.

    CHECKBOX Checkboxes have either two or three-state behaviours which is specified by setting the ThreeState property

    to false or true respectively. In two-state the CheckState property can either be CheckState.Checked or

    CheckState.Unchecked, whereas in three-state it can additionally be in CheckState.Indeterminate. Note

    Indeterminate can only be set in code and is usually used to indicate to the user that a choice has not yet

    been made. There is also an associated property called Checked which takes Boolean values and

    corresponds to the two-state behavior. The CheckedChanged or CheckedStateChanged events occur when

    the Checked or CheckedState properties change.

    Exercise 1.5 Put three checkboxes on a form and make it so that only one check box can be checked at any

    one time. (Note you should actually use RadioButton controls for this they are designed to support this

    behavior, it is actually very difficult/impossible reproduce the behavior with check boxes).

    RADIOBUTTON Radio buttons are designed to work in packs. That is two or more radio buttons in a single container item

    (i.e. on a form, in a group box) act together such that only one button can be selected at any one time (i.e.

    the behavior requested in the last exercise). The value of Checked Boolean property can be used to

    determine the choice of the user. There is a CheckedChange event like that of the CheckBox but it is best

    practice to use these controls as Microsoft intended.

    LISTBOX, COMBOBOX AND CHECKEDLISTBOX These items are designed to manage and display lists of data. Key operations that need to be mastered are

    the addition, selection and deletion of list elements. If you require the ability to select multiple items theneither a ListBox or CheckedListBox control are most suitable. On the other hand if space is tight on the form

    and only one selection should be made then the combo box may be best. Let’s first concentrate on the

    ListBox control.

    The elements of the ListBox are managed using the ListBox.ObjectCollection which is exposed as the Items

    property. Objects can be added to the list using the Add() method of the Items property. Use the

    DisplayMember and DisplayValue properties of the ListBox to specify which property of the objects being

    stored are displayed and the value returned.

    For a simple example, create a form and put a ListBox named lbTest, a Button named btGetSelection, a

    Button named btLoad and two RadioButtons name rbString and rbObject on it. Set the text of

    btGetSelection to “Get Selection” and similarly for the other controls. Create a LoadListBox method in the

    form class which takes bool argument as follows:

  • 8/9/2019 Windows Forms Development

    15/51

    Page 15 of 55 

    publ i c  voi d  LoadLi st Box( bool   st r i ngDat a){

    / / r emove any exi st i ng datal bTest. I tems. Cl ear( ) ;i f   ( st ri ngDat a){

    l bTest . I t ems. Add( "Cork" ) ;l bTest . I t ems. Add( "Dubl i n" ) ;

    l bTest . I t ems. Add( "Gal way") ;l bTest . I t ems. Add( "Li mer i ck") ;l bTest . I t ems. Add( "Waterf ord") ;

    }el se{

    l bTest . I t ems. Add( new  ci t y( "Cor k", "Munst er") ) ;l bTest . I t ems. Add( new  ci t y( "Dubl i n" , "Lei nster" ) ) ;l bTest . I t ems. Add( new  ci t y( "Gal way", "Connaught " ) ) ;l bTest . I t ems. Add( new  ci t y( "Li mer i ck" , "Munst er" ) ) ;l bTest . I t ems. Add( new  ci t y( "Water f ord", "Munst er") ) ;l bTest . Di spl ayMember = "Name" ;l bTest . Val ueMember = "Pr ovi nce";

    }} 

    Where the city class is defined as:

    publ i c  c l ass  ci t y{

    pri vate  s t r i ng  name;publ i c  s t r i ng  Name{

    get   { return  name; }set   { name = val ue; }

    }pri vate  s t r i ng  pr ovi nce;publ i c  s t r i ng  Provi nce{

    get   { return  pr ovi nce; }set   { pr ovi nce = val ue; }

    }publ i c  ci t y (s t r i ng  name, s t r i ng  provi nce){

    t hi s. name = name;t hi s. provi nce = pr ovi nce;

    }} 

    Implement the click event for btLoad as follows:

    pri vat e  voi d  bt Load_Cl i ck(obj ect   sender , EventAr gs  e){

    LoadLi st Box( r bSt r i ng. Checked) ;} 

    Implement the btGetSelection click event as follows:

    pri vat e  voi d  bt Get Sel ecti on_Cl i ck( obj ect   sender, Event Ar gs  e){

    s t r i ng  sel ect i on;i f ( r bSt r i ng. Checked)

    sel ect i on = ( s t r i ng) l bTest . Sel ect edI t em;el se

    sel ect i on = (( ci t y) l bTest. Sel ectedI t em) . Pr ovi nce;MessageBox. Show( s t r i ng. Format ( "You sel ected: {0}", sel ect i on) ) ;

  • 8/9/2019 Windows Forms Development

    16/51

    Page 16 of 55 

    This implementation is not bulletproof.

    Exercise 1.6 Can you figure out how to break this application? Also provide a solution.

    Exercise 1.7 Create an application with two ListBoxes and two Buttons (captioned -> and

  • 8/9/2019 Windows Forms Development

    17/51

    Page 17 of 55 

    LISTVIEW This is essentially a sophisticated ListBox control and works in much the same way. ListView can only display

    objects which are inherited from a ListViewItem class. Place a ListView control on a form, name it

    lvStudentList and also place a ComboBox call cmbViewType. In the form load event place the following

    code:

    i mageLi st 1. I mages. Add( ( I mage) Propert i es. Resources. ASSETS) ;i mageLi st 1. I mages. Add( ( I mage) Propert i es. Resources. EXPENSES) ;i mageLi st 1. I mages. Add( ( I mage) Propert i es. Resources. CONTACTS) ;i mageLi st 1. I mages. Add( ( I mage) Propert i es. Resources. ORDPROC) ;s t r i ng  t mp = ( s t r i ng) Proper t i es. Resources. Doodl e;/ / add i t ems t o ComboBoxcmbVi ewType. I t ems. Add(Vi ew. Lar geI con) ;cmbVi ewType. I t ems. Add(Vi ew. Smal l I con) ;cmbVi ewType. I t ems. Add(Vi ew. Li st ) ;cmbVi ewType. I t ems. Add(Vi ew. Detai l s ) ;/ / make sure f i rst i t em i s sel ectedcmbVi ewType. Sel ectedI ndex = 0;/ / set up Li st Vi ew t o connect ot i mage l i stl vSt udent Li st . Lar geI mageLi st = i mageLi st 1;l vSt udent Li st . Smal l I mageLi st = i mageLi st 1;/ / Add I t ems t o Li st Vi ew

    Li stVi ewI t em l vi = new  Li stVi ewI t em( ) ;l vi . Text = "Ki er an";l vi . SubI t ems. Add( "Mul chrone") ;l vi . SubI t ems. Add( "42" ) ;l vStudentLi st . I tems. Add( l vi ) ;l vSt udent Li st . I t ems[ 0] . I mageI ndex = 0;l vi = new  Li stVi ewI t em( ) ;l vi . Text = "J ohn" ;l vi . SubI t ems. Add( "MacCar t hy") ;l vi . SubI t ems. Add( "40" ) ;l vStudentLi st . I tems. Add( l vi ) ;l vSt udent Li st . I t ems[ 1] . I mageI ndex = 1;l vi = new  Li stVi ewI t em( ) ;l vi . Text = "Bobby";l vi . SubI t ems. Add( "Skywal ker ") ;l vi . SubI t ems. Add( "35" ) ;

    l vStudentLi st . I tems. Add( l vi ) ;l vSt udent Li st . I t ems[ 2] . I mageI ndex = 2;/ / add col umns f or t he detai l s vi ewl vSt udent Li st . Col umns. Add( "Fi r st Name", 100) ;l vSt udent Li st . Col umns. Add( "Sur name" , 100) ;l vSt udent Li st . Col umns. Add( "Age", 100) ;  

    Use the ComboBox to switch view types by responding to the SelectedIndexChanged event.

    pri vat e  voi d  cmbVi ewType_Sel ect edI ndexChanged( obj ect   sender, Event Ar gs  e){

    l vSt udent Li st . Vi ew = ( Vi ew) cmbVi ewType. Sel ectedI t em;} 

    PROGRESSBAR Exercise 1.8 Figure out how to use the ProgressBar control.

  • 8/9/2019 Windows Forms Development

    18/51

    Page 18 of 55 

    VARIOUS OTHER CONTROLS A large variety of controls exist. Check out some of the container items such as group boxes and tab

    controls as they can make form layouts much more appealing to the user.

    Exercise 1.9 Can you figure out how to use the TreeView control?

  • 8/9/2019 Windows Forms Development

    19/51

    Page 19 of 55 

    TOOLSTRIPS, MENUS, SERIALIZATION, DATA-BINDING AND MDI 

    APPLICATIONS 

    TOOLSTRIPS In graphical applications menus and toolstrips (aka toolbars) are essential and expected components of the

    interface. The .NET framework provides excellent support for these elements. In this example we write

    programme to show off some of its capabilities. Although in a normal application the result of clicking a

    menu of toolstrip item is some useful calculation, here we just use MessageBox displays to indicate the

    selection has been interpreted correctly.

    Begin with a blank form. Place a ToolStrip control on the form and rename it tstrMain. In the properties of

    the tstrMain go to the Items property and select the Button with the dots at the RHS. You should see a

    dialog box as follows:

    Add one of each item type: Button, Label, SplitButton, DropDownButton, Separator, ComboBox, TextBox

    and ProgressBar. You can modify the properties of each item here and also remove and change the order in

    which the items appear. Click OK to finish.

    Each item added is now visible on the tstrMain control on the form. You can select each item and modify its

    properties as you would with any control. You can also respond to events. If you care to look in the Designer

    code file you will see the programmatic equivalent of your interactive modifications.

    Exercise 2.1 Add the items “One”, “Two”, “Three” to the ToolStrip ComboBox. Add three corresponding

    menu options to the DropDownButton control.

    MENUS 

  • 8/9/2019 Windows Forms Development

    20/51

  • 8/9/2019 Windows Forms Development

    21/51

    Page 21 

    0-1 SERI

    In any file

    usi ng  Syusi ng  Sy

    In order

    example

    f 55 

    LIZATION A

     where Serial

    t em. Runti mt em. Runti m

    o use our o

    onsider the f 

    S THE INTER 

    ization is use

    . Ser i al i zat

    . Ser i al i zat

     jects with th

    llowing code

    FACE BETWE

     you must in

    i on;i on. Format t

    e Serializatio

     example:

    EN THE DAT

    clude the foll

    er s. Bi nar y;  

    mechanism

    AND THE FI

    wing using s

     

    we must m

    LE STORAGE

    tatements:

    ke our objec

     

    ts Serializable. For

  • 8/9/2019 Windows Forms Development

    22/51

    Page 22 of 55 

    [ Ser i al i zabl e( ) ]publ i c  c l ass  Car   : I Ser i al i zabl e{

    pri vate  s t r i ng  make;pri vate  s t r i ng  model ;pr i vate  i nt   year ;pr i vate  Owner   owner ;

    publ i c  Car ( ){}

    publ i c  Car ( Ser i al i zat i onI nf o  i nf o, St r eami ngCont ext   c txt ){

    t hi s. make = ( s t r i ng) i nf o. Get Val ue( "Make" , t ypeof ( s t r i ng) ) ;t hi s. model = ( s t r i ng) i nf o. Get Val ue( "Model " , t ypeof ( s t r i ng) ) ;t hi s. year = ( s t r i ng) i nf o. Get Val ue( "Year" , t ypeof ( i nt ) ) ;t hi s. owner = ( Owner ) i nf o. Get Val ue( "Owner " , t ypeof ( Owner ) ) ;

    }

    publ i c  voi d  Get Obj ect Dat a( Ser i al i zat i onI nf o  i nf o, St r eami ngCont ext   c txt ){

    i nf o. AddVal ue("Make" , t hi s. make) ;i nf o. AddVal ue("Model " , t hi s. model ) ;

    i nf o. AddVal ue("Make" , t hi s. year) ;i nf o. AddVal ue("Owner ", t hi s. owner ) ;

    }}

    [ Ser i al i zabl e( ) ]publ i c  c l ass  Owner   : I Ser i al i zabl e{

    pri vate  s t r i ng  f i r st Name;pri vate  s t r i ng  l ast Name;

    publ i c  Owner ( ){}

    publ i c  Owner ( Ser i al i zat i onI nf o  i nf o, St r eami ngCont ext   c txt ){

    t hi s. f i rst Name = ( s t r i ng) i nf o. Get Val ue( "Fi r st Name", t ypeof ( s t r i ng) ) ;t hi s. l astName = ( s t r i ng) i nf o. Get Val ue( "Last Name" , t ypeof ( s t r i ng) ) ;

    }

    publ i c  voi d  Get Obj ect Dat a( Ser i al i zat i onI nf o  i nf o, St r eami ngCont ext   c txt ){

    i nf o. AddVal ue("Fi r st Name", t hi s. f i rst Name) ;i nf o. AddVal ue("Last Name", t hi s. l ast Name);

    }}

    There a couple of features to note (1) each class is preceded by Ser i al i zabl e( ) ]  signifying the following

    object is to be serializable and (2) each class implements the ISerializable interface which requires aconstructor with a signature like publ i c  Owner ( Ser i al i zat i onI nf o  i nf o, St r eami ngCont ext   ctxt)   for

    example and a method with signature publ i c  voi d  Get Obj ect Dat a( Ser i al i zat i onI nf o  i nf o,

    St r eami ngCont ext   ctxt) . The constructor allows construction of an object from data in the info object,

    whereas GetObjectData stores data into the info object. The typeof operator returns the System.Type of the

    object.

    Next we create a data object which holds a collection of car objects and some code to do the

    Serialization/Deserialization.

  • 8/9/2019 Windows Forms Development

    23/51

    Page 23 of 55 

    publ i c  c l ass  DataSt ore{

    pri vate  Li s t cars ;/ / can use t hi s f or addi ng, edi t i ng or subt r acti ng et c./ / shoul d somehow be connected t o t he vi sual l ayerpubl i c  Li s t Car s {

    get   { return  car s; }set   { car s = val ue; }

    }publ i c  voi d  Ser i al i ze( s t r i ng  f i l ename){

    St r eams t r = Fi l e. Open( f i l ename, Fi l eMode. Create);Bi nar yFormat t er   bf = new  Bi nar yFor mat t er( ) ;bf . Ser i al i ze( s t r , cars ) ;

    }publ i c  voi d  DeSer i al i ze( s t r i ng  f i l ename){

    St r eams t r = Fi l e. Open( f i l ename, Fi l eMode. Open) ;Bi nar yFormat t er   bf = new  Bi nar yFor mat t er( ) ;cars = ( Li s t)bf . Deser i al i ze(st r ) ;

    }} 

    It is worth noting that List is also serializable and it knows how to serialize itself (i.e. it tells each item in

    the list to serialize itself and this is a list of cars which we have coded to be able to serialize themselves, so

    everything is fine). Really all we have to worry about is the name and location of the file where information

    gets stored and we have standard dialogs to help manage most of these tasks.

    Exercise 2.4 Can you take the above code and make it work with actual data?

    DATA BINDING The previous section used serialization to manage the interface between our data and persistent file storage.

    Data binding is the mechanism provided by .NET to manage the interface between the data and the

    presentation layer (i.e. the visible bits you can see). We could of course code this from the ground up but it

    can become quite involved very quickly and even more than this, it becomes tedious. In many presentations

    the Data Binding mechanism becomes mixed up with database access. Although this is probably the most

    common commercial application, Data Binding is actually more generic than simply managing a connection

    between a database and a form. Data Binding manages the connection between a data source (arrays,

    objects, databases or whatever) and the visual display of the data.

    Objects of type BindingSource encapsulate much of the work involved in maintaining currency between form

    controls and the data source. The default property of the BindingSource is DataSource which expects to

    assigned type object (i.e. pretty much anything). The BindingSource object is then used to bind data to the

    various controls on the form. For example consider the following simple example.

    1)  Create an object of type student

    cl ass  st udent{

    pri vat e  s t r i ng  f i r st name = nul l ;publ i c  s t r i ng  Fi r st name{

    get   { return  f i r st name; }set   { f i r st name = val ue; }

    }pri vat e  s t r i ng  sur name = nul l ;publ i c  s t r i ng  Sur name{

    get   { return  sur name; }set   { sur name = val ue; }

    }

  • 8/9/2019 Windows Forms Development

    24/51

    Page 24 of 55 

    pri vat e  i nt   age = 0;publ i c  i nt   Age{

    get   { return  age; }set   { age = val ue; }

    }} 

    2) 

    Create a layout as follows:

    Where the textboxes are named txtFirstname, txtSurname, txtSurname2, txtAge and the button is

    btcheck.

    3)  Add the following code:

    / / t hi s i s t he dat a and wi l l bound t o t he cont r ol spri vat e  st udent   s = new  st udent ( ) ;publ i c  DataBi ndi ng( ){

    I ni t i al i zeComponent ( ) ;/ / do the dat a bi ndi ng/ / cr eat e a Bi ndi ngSour ceBi ndi ngSour ce  bs = new  Bi ndi ngSource( ) ;/ / assi gn a DataSourcebs. DataSour ce = s;/ / connect t he cont r ol st xt Fi r st Name. DataBi ndi ngs. Add( "Text " , bs , "Fi r st Name") ;t xt Sur name. DataBi ndi ngs. Add( "Text " , bs , "Sur Name") ;t xt Sur name2. DataBi ndi ngs. Add( "Text " , bs, "Sur Name" ) ;t xt Age. DataBi ndi ngs. Add("Text " , bs , "Age") ;

    }

    pri vat e  voi d  bt Check_Cl i ck(obj ect   sender , EventAr gs  e){

    s t r i ng  message = st r i ng. Format ( "{0} {1} {2}", s. Fi r st name, s. Sur name,s. Age) ;

    MessageBox. Show( message) ;} 

    When this application runs edit the textboxes and click btCheck. Notice how the two textboxes

    connected to the SurName update. This simple example illustrates how databinding manages the

    relationship between controls and data and keeps it current.

  • 8/9/2019 Windows Forms Development

    25/51

    Page 25 of 55 

    A slightly more complex example involves using a List or student objects as the DataSource. Here is the

    code:

    / / add some dat as l i s t . Add( new  st udent ( "Ki er an" , "Mul chrone", 42) ) ;s l i s t . Add( new  st udent ( "Mi ck", "McCar t hy", 57) ) ;

    bi ndi ngSour ce1. Dat aSour ce = sl i st ;bi ndi ngNavi gator1. Bi ndi ngSour ce = bi ndi ngSour ce1;/ / do t he dat a bi ndi ngt xt Fi r st Name. DataBi ndi ngs. Add("Text" , bi ndi ngSour ce1, "Fi r st name") ;t xt Sur name. DataBi ndi ngs. Add( "Text " , bi ndi ngSour ce1, "Sur Name" ) ;t xt Age. DataBi ndi ngs. Add( "Text " , bi ndi ngSour ce1, "Age") ;l st Surnames. DataSource = bi ndi ngSour ce1;l st Sur names. Di spl ayMember = "Sur name" ;dat aGr i dVi ew1. DataSour ce = bi ndi ngSour ce1;dat aGr i dVi ew1. Col umns[ 0] . DataPr opert yName = "Sur name" ;dat aGr i dVi ew1. Col umns[ 1] . DataPr opert yName = "Fi r st name";dat aGr i dVi ew1. Col umns[ 2] . DataPr opert yName = "Age";  

    In this example there is a list as follows:

    pri vat e  Li s t sl i st = new  Li s t( ) ;  

    Additionally, a ListBox and DataGridView control have been added. Two controls namely the bindingSource1

    and bindingNavigator1 have been included and hooked up. Play with this application. The BindingNavigator

    essentially does all the work in navigating though the list of student objects.

    BindingSource objects expose many useful properties and methods such as: MoveFirst(), MoveLast(),

    MoveNext(), MovePRevious(), AddNew(), AllowNew etc.

    Exercise 2.5 Modify the ListBox example in the previous Chapter to work with databinding.

    MDI APPLICATIONS 

    INTRODUCTION Multiple Document Interface (MDI) Applications are used when you need an application that can (1) display

    multiple instances of the same type of form simultaneously (for example MS Word can display multiple text

    documents at the same time) or (2) display multiple views of the same core application data (usually in

    different ways – for example in MS Access a single database (core data) can be viewed as a list of tables,

    queries, like a spreadsheet etc.). The uniting feature of MDI Applications is that every form in the application

    is contained within the boundaries of the main application form.

    MENU MERGING Let’s look at an example. Create a forms application as before. Rename the form MDIParent. Set the

    IsMDIContainer property to true. Notice that this effects the display of the form. This form will contain all

    other forms created in the application. Add a menuStrip with File, New, Exit and Window, Tile Vertical, Tile

    Horizontal, Cascade. Use the ShortCutKeys property to assign Ctrl + N to File->New and Ctrl + E to File-

    >Exit. Put a separator between New and Exit. Select the menuStrip and set the MdiWindowListItem towindowToolStripMenu. This means that under the window menu an automatic list of all open Child Forms will

    be maintained.

    Next create the child form (MDI Child) and it should have its own menustrip. In MDI applications you can

    have a menu for the parent and one for the child. A complication arises about how to manage the two

    menus. Windows Forms provides pretty much automatic support for solving this problem. When the parent

    form only is displayed then clearly only the parent menu is to be displayed. However when a child form is

    also displayed there should be some mixture of the child and parent menus. Let the child menu have File,

    Save and Close and another top level item Edit.

  • 8/9/2019 Windows Forms Development

    26/51

    Page 26 of 55 

    Implement the File->New menu option for MDIParent as follows:

    pri vat e  voi d  newTool St r i pMenuI t em_Cl i ck(obj ect   sender , EventAr gs  e){

    MDI Chi l d  m = new  MDI Chi l d( ) ;m. Mdi Parent = t hi s; / / a c ruci al s tep!m. Show( ) ;

    Look at what happens to the menus. I hope you agree it’s a bit of a mess. First of all, set the visible

    property of the menustrip of the child to false to get rid of the empty blue bar.

    We can solve this using the Menu Merge feature. An important related concept is menu level. Top-level

    menu items are those always visible such as File, Edit, Window etc. in a standard application. When a top

    level menu is selected then a dropdown submenu is displayed. This is the submenu-level. Sometimes a

    submenu item may also result in a flyout of more menu options (we could call it a sub-submenu level). Each

    and every menu item has a unique level. Forms contructs menus starting at the highest level (the top-level)

    and works its way down progressively to the lowest level. That is, every submenu level is constructed before

    moving down to the next level.

    Each menu item has associated with it a MergeAction and a MergeIndex property. As a menu level is

    constructed the contents of these properties determines the positioning of the menu item. The defaultvalues are MergeAction Append and MergeIndex -1. The following table briefly explains the various

    MergeAction options.

    MergeAction  Explanation 

     Append  This is the default value and means that the specified menu item is appended to theend of existing menu items at the same level.

    Insert   Insert the menu item into the existing menu items at the position specified inMergeIndex.

    MatchOnly  If a menu item exists at the same level with the same Text they merge and anylower level menu items are merged according to their MergeAction and MergeIndexvalues.

    Remove  If a menu item exists at the same level with the same Text then the menu item isexcluded from the merged menu.

    Replace  If a menu item exists at the same level with the same Text then the pre-existingmenu item is replaced in its entirety (including any sub-levels) by the new menuitem.

    The MDIParent menu items should all be set to Append and -1. This means that when only the MDIParent is

    to be displayed the menu is created as seen in the designer. For example:

    1.  Top-Level

    a.  Append File (Position 0)

    b.  Append Window (Position 1)

    2.  Sub Level

    a.  Append New to File (Position 0)

    b. 

    Append separator to File (Position 1)c.  Append Exit to File (Position 2)

    Now consider the situation with the MDIChild form. The proposed values of the relevant properties are:

    Menu Item  MergeAction  MergeIndex 

    File  MatchOnly -1File->Save  Insert 1File->Close  Insert 2Edit   Insert 1

  • 8/9/2019 Windows Forms Development

    27/51

    Page 27 of 55 

    Now the detailed procedure for menu creation is as follows:

    1.  Top-Level

    a.  MDIParent

    i.  Append File (Position 0)

    ii. 

    Append Window (Position 1)

    b.  MDIChild

    i.  MatchOnly File (Matches the MDIParent File and sub-levels to be merged).

    ii.  Insert Edit at position 1, to get File (Position 0), Edit (Position 1), Window (Position

    2).

    2.  Sub Level

    a.  MDIParent

    i.  Append New to File (Position 0)

    ii.  Append separator to File (Position 1)

    iii.  Append Exit to File (Position 2)

    b.  MDIChild

    i.  Insert Save at position 1, to get New (Position 0), Save (Position 1), separator

    (Position 2), Exit (Position 3).

    ii.  Insert Close at position 2, to get New (Position 0), Save (Position 1), Close

    (Position 2), separator (Position 3), Exit (Position 4).

    Set the properties as advised and run the application. The menu’s are now working as might be expected.

    Implement Close and Exit.

    A nice feature of MDI Applications is the ability to have multiple forms open at the same time. We can easily

    add options to modify how the child forms are arranged.

    Exercise 2.6 On the MDIParent Menu make sure that options to Tile Horizontally, Tile Vertically, Cascade

    and Arrange Icons are implemented and merge appropriately (hint: see LayoutMDI). Can you achieve the

    same functionality from a MDIChild?

    DOCUMENT-VIEW ARCHITECTURE OR MODEL VIEW CONTROLLER In previous incarnations of the windows development environment (i.e. pre .NET - Visual C++ and the

    Microsoft Foundation Classes were all the rage), the Document-View Architecture was heavily promoted.

    Since the arrival of Windows Forms this has been less so, possibly due the convergence of disparate

    development environments including Visual Basic. However it is still worth considering the Document View

    Architecture (DVA) or its modern design pattern equivalent Model View Controller.

    In a nutshell the DVA allows a single data source (i.e. the Document part) to be viewed in one or more

    ways. For example, we may have a list of coordinate data and this could be viewed as a spreadsheet or as a

    graph. Taking cognisance of Data Binding and Serialization we may come up with the following design:

  • 8/9/2019 Windows Forms Development

    28/51

    Page 28 of 55 

    Furthermore when one view makes a change to the data then that change propagates through to all other

    views. Note that windows forms provides no native support for this architecture and we will have to go it

    alone. In the next example we try to implement a DVA for a list of coordinates. Suppose that for each set of

    coordinates we can have as many graph views or data views of the underlying data as we want and that we

    also want any changes to data to be reflected in all the other views.

    We will need a class to encapsulate the coordinate:

    publ i c  c l ass  coor di nat e{

    pri vate  f l oat   x;publ i c  f l oat   X{

    get   { return  x; }set   { x = val ue; }

    }pri vate  f l oat   y;publ i c  f l oat   Y{

    get   { return  y; }set   { y = val ue; }

    }publ i c  coor di nat e(f l oat   x, f l oat   y){

    t hi s. x = x;t hi s. y = y;

    }} 

    Let’s use a List object to manage the collection of coordinate objects. Suppose now we have

    multiple views displaying the information in List object. We have a few requirements:

    1)  There must be only one List object which is referenced by each attached view (i.e.

    form).

  • 8/9/2019 Windows Forms Development

    29/51

    Page 29 of 55 

    2)  We need to be able to create a totally new view (and attendant new List).

    3)  We need to be able to create a new view based on an existing view (and there may be different

    types of new view available).

    4)  It would seem sensible to use the existing data binding mechanism to maintain currency between

    the different view types.

    One way to achieve this functionality is to have different menu items and different constructors for the

    MDIChild forms. On the MDIParent menu the New menu option means create a new View (by default it’s a

    data view - say) and List data. On the MDIChild New Graph View and New Data View menu

    options create the respective view type but no new data. We can write a different constructor depending

    on the form type being passed (a bit sloppy) or alternatively we could get our forms to subscribe to an

    interface which forces certain properties to be present. In the present case we will need a reference to a

    List and also to a BindingSource (to maintain data currency). Other approaches may also

    work.

    Assignment 1 Provide the implementation of the application discussed in the previous section. An example

    application is provided. Use the dataGridView control for displaying data and download the trail version of

    Component One Studio for Winforms and use its Chart2D component. As well as providing the functionality

     present in the application use the Form text property (i.e. the form caption) to indicate to the user which

    child forms are attached to the same data object. Implement serialization for the application so that users

    can save to file and open from file (use the filename to modify the caption of the child forms).

    The following code is useful for getting chart setup correctly.

    char t Dat a. Reset ( ) ;/ / char t Dat a i s the char t obj ectchart Data. Char t Gr oups[0] . Char t Type = Char t 2DTypeEnum. XYPl ot ;chart Dat a. DataSour ce = bs;/ / bs i s my Bi ndi ngSour ceChar t Dat aSer i esCol l ecti on  sc = char t Dat a. Char t Gr oups[ 0] . Char t Dat a. Ser i esLi st ;sc. RemoveAl l ( ) ;

    / / Add t he dat a ser i es.Chart DataSer i es  s = sc. AddNewSer i es( ) ;s. Label = "Gr aphPl ot" ;

    s. X. Dat aFi el d = "X";s. Y. Dat aFi el d = "Y";  

    DATA BINDING AND ENABLING MENU OPTIONS In many modern applications there are many ways provided for a user to perform the same tasks i.e. menu

    options, tool bars, buttons etc. As mentioned earlier on it is often good practise to only available to users’

    feasible options at any given time. Maintaining an application in this way can be a headache and may result

    in many hundreds of lines of code.

    EXAMPLE PROBLEM Data binding is one way of semi-automating the process of keeping menus enabled or disabled, checked or

    unchecked. Let’s consider the following example. Suppose we wish to graphically compare solutions

    Verhulst’s logistic population equation for two separate populations. The model is developed first by

    considering the Exponential or Malthusian population as follows:

       Where N(t) is the size of the population as a function of time t, and r is a constant rate parameter. This

    essentially states that the rate of change of the population is proportional to the size of the population. Thus

  • 8/9/2019 Windows Forms Development

    30/51

    Page 30 of 55 

    if r>0, the population grows exponentially and vice versa for rK then r

  • 8/9/2019 Windows Forms Development

    31/51

    Page 31 of 55 

    {i f   ( bi ndi ngCont ext == nul l ){

    bi ndi ngCont ext = new  Bi ndi ngCont ext ( ) ;}return  bi ndi ngCont ext ;

    }set

    {bi ndi ngCont ext = val ue;

    }}[ Des i gnerSer i al i zat i onVi s i bi l i ty( Des i gnerSer i al i zat i onVi s i bi l i ty. Cont ent ) ] / / i gnore

    thi spubl i c  Cont r ol Bi ndi ngsCol l ect i on  DataBi ndi ngs{

    get{

    i f   ( dataBi ndi ngs == nul l ){

    dataBi ndi ngs = new  Cont r ol Bi ndi ngsCol l ect i on( t hi s) ;}return  dataBi ndi ngs;

    }

    }#endr egi on

    MAKE THE FORM AND MENU Create the menu for you application as before. Create a single form application called frmLogistic and

    include the above code. Create a new menu called menuStrip with the following structure:

    Top Level  Sub Level 

    File  New Model 

    Exit 

    Model  Enter Pop1 

    Modify 

    Pop1 

    Enter Pop2 

    Modify Pop2 

    Enter Timescale 

    Generate Graphics 

    Accept the default names generated for the menu items. Finally edit the designer generated code to make

    objects of type ToolStripMenuItem be BindableToolStripMenuItem (this could take some time and patience –

    the find/replace options of the IDE may come in handy).

    Add a component one chart called chartSolution.

    CODE THE APPLICATION Let’s ignore the requirements for menu enabling and disabling and code the solution. Let’s grab all of the

    relevant data into one object.

    publ i c  c l ass  popul ati onData{

    pri vate  f l oat   p1_r 0;publ i c  f l oat   P1_R0

  • 8/9/2019 Windows Forms Development

    32/51

    Page 32 of 55 

    {get   { return  p1_r0; }set   { p1_r 0 = val ue; }

    }pri vate  f l oat   p1_n0;publ i c  f l oat   P1_N0{

    get   { return  p1_n0; }

    set   { p1_n0 = val ue; }}pri vate  f l oat   p1_k;publ i c  f l oat   P1_K{

    get   { return  p1_k; }set   { p1_k = val ue; }

    }pri vate  f l oat   p2_r 0;publ i c  f l oat   P2_R0{

    get   { return  p2_r0; }set   { p2_r 0 = val ue; }

    }pri vate  f l oat   p2_n0;publ i c  f l oat   P2_N0

    {get   { return  p2_n0; }set   { p2_n0 = val ue; }

    }pri vate  f l oat   p2_k;publ i c  f l oat   P2_K{

    get   { return  p2_k; }set   { p2_k = val ue; }

    }}

    Make an instance of this object in the form constructor called popParams.

    A custom dialog box is required for setting the parameters for each population. The code for the dialog box

    is:

    publ i c  part i al   c l ass  f r mPopDi al og  : For m  {

    pri vate  dl gData  dat a;publ i c  dl gData  Dat a{

    get   { return  dat a; }}publ i c  f r mPopDi al og( ){

    I ni t i al i zeComponent ( ) ;dat a = new  dl gData( ) ;/ / bi nd t he pr oper t i es to the cont r ol st xt R0. DataBi ndi ngs. Add("Text" , dat a, "R0") ;t xt N0. DataBi ndi ngs. Add("Text" , dat a, "N0") ;t xtK. DataBi ndi ngs. Add( "Text " , data, "K") ;

    }

    pri vate  voi d  btOK_Cl i ck(obj ect   sender, EventAr gs  e){

    t hi s. Di al ogResul t = Di al ogResul t . OK;t hi s. Cl ose( ) ;

    }

    pri vate  voi d  btCancel _Cl i ck( obj ect   sender, EventAr gs  e){

  • 8/9/2019 Windows Forms Development

    33/51

    Page 33 of 55 

    t hi s. Di al ogResul t = Di al ogResul t . Cancel ;t hi s. Cl ose( ) ;

    }}publ i c  c l ass  dl gData{

    pri vate  f l oat   r0;publ i c  f l oat   R0

    {get   { return  r 0; }set   { r0 = val ue; }

    }pri vate  f l oat   n0;publ i c  f l oat   N0{

    get   { return  n0; }set   { n0 = val ue; }

    }pri vate  f l oat   k;publ i c  f l oat   K{

    get   { return  k; }set   { k = val ue; }

    }

    In the main form the code is:

    pri vat e  voi d  enter Pop1Tool Str i pMenuI t em_Cl i ck( obj ect   sender, EventAr gs  e){

    f r mPopDi al og  f = new  f r mPopDi al og( ) ;f . Text = "Enter Par ameter s f or Popul ati on 1";Di al ogResul t   d = f . ShowDi al og( ) ;i f   ( d == Di al ogResul t . OK){

    popParams. P1_R0 = f . Data. R0;popParams. P1_N0 = f . Data. N0;popPar ams. P1_K = f . Dat a. K;

    }

    }

    pri vate  voi d  modi f yPop1Tool Str i pMenuI t em_Cl i ck( obj ect   sender , EventAr gs  e){

    f r mPopDi al og  f = new  f r mPopDi al og( ) ;f . Text = "Modi f y Parameter s f or Popul ati on 1";/ / di spl ay exi sti ng val uesf . Data. R0 = popParams. P1_R0;f . Data. N0 = popParams. P1_N0;f . Dat a. K = popPar ams. P1_K;Di al ogResul t   d = f . ShowDi al og( ) ;i f   ( d == Di al ogResul t . OK){

    popParams. P1_R0 = f . Data. R0;popParams. P1_N0 = f . Data. N0;popPar ams. P1_K = f . Dat a. K;

    }}

    pri vate  voi d  ent erPop2Tool St r i pMenuI t em_Cl i ck( obj ect   sender, EventAr gs  e){

    f r mPopDi al og  f = new  f r mPopDi al og( ) ;f . Text = "Enter Par ameter s f or Popul ati on 2";Di al ogResul t   d = f . ShowDi al og( ) ;i f   ( d == Di al ogResul t . OK){

    popParams. P2_R0 = f . Data. R0;

  • 8/9/2019 Windows Forms Development

    34/51

    Page 34 of 55 

    popParams. P2_N0 = f . Data. N0;popPar ams. P2_K = f . Dat a. K;

    }}

    pri vate  voi d  modi f yPop2Tool Str i pMenuI t em_Cl i ck( obj ect   sender , EventAr gs  e){

    f r mPopDi al og  f = new  f r mPopDi al og( ) ;

    f . Text = "Modi f y Parameter s f or Popul ati on 2";/ / di spl ay exi sti ng val uesf . Data. R0 = popParams. P2_R0;f . Data. N0 = popParams. P2_N0;f . Dat a. K = popPar ams. P2_K;Di al ogResul t   d = f . ShowDi al og( ) ;i f   ( d == Di al ogResul t . OK){

    popParams. P2_R0 = f . Data. R0;popParams. P2_N0 = f . Data. N0;popPar ams. P2_K = f . Dat a. K;

    }} 

    A custom dialog for the getting and setting the timescale is also required.

    Exercise 2.6 Implement the timescale dialog box.

    MENU CONTROL Finally we are ready to implement menu control. Note I have omitted creating a dialog box for the timescale

    you can fill in those details. Essentially we create an object with Boolean data member corresponding to

    each menu item as follows:

    publ i c  c l ass  menuStat e{

    pri vate  bool   ent erP1 = f al se;publ i c  bool   EnterP1{

    get   { return  enter P1; }

    set   { ent erP1 = val ue; }}pri vate  bool   modi f yP1 = fal s e;publ i c  bool   Modi f yP1{

    get   { return  modi f yP1; }set   { modi f yP1 = val ue; }

    }pri vate  bool   ent erP2 = f al s e;

    publ i c  bool   Ent erP2{

    get   { return  enter P2; }set   { ent erP2 = val ue; }

    }pri vate  bool   modi f yP2 = fal se;publ i c  bool   Modi f yP2

    { get   { return  modi f yP2; }set   { modi f yP2 = val ue; }

    }}

    Create an object in the Load and bind to the menu items enabled properties.

    pri vat e  voi d  f r mLogi st i c_Load( obj ect   sender, EventAr gs  e){

    popPar ams = new  popul ati onData( ) ;

  • 8/9/2019 Windows Forms Development

    35/51

    Page 35 of 55 

    ms = new  menuStat e( ) ;bs = new  Bi ndi ngSour ce( ) ;bs. DataSource = ms;Bi ndi ng  bi ndi ng = new  Bi ndi ng( "Enabl ed" , bs , "Modi f yP1") ;modi f yPop1Tool Str i pMenuI t em. DataBi ndi ngs. Add( bi ndi ng);modi f yPop2Tool St r i pMenuI t em. DataBi ndi ngs. Add( "Enabl ed" , bs , "Modi f yP2" ) ;ent erPop1Tool St r i pMenuI t em. DataBi ndi ngs. Add("Enabl ed" , bs, "Ent erP1") ;ent erPop2Tool St r i pMenuI t em. DataBi ndi ngs. Add("Enabl ed" , bs, "Ent erP2") ;

    We can know set menus to be enabled or disabled according to the values of the menuState ms object. After

    a value is changed you must call bs.ResetBindings() to propagate the change. Thus you could bind

    menuState with the BindingSource bs to toolstrip options or checkboxes or radiobuttons and changes to ms

    will coordinate the display throughout. Note that when new toolstrip items are added then you can reuse the

    esisting event handlers coded for the menu items.

    Exercise 2.7 Modify the application so that it has a toolstrip items corresponding to the controlled menu

    items above. Add control for the generate graphics menu option. Implement code to make the application

    restrict the user choices depending on where they are in the process described earlier.

  • 8/9/2019 Windows Forms Development

    36/51

    Page 36 of 55 

    BOUNCING BALLS, BOIDS AND GDI+

    INTRODUCTION In the last two chapters applications were constructed by using a potpourri of pre-existing components and

    visual elements. Essentially we were simply tacking it all together and then providing the odd bit of code

    here and there. This can be restrictive regarding what you can achieve. For example, suppose you wish to

    make a version of that classic computer game tennis (called pong)?

    GDI+ is a collection of objects which allow you to take control of the visual output from your program. We

    will begin by looking at some static visual outputs and then advance to animated outputs and some

    elementary game development.

    BASIC GDI+INTRODUCTION First there was GDI (Graphics Device Interface) which was a mainstay of Windows programming throughout

    the years. Essentially GDI abstracted the connection between a programme and the visual display. This was

    achieved through Microsoft providing an interface from the programme to a standard set of drivers, and the

    display manufacturers providing the connection from their hardware to the same set of drivers but from a

    different direction. GDI+ is an improved version of GDI which works in much the same way. Naturally .NET

    provides a selection of objects which abstracts GDI+ and most of these are present in the System.Drawing

    namespace.

  • 8/9/2019 Windows Forms Development

    37/51

    Page 37 of 55 

    The key class is the Graphics class. It is a rich and varied class and we will probe some but not all of its

    features. An object of type Graphics uses a significant resource essentially managed by the operating

    system, it is imperative that when we are finished with such an object all associated resources are given

    back to the system (this will be a feature of all our graphical activities).

    A BASIC EXAMPLE 

    Let’s begin with a simple example to draw an ellipse. Create a form and place a single button on it. Add thefollowing code to its click event handler.

    Gr aphi cs  g = t hi s. Cr eat eGr aphi cs() ;t ry{

    g. Fi l l El l i pse( Br ushes. Bei ge, t hi s. Cl i ent Rectangl e) ;}f i nal l y{

    g. Di spose( ) ;} 

    Run the code and see what happens. Resize the form and see what happens. Notice in the code we use the

    try/finally syntax which guarantees the graphics resource is disposed. A shorthand equivalent is:

    usi ng( Gr aphi cs  g = t hi s. Cr eat eGr aphi cs() ){

    g. Fi l l El l i pse( Br ushes. Bl ueVi ol et , t hi s. Cl i ent Rectangl e) ;} 

    Here g is automatically disposed. This is the using statement which is distinct from the using directive which

    is used to specify namespaces in which we are interested.

    In playing with this simple application you may have notice some behaviour which is not nice. Whenever the

    form is resized or covered and uncovered the ellipse disappears and by default is not automatically redrawn.

    The windows operating system however triggers an event each time a form needs to be redrawn and this is

    the Paint() event. Implement the paint event as follows:

    pri vate  voi d  f r mMai n_Pai nt ( obj ect   sender , Pai ntEvent Ar gs  e){

    Gr aphi cs  g = e. Gr aphi cs;g. Fi l l El l i pse( Br ushes. Bl ueVi ol et , t hi s. Cl i ent Rectangl e) ;

    This code performs very well with the cover/uncover situation but still it does not do well in the case of a

    resize. Notice that here we use the graphics object pre-created for us (and also disposed for us): we are not

    creating a new Graphics object , as we had to do in the click event.

    During the redraw, windows is only redrawing the new bits that become exposed as the window expands

    and does no redrawing at all as the window shrinks in size. We can fix (assuming that we always want the

    ellipse to fit into the form snugly) this in one of two ways. First we can simple set a style option for the form

    requesting that resize warrants a redraw as follows (put it in the load event or constructor after thecomponents are initialised):

    t hi s. Set St yl e( Cont r ol St yl es. Resi zeRedr aw, true) ;  

    This works fine but we get loads of flicker (we will fix this in a minute). The second solution is to code up the

    resize event:

    pri vat e  voi d  f r mMai n_Resi ze( obj ect   sender , EventAr gs  e){

  • 8/9/2019 Windows Forms Development

    38/51

    Page 38 of 55 

    / / thi s . I nval i date( t rue) ;/ / thi s . Update( ) ;t hi s. Ref resh( ) ;

    This works in exactly the same way (flicker included). A few words about the methods listed above.

    Invalidate() requests that a paint event be triggered, however because drawing is a resource intensive

    operation windows will often take care of other stuff first such as mouse events etc. this can lead to a lightdelay. On the other hand Update() causes the paint event to occur straight away. Note Invalidate() and

    Update() are called as a pair! Refresh() simply raps up the pair of calls into a single call.

    That flicker is very upsetting. It is caused by the fact that paint event is actually the end of a sequence of

    activities:

    1)  Erase the portion of the form to be redrawn by painting it with a windows level brush.

    2)  Sends a paint background event (usually automatically handled by the base-class implementation

    using the settings of the BackColor and/or BackgroundImage properties).

    3)  Finally the paint handler.

    The flicker is cause by constant interference between the background paint and the stuff you actually want

    painted.

    The solution is simple: set the double buffered property of the form to true. This equivalent to setting the

    following Controlstyles on for the form (the older way to achieving the same end):

    t hi s. Set St yl e( Cont r ol St yl es. User Pai nt , true) ;t hi s. Set St yl e( Cont r ol St yl es. Al l Pai nt i ngI nWmPai nt , true) ;t hi s. Set St yl e( Cont r ol St yl es. Doubl eBuf f er , true) ;

    The solution is simple and hides quite an amount of work going on behind the scenes. First of all drawing is

    condensed into the paint event (no separate background paint). Secondly, double buffering means that all

    drawing is first performed into a memory buffer (like to an array, this is very fast) and then the buffer is

    transferred directly to the screen. The combination of these two activities removes the flicker.

    TOOLS OF THE TRADE In the last section we were really only exposed to one drawing method of the Graphics objects: namely

    FillEllipse(). In this section we look at a few other tools we can use for drawing.

    COLOR Colour is a basic feature of drawing. Many colours are available as static properties of the Color [sic ] class.

    Sometimes you may wish to have more control (for example colouring a fractal image) and to this end you

    can use the static Method FromArgb which has two relevant overloads:

    Color FromArgb(int red, int green, int blue);

    Color FromArgb(int alpha, int red, int green, int blue);

    Each parameter takes and value between 0 and 255 inclusive. For red, green, blue 255 means full on and 0

    means full off and alpha is a measure of transparency: 0 is total transparency and 255 is total opacity. You

    can also check out two other enumerations related to the operating system preferences KnowColor and

    SystemColors.

    BRUSHES Brushes are used for colouring in regions of a form. In the earlier example we used the system collection

    Brushes which are by default solid colours. As these are system resource you don’t need to worry about

  • 8/9/2019 Windows Forms Development

    39/51

    Page 39 of 55 

    disposing of them. However there are many sophisticated brushes which are all derived from the Brush base

    class. If you create a Brush object then you should use the using() syntax to ensure it is disposed of after

    usage. You can check out the following classes: SolidBrush, TextureBrush, HatchBrush,

    LinearGradientBrush, PathGradientBrush. Try the following code:

    pri vat e  voi d  f r mMai n_Pai nt( obj ect   sender, Pai ntEventArgs  e){

    Gr aphi cs  g = e. Gr aphi cs;usi ng( Br ush  b = new  Hat chBr ush( Hat chSt yl e. Di vot , Col or . Dar kBl ue, Col or. Wheat) ){

    g. Fi l l El l i pse( b, t hi s. Cl i ent Rectangl e) ;}

    PENS Pens are used just as an artist would use them i.e. for drawing shape outlines or framing shapes. Pens can

    be constructed by passing wither a Brush or a Color (more common) and then optionally specifying a width.

    Other properties can be specified afterwards such as DashStyle, EndCap, StartCap (see the LineCap

    enumeration for options). There is an extreme level of flexibility. On this course we won’t go into the

    niceties.

    The width of a Pen is related to the graphics units being used (by default it is pixels). Setting the width to 0

    means that it will have a width of one of the underlying graphical device basic unit (for most displays this is

    one pixel). We will go into units in more detail later. Let’s just draw a line:

    pri vat e  voi d  f r mMai n_Pai nt( obj ect   sender, Pai ntEventArgs  e){

    Gr aphi cs  g = e. Gr aphi cs;usi ng( Br ush  b = new  Hat chBr ush( Hat chSt yl e. Di vot , Col or . Dar kBl ue, Col or. Wheat) ){

    g. Fi l l El l i pse( b, t hi s. Cl i ent Rectangl e) ;}usi ng  ( Pen  p = new  Pen( Col or. Tomat o, 0) ){

    g. Dr awLi ne( p, 0, 0, 50, 50) ;

    }

    WHAT CAN BE DRAWN?Unsurprisingly there is quite an amount of flexibility available and pretty much anything can be drawn.

    Here are some of the relevant methods, which tend largely use pens, provided by the Graphics object:

    Method Description

    DrawArc Overloaded. Draws an arc representing a portion of an ellipse specified by apair of coordinates, a width, and a height.

    DrawBezier Overloaded. Draws a Bézier spline defined by four Point structures.

    DrawBeziers Overloaded. Draws a series of Bézier splines from an array of Pointstructures.DrawClosedCurve Overloaded. Draws a closed cardinal spline defined by an array of Point

    structures.DrawCurve Overloaded. Draws a cardinal spline through a specified array of Point

    structures.DrawEllipse Overloaded. Draws an ellipse defined by a bounding rectangle specified by a

    pair of coordinates, a height, and a width.DrawIcon Overloaded. Draws the image represented by the specified Icon at the

    specified coordinates.DrawIconUnstretched Draws the image represented by the specified Icon without scaling the image.

  • 8/9/2019 Windows Forms Development

    40/51

    Page 40 of 55 

    DrawImage Overloaded. Draws the specified Image at the specified location and with theoriginal size.

    DrawImageUnscaled Overloaded. Draws the specified image using its original physical size at thelocation specified by a