COP4226 Assignment 3
Due Monday, 11/15
Zip your entire project and upload on the web. Exclude the
Debug and Release directories.
Submitting
Homework Online. Be sure to include any additional projects that you use,
when you submit the homework
This application will be an example of a Multiple Document Interface (MDI)
application, from Chapter 2. It will run a car race in a separate thread in
each main form. Many races can be running at the same time. The thread will run
a simulation of a race. Every second will be the equivalent of several laps.
The number of laps per second is controlled by a trackbar. Data binding will be
used to tie all of the data together. There will be a list of national drivers
and local drivers that can be added to a race. There will be data classes to
encapsulate all of these concepts.
You are all experienced programmers by now. Be sure that I cannot crash your
program. This means that you will need to implement validation appropriately.
Do not swallow exceptions! If something goes wrong, be sure that the
appropriate exception is thrown.
You are now experienced designers. Be sure that dialogs open in appropriate
places. Use docking, anchoring, splitting, minimum and maximum sizes to control
the appearance of your application. Use your base classes and user controls
from HW2 to improve the appearance of your application.
Under no circumstances should any child form access any part of a parent.
Use interfaces appropriately.
Under no circumstances may a thread access a variable that is not local to
the thread. Pass a custom class between the thread and the thread that called
it.
- Create a class for a race car driver.
- Create public properties for name, number of wins and number of
races.
- Create a public read-only property for the percentage of wins.
- Do not write a setter for this property, it is a calculated
field.
- Do not define a member variable for this field.
- Calculate the percentage from the number of wins and races.
- Modify the class so that it will broadcast a message everytime that a
property is changed. You will need to devise a way that the change to
the percentage is also broadcast, without writing a setter for the
percentage and without creating a member variable for it.
- Modify it so that if it is bound to a DataGridView then a new row can
be added at the bottom of the DataGridView.
- Override the ToString method. Display all of the data from the class
in a readable format.
- Make it serializable.
- Implement IDisposable, as discussed in class.
- Create a data class for a race.
- Create public properties for the number of laps in the race and the
driver that won the race.
- Create public, read-only properties for the number of drivers in the
race and for a list of the drivers in the race.
- Create a property that indicates if the class has been modified since
the last save or open operation.
- Add helper methods that make sense to be in the data class. If you
have an operation that processes records in the race, then that method
should be in the race class. This is known as encapsulation.
- Add additional properties as needed to improve encapsulation.
- Modify it so that if it is bound to a binding source then changes to
the race class will automatically update the binding source.
- Make it serializable.
- Implement IDisposable, as discussed in class.
- Create a modeless dialog that will be reused by all the child forms.
- Add a listbox that will contain all the national drivers. The main
form will maintain a list of national drivers. Bind the list that is
maintained by the main form to this listbox. Do not use a binding
source.
- When the mouse is clicked on the listbox, start a drag and drop
operation.
- Drop a data source for the race car driver into a groupbox on the
form. This will create a binding source. Use data binding to add and
retrieve data from the generated input elements. This area of the form
is for adding drivers that are not on the national list. I refer to
these drivers as local drivers.
- When the mouse is clicked on the groupbox, start a drag and drop
operation. (Just because an event handler is not listed in the
designer, does not mean it isn't available.)
- Add buttons for adding a national driver and adding a local driver.
- Use a custom event and custom event args class to notify the main
form that a driver is being added. Use only one custom event. The
custom event args should contain a member for distinguishing between a
local driver and a national driver (create an enumeration).
- Add a button that will copy the local driver to the national driver
list. This is the button that will be used by you to create the
national driver list the first time you run the program.
- Add a close button. When the close button is clicked, ESC is typed or
the X button is clicked, do not close the dialog, only hide it. This
will allow the modeless dialog to be reused.
- Create a MDI parent class. There is a template in VS.
- It will have a main menu already. Remove any items that you do not
need, but keep the View menu.
- It should create the modal dialog when constructed. Be sure that it
is disposed of properly (look in the designer code, you will see a
useful method).
- When the form is closed, it should serialize the current list of
national drivers.
- When the form is opened, it should try to deserialize the list of
national drivers. The first time the form is run, there will not be a
list of national drivers. You will need to run the program and add some
names to the national driver list. When you close the application, the
list will be serialized. The next time you run the app, you will be
able to see the list of national drivers in the modal dialog.
- Modify the help menu for About and Oath items. Use only one Oath
dialog and one About dialog for the entire application. Be sure they
are disposed of properly.
- Connect the Open, Save and New toolbar icons to the corresponding
menu handlers. Connect the help icon to the About handler. Remove the
unused icons.
- Add a cap lock indicator to the status bar.
- Update the state of the indicator whenever the message queue
becomes empty.
- When the cap lock key is locked, display CAP; otherwise, display
the empty string.
- Add an insert key indicator to the status bar.
- Update the state of the indicator whenever the message queue
becomes empty.
- The status bar should display INS when the mode is insert and OVR
when the mode is over write.
- Anytime there is the possiblity of data being lost, warn the user and
give three options.
- Save the data and continue the current operation.
- Do not save the data and continue the current operation.
- Cancel the current operation without erasing the contents of the
race.
- File Menu
- New - Create a new race.
- Display a new race dialog that requires the name of the race and
the number of laps in the race.
- Create a new child form using the object that was just updated in
the dialog.
- Open - Open a saved race.
- In the open file dialog, the file type list should include
Hw3 Files (*.hw3)
and All Files (*.txt)
.
- Only open files that have been serialized by this application.
- Use only one OpenFileDialog for the entire application. Be sure
it is disposed of properly.
- Save - Serialize the data in a file.
- If the data has been saved to a file before, then save it using
the same file name.
- If the data was opened from a file, then save it using the same
file name.
- If the data has not been saved before or did not come from a
file, then perform a Save As operation.
- Save As - Serialize the data in a file
- Open a file dialog to get the file name.
- Serialize the race to the file.
- Use only one SaveFileDialog for the entire application. Be sure
it is disposed of properly.
- Close - Close the active child form.
- Check for unsaved data.
- Do not call Application.Exit.
- Exit - Close all active children.
- Check for unsaved data.
- Do not call Application.Exit.
- Child Form
- Pass in the race object that was modified in the race dialog class.
- Add a data grid view.
- Bind the grid view to the drivers member of the race object.
- Do not use a binding source for this, bind directly to the
object.
- Make this a target for drag and drop. Only accept race car driver
objects.
- A new driver should be able to be added via the last row of the
grid.
- Add an area for controlling the race.
- Add three buttons: start, stop, pause.
- Add a numeric up down control for the number of laps in the race.
This should be bound to the number of laps in the race object.
- Add a label for the name of the race. This should be bound to the
name in the race object.
- Add a button for adding drivers to the race. When clicked, it
should open the modal dialog for adding a driver. The listbox in
the dialog should be bound to the national list that is maintained
by the parent. Remember, the child may not access the parent.
- The buttons control a thread that will run a race.
- Each second will represent a number of laps in the race.
- A trackbar in the progress are (below) will indicate how many
laps are done in a second.
- The thread may not access any member variables or static
variables in any class. It may pass information when it reports
progress, by passing a custom object.
- When the thread is done, increment the number of races for
all the drivers in the race and increment the number of wins
for the winner. Do not do this in the worker thread, be sure to
do it on the UI thread.
- Add an area for the progress of the race.
- Add a progress bar for the number of laps that have been
completed. Update this control as the thread runs.
- Add a tooltip to the progress bar that shows the number of
completed laps. This should be updated every time the value in the
progress bar changes. Use the tooltip from the base class.
- Add a track bar that indicates how many laps correspond to one
second in the race.
- Use a lower bound of 0 (this is the same as pausing the
thread).
- Use an upper bound of between 25 and 100 (your choice). This
is the number of laps that will elapse for each second in the
simulation.
- Initialize the track bar with a valid number other than
0.
- As the value in the track bar changes, the simulation will
run faster or slower. Remember, the thread may only access
local variables declared in the thread.
- Add a tooltip to the track bar that shows the value of the track
bar. This should be updated every time the value in the track bar
changes. Use the tooltip from the base class.
- Add an area for the winner's circle.
- Drop a race car driver data source into the area.
- Change all of the text boxes so they are read only.
- Bind it to the binding source for a race.
- Update the data with the winner of the race, when the thread
ends.
Screen Shots: Image
Folder