辅导menus、讲解C#编程语言、辅导C#、讲解Drink menu 讲解留学生Prolog|调试Matlab程序
Practice in C#
1
Practice 9. Exercise1: Using menus
In a nice little village of North Hungary, there
is a pub with a funny name. Now we write a
program for this pub.
Our application has more forms, and on the
main form, there is a menu bar.
The File menu is typical: you can open a data file containing the list of drinks and their price,
and save the booking of pub. These files are something like this:
drink_menu.txt: booking.txt
The Help menu helps you, the About gives a little information about you:
Before opening the data file, the Drink menu and Save menu items are inactive, after reading
the file, they will be active.
The effect of Drink menu is: You can see the menu of drinks – only one page in a time –, and
you can order any drink. As it is a little pub, de maximum number of a drink is 999. 2
Clicking Order button, you can order. Give error message if there is no any selection or there
is any error with pieces belonging to a selected drink. In this case, the background of wrong
textboxes becomes red. In case of correctly completed data, the program accepts the ordering,
and be the drink deselected and the textbox empty.
Click the right mouse button on Order button a context menu appears:
The effect of Bill menu item: (The bill is
in a RichTextBox.)
The effect of Pay menu item is: the bill will be empty and
the paid items are booked. Now the result is only in the
memory, but applying Save menu item, it will be write into
a file. (For each drink the name of drink, the total amount of
sold items per drink and income per drink.)
If you want to see some pictures about village, chose the Gallery menu item (as many times as
you want):Practice in C#
3
A possible solution is:
1. Design of surface (GUI)
As you see, this application consists of more
forms.
Form1 (if you want, you can rename it)
It is recommended to set fix size of the form
(FormBorderStyle and MaximizeBox
properties). The simplest way for using background image to put the picture in bin/debug folder,
and from this folder you can chose the appropriate BackgroundImage object. The best setting
of BackgroundImageLayout property is Stretch.
Put the menu bar in the form, and assign to the form an OpenFileDialog and a
SaveFileDialog control as well.
DrinkMenuForm
It is recommended to set fix size of the form as well. In this form, there is a label with a title, a
panel (pnlMenu) and a button (btnOrder). This panel will contain the drink menu, that is
these control elements will be created according to data of data-file. As you don’t know the
number of drinks, so the AutoScroll property of panel has to be true.
At first glance, we are ready with this form, but there is one more element, a
ContextMenuStrip control belonging to Order button. The main difference between menu
strip and context menu strip is, that the later one invisible by default. It will be visible when
you click the right mouse button on control belonging to this context menu strip. A context
menu strip can be put in form in the same way as menu strip, the only difference is that you
have to assign it to a context, namely to the relevant control – in our case to Order button.
(ContextMenuStrip property of btnOrder item.)
BillForm
Only one RichTextBox control – its name is: rchTxtBill. Let it be read only and don’t
allow the tabulator parking on it. 4
GalleryForm
Its controls are: pictureBox1, btnLeft, btnRight. The Text property of buttons is empty,
but they have background image.
The main question about forms is not their appearance, but how can we see them and what
happen on these surfaces. Of course, they are classes, so we have to instantiate them and ensure
their visibility.
2. Coding
Let us begin with Drink class:
class Drink {
public int OrderedQuantity { get; private set; }
public int TotalQuantity { get; private set; }
public int Income { get; private set; }
public string DrinkName { get; private set; }
public int UnitPrice { get; set; }
public Drink(string drinkName, int unitPrice) {
this.DrinkName = drinkName;
this.UnitPrice = unitPrice;
}
// During ordering the number of ordered drinks increases
public void Order(int piece) {
OrderedQuantity += piece;
}
public int Payable() {
return OrderedQuantity * UnitPrice;
}
// After paying the ordered quantity is zero again.
public void Pay() {
TotalQuantity += OrderedQuantity;
Income += Payable();
OrderedQuantity = 0;
}
public string ToPriceList() {
return DrinkName + " (" + UnitPrice + " Ft)";
}
public string ToBooking() {
return DrinkName + ";" + TotalQuantity + ";" + Income;
}
public override string ToString() {
return OrderedQuantity.ToString().PadLeft(4) + " " + Practice in C#
5
DrinkName.PadRight(33) +
Payable().ToString().PadLeft(10) + " Ft";
}
}
Hopefully you can understand this code. The only news are PadLeft(), PadRight()
methods. They serve to fill with spaces the given length if the string is shorter. However these
methods work only with Consolas and Courier fonts.
Form1 class:
This class works due to menu items. Namely you can open the data file (after choosing it), show
the drink-menu, the gallery, save the booking file, give help and give information about the
author of the program.
The questions are:
1. How can we show the drink-menu, because it is in other form, and how pass the data to this
form?
2. How can we show gallery, because it is in other form as well, and where (in which form) do
we load pictures?
Showing a form is simple. We create an instance of the form, and call its Show() or ShowDialog()
method. What is the difference between the two methods? The Show() method shows the form in a
non-modal form. This means that you can click on the parent form, moreover you can show the
form in multiple instances. ShowDialog() shows the form modally, meaning you cannot go
to the parent form.
As the Open menu item is in Form1 form, but the drink-menu is in DrinkMenuForm, so the
list of drinks have to be passed to the instance of DrinkMenuForm, namely we ask this form
to write the drink-menu.
The last question is the place of image loading. The simplest solution seems to load them in
GalleryForm. However, we want to give the possibility to show the form in multiple
instances. In this case, we would have to load the pictures many times. Therefore the best
solution is to load them in Form1 form and pass them to GalleryForm instances.
The code of class is:
public partial class Form1 : Form {
private List drinks = new List();
private List pictures = new List();6
private int numberOfPictures = 10;
public Form1() {
InitializeComponent();
this.CenterToScreen();
openFileDialog1.InitialDirectory = Environment.CurrentDirectory;
openFileDialog1.FileName = "drink_menu.txt";
saveFileDialog1.InitialDirectory = Environment.CurrentDirectory;
saveFileDialog1.FileName = "booking.txt";
}
// The pictures have to be loaded only once, so this is the task
// of form loading.
private void Form1_Load(object sender, EventArgs e) {
try {
PicturesLoading();
}
catch (Exception ex) {
MessageBox.Show("Error creating picture" + ex, "Error");
}
}
private void PicturesLoading() {
Image picture;
for (int i = 1; i <= numberOfPictures; i++) {
picture = Image.FromFile("picture" + i + ".jpg");
pictures.Add(picture);
}
}
private void openMenuItem_Click(object sender, EventArgs e) {
if (openFileDialog1.ShowDialog() == DialogResult.OK) {
StreamReader streamReader = null;
try {
string fileName = openFileDialog1.FileName;
streamReader = new StreamReader(fileName);
Input(streamReader);
drinkMenuMenuItem.Enabled = true;
saveMenuItem.Enabled = true;
}
catch (Exception ex) {
MessageBox.Show(ex.Message, "Error message for programmer");
}
finally {
if (streamReader != null) {
streamReader.Close();
}
}
}
}
private void Input(StreamReader streamReader) {
string line;
string[] data;
while(!streamReader.EndOfStream){
line = streamReader.ReadLine();
data = line.Split(';');
// Shot of plum brandy;200 Practice in C#
7
drinks.Add(new Drink(data[0],int.Parse(data[1])));
}
}
// We want one drink menu a time, so the form is shown with
// ShowDialog() method. Of course we pass the list of drinks before.
private void DrinkMenuMenuItem_Click(object sender, EventArgs e) {
DrinkMenuForm drinkMenuForm = new DrinkMenuForm();
drinkMenuForm.WriteDrinkMenu(drinks);
drinkMenuForm.ShowDialog();
}
// We allow to show more gallery a time, so the form is shown with
// Show() method after passing pictures.
private void GalleryMenuItem_Click(object sender, EventArgs e) {
GalleryForm galleryForm = new GalleryForm();
galleryForm.Pass(pictures);
galleryForm.Show();
}
private void SaveMenuItem_Click(object sender, EventArgs e) {
if (saveFileDialog1.ShowDialog() == DialogResult.OK) {
StreamWriter streamWriter = null;
try {
string fajlNev = saveFileDialog1.FileName;
streamWriter = new StreamWriter(fajlNev);
WriteToFile(streamWriter);
}
catch (Exception) {
MessageBox.Show("Error in file-writing", "Error");
}
finally {
if (streamWriter != null) {
streamWriter.Close();
}
}
}
}
private void WriteToFile(StreamWriter streamWriter) {
foreach (Drink item in drinks) {
streamWriter.WriteLine(item.ToBooking());
}
}
private void HelpMenuItem_Click(object sender, EventArgs e) {
new HelpForm().ShowDialog();
}
private void AboutMenuItem_Click(object sender, EventArgs e) {
MessageBox.Show("Made on programming course", "Information");
}
private void exitMenuItem_Click(object sender, EventArgs e) {
this.Close();
}
}8
DrinkMenuForm class:
Maybe this is the most complicated part of our program, however it is not your first dynamic
control application, so it will not be too difficult.
The tasks of this form are:
? To write the drink-menu according to the list of drinks. This means: dynamically put the
controls (checkbox, textbox, label) into the panel.
? To order drinks. Doing it, you have to pay attention to check the selection, the correct
number-format of pieces, and of course to make orders. If in any textbox there is wrong
number, so its color becomes red. You can correct this error in two ways. One of them is to
write a correct number, the other one is to deselect this item. In the latter case you have to
change the color of the textbox and make it empty. This action has to listen the checkboxchange
event.
? According to Bill menu item, you have to show the bill – it is in other form, so you have to
ask this form to write the bill.
? According to Pay menu item, you “pay” the items.
The code of the class is:
public partial class DrinkMenuForm : Form {
public DrinkMenuForm() {
InitializeComponent();
}
// The list of drinks will be used in other methods as well,
// so we have to declare it on class level.
private List drinks = new List();
// They are used for ordering. If you are smart programmer, you can solve this
// program without these two lists, but using them makes the solution simpler.
private List chkBoxes = new List();
private List txtBoxes = new List();
// The distances for placement dynamic controlls
private int left = 10, top = 10, chkXSize = 250, chkYDistance = 40,
txtXSize = 30, txtYSize = 17, txtBoxLblDistance = 5;
private int maxQuantity = 999;
internal void WriteDrinkMenu(List drinks) {
pnlMenu.Controls.Clear();
chkBoxes.Clear();
txtBoxes.Clear();Practice in C#
9
this.drinks = drinks;
CheckBox chkBox;
TextBox txtBox;
Label lbl;
// Placement of dynamic controls.
for (int i = 0; i < drinks.Count; i++) {
// chkBox
chkBox = new CheckBox();
chkBox.Location = new Point(left, top + i * chkYDistance);
chkBox.Size = new Size(chkXSize, txtYSize);
chkBox.Text = drinks[i].ToPriceList();
chkBox.TextAlign = ContentAlignment.MiddleLeft;
chkBox.CheckedChanged += new EventHandler(this.chkBox_CheckedChanged);
// txtBox
txtBox = new TextBox();
// Both locations are good.
// If you look at Designer.cs file with trying controls, you can see
// the explanation for -2 value.
//txtBox.Location = new Point(left + chkXSize, top + i * chkYDistance
-2);
txtBox.Location = new Point(left + chkXSize, chkBox.Location.Y -2);
txtBox.Size = new Size(txtXSize, txtYSize);
// lbl
lbl = new Label();
lbl.AutoSize = true;
lbl.Location = new Point(txtBox.Location.X + txtXSize + txtBoxLblDistance,
chkBox.Location.Y);
lbl.Text = "pcs";
// "put" controls on the panel
pnlMenu.Controls.Add(chkBox);
pnlMenu.Controls.Add(txtBox);
pnlMenu.Controls.Add(lbl);
// add controls to the appropriate lists
chkBoxes.Add(chkBox);
txtBoxes.Add(txtBox);
}
}
private void chkBox_CheckedChanged(object sender, EventArgs e) {
CheckBox chkBox = (CheckBox)sender;
if (!chkBox.Checked) {
int i = chkBoxes.IndexOf(chkBox);
txtBoxes[i].BackColor = Color.White;
txtBoxes[i].Text = "";
}
}
// ordering
private void btnOrder_Click(object sender, EventArgs e) {
bool isSelected = false, isWrongPcs = false;
int pcs = 0;10
for (int i = 0; i < chkBoxes.Count; i++) {
if (chkBoxes[i].Checked) {
isSelected = true;
try {
pcs = int.Parse(txtBoxes[i].Text);
if (pcs <= 0 || pcs > maxQuantity) throw new Exception();
drinks[i].Order(pcs);
txtBoxes[i].BackColor = Color.White;
chkBoxes[i].Checked = false;
txtBoxes[i].Clear();
}
catch (Exception) {
txtBoxes[i].BackColor = Color.Salmon;
isWrongPcs = true;
}
}
}
if (!isSelected) {
MessageBox.Show("There is no selected item", "Warning");
}
else if (isWrongPcs) {
MessageBox.Show("The pieces colored by red are incorrect", "Warning");
}
}
private void billMenuItem_Click(object sender, EventArgs e) {
BillForm billForm = new BillForm();
billForm.Write(drinks);
billForm.ShowDialog();
}
private void payMenuItem_Click(object sender, EventArgs e) {
foreach (Drink item in drinks) {
item.Pay();
}
}
}
BillForm class
public partial class BillForm : Form {
public BillForm() {
InitializeComponent();
}
internal void Write(List drinks) {
rchTxtBill.Clear();
foreach (Drink item in drinks) {
if (item.OrderedQuantity != 0) {
rchTxtBill.Text += item.ToString() + "\r\n";
}
}
}
}Practice in C#
11
GalleryForm class
It is simple but spectacular:
public partial class GalleryForm : Form {
public GalleryForm() {
InitializeComponent();
this.CenterToParent();
}
private List pictures = new List();
private int currentIndex;
internal void Pass(List pictures) {
this.pictures = pictures;
pictureBox1.Image = pictures[currentIndex];
}
private void btnRight_Click(object sender, EventArgs e) {
if (currentIndex < pictures.Count -1) currentIndex++;
else currentIndex = 0;
pictureBox1.Image = pictures[currentIndex];
}
private void btnLeft_Click(object sender, EventArgs e) {
if (currentIndex > 0) currentIndex--;
else currentIndex = pictures.Count - 1;
pictureBox1.Image = pictures[currentIndex];
}
}
HelpForm class:
public partial class HelpForm : Form {
public HelpForm() {
InitializeComponent();
this.CenterToParent();
}
private void HelpForm_Load(object sender, EventArgs e) {
rchTxtHelp.Text =
"File menu item:\r\nYou can open the data file containing the drink list" +
"\r\nand you can save the file containing the booking of pub " +
"(name of drinks, total amount per drinks and income per drinks)" +
"\r\n\nDrink menu menu item:\r\nYou can see the drink menu and order any drink" +
"\r\n\nGallery menu item:\r\nYou can see pictures of the village" +
" and the surrounding area. - " +
" You can open it many times and multiple instances. ";
}
}