Rudi
  • Home
  • About
  • Contact
  • VB.Net
    • Flippin
    • Calculator
    • Mine Scout
    • Slot Machine
    • Snake
    • Accounting using Child forms
  • Excel
    • Calendar 1
    • Calendar 2
    • Sudoku
    • Mine Scout
    • Tilexcel
    • ExceLudo
    • Alphabet Game
  • C# Child Forms
  • C# Struct Array

C# MDI project
C# Child forms interact

This project has a visual menu so options can be clicked or choices can be made with the keyboard. The inspiration is Quickbooks and MYOB but this project is only rudimentary. That's how programs start.
For Child forms to interact takes quite a bit of code and know how which took me a fair while to research and figure out. Fortunately, a lot of the code pops up with the built-in Intellisense and the work is reduced with copying and pasting similar code and controls.

Let's make a start to create the BIG Accounting Project. BIG stands for Business Is Good. The first form is named frmParent. Set its IsMdiContainer property to True and add a MenuStrip with the menus shown.
Picture
Picture
Picture
Picture
Add six forms.
Picture
Click frmParent and press F7 to start coding. In the using area add using System.IO;.
After { InitializeComponent() }; add the references to all the forms and variables for a Child form to send data to another Child form.
The forms are declared Public so, again, Child forms can interact. There are also array variables to store Sales and Purchases plus a variable to enable easy closing of the project.
 
    frmMenu BigMenu = new frmMenu();
    public static frmAddSale Sale = new frmAddSale();
    public static frmAddPurchase Purchase = new frmAddPurchase();
 
    public static frmListPurchases ListPurchases = new frmListPurchases();
    public static frmListSales ListSales = new frmListSales();
    public static frmBalance Balance = new frmBalance();
 
    //Arrays to store Sales and Purchases
    public static string[] strSalesText= new string[0];
    public static Single sngTotalSales = new Single();
 
    public static string[] strPurchasesText = new string[0];
    public static Single sngTotalPurchases = new Single();
 
    //Enable bulk closing
    public static bool ParentClosing = new bool();

Double click frmParent to start the Load method and enter the code to display all the forms.

      this.Size = new Size(1340, 720);

      BigMenu.MdiParent = this;
      BigMenu.Show();

      Sale.MdiParent = this;
      Sale.Show();

      Purchase.MdiParent = this;
      Purchase.Show();

      ListSales.MdiParent = this;
      ListSales.Show();

      ListPurchases.MdiParent = this;
      ListPurchases.Show();

      Balance.MdiParent = this;
      Balance.Show();

     //more to come

Make sure the IsMdiContainer property of the parent form is True then run the project.
Picture
Picture
Double click the Sale menu to bring back the form if it was closed by the user.
 
    Private void saleToolStripMenuItem_Click(object sender, EventArgs e)
    {
      Sale.Show();
      Sale.Activate();
    }

Repeat this for the Purchase menu.
 
      Purchase.Show();
      Purchase.Activate();

The other three menus do not need to activate the particular form as the user does not enter data on them.

      ListSales.Show();

      ListPurchases.Show();

      Balance.Show();

This will not bring these forms back as yet. To achieve this, we’ll cancel Closing and only Hide a form when the user closes it.

This will also preserve the data on the forms. Add the following to the FormClosing method of all the child forms except the menu.

To start a FormClosing method click the form, switch to the events flash in the Properties box and double click on FormClosing.

    private void frmAddSale_FormClosing(object sender, FormClosingEventArgs e)
    {
      if (!frmParent.ParentClosing)
      {
      e.Cancel = true;
      this.Hide();
      }
    }

This, however, means that clicking the project close button only closes one child at a time. To enable the application to close with one click, code the following for the Exit menu.
 
    private void exitToolStripMenuItem_Click(object sender, EventArgs e)
    {
      ParentClosing = true;
      Application.Exit();
    }

I'll leave it to you whether to ask: Are you sure?

Now we’ll design the Menu form. It has buttons to bring back the other forms. They could have pictures on them instead of text.

Picture
Picture

Set the ControlBox to False to hide the Minimize/Maximize/Close buttons. This prevents this form from being closed.
Double click each button and add the following codes for each button. The codes are like the parent but have to refer to the forms via the parent to access them.

      frmParent.Sale.Show();
      frmParent.Sale.Activate();
      //Ready to enter data

      frmParent.Purchase.Show();
      frmParent.Purchase.Activate();
      //Ready to enter data

      frmParent.ListSales.Show();

      frmParent.ListPurchases.Show();

      frmParent.Balance.Show();
 
      //Exit button
      frmParent.ParentClosing = true
      Application.Exit();
 
Just like the parent, the Exit button will close all forms. Add code to the Activated method for each form to space them out on the parent form.
 
      //frmAddSale_Activated
      this.Top = 0;
      this.Left = 300;
 
      //frmAddPurchase_Activated
      this.Top = 0;
      this.Left = 680;
 
      //frmBalance_Activated
      this.Top = 0;
      this.Left = 1060;
 
      //frmListSales_Activated
      this.Top = 300;
      this.Left = 0;
 
      //frmListPurchases_Activated
      this.Top = 300;
      this.Left = 500;

Design the Sale form with 2 TextBoxes and a Button. Set the MaxLength property for txtDescription to 40 characters. Set the TextAlign property of txtAmount to Right.


Picture
Copy and paste the title label from the menu to have the same font then copy all the objects and paste them onto the Purchase form. Of course, change the titles to Purchase.
Next is the Sales form.
Picture
Change the font for lstBox to Courier New, 9pt. Make the form 503 wide to fit 49 characters in the lstbox. Set the Borderstyle of lblTotal to FixedSingle, the BackColor to White, TextAlign to MiddleRight, and AutoSize to False.

Set the Modifiers property to Public for the ListBox and lblTotal to enable access from other child forms. Copy all controls and paste them to the Purchases form.
Picture
Design the Balance form. Copy lblTotal from above and paste it 3 times here. Rename the labels to the names shown. The Modifiers property should already be Public for the three white labels.
Picture
All going well all the forms can be shown, closed and shown again both via the MenuStrip or the Menu form or the ShortCut keys off the MenuStrip. The last menu item is the Cascade option to present the forms as per the earlier picture.

    private void cascadeToolStripMenuItem_Click(object sender, EventArgs e)
    {
      this.LayoutMdi(System.Windows.Forms.MdiLayout.Cascade);
    }
Picture
I want the items in the list boxes to look like this with the money lined up neatly on the right.
Sale..................................................$5.50
For the dots we'll work out the length of the text and the money and add the dots using the following method.

String of Characters
This produces a String of a character of a nominated number of Characters. Here I’m getting a string of dots and we’ll use it to pad lines in the ListBox on the Sales and Purchases forms. I did this quick little project to see the result.

Picture
   




private void btnDuplicate_Click(object sender, EventArgs e)
    {
        txtDuplicate.Text = new string('.', 20);
    }

We'll use a formula to work out the number of dots required. Double click the Add button on the Sale form.

    private void btnAdd_Click(object sender, EventArgs e)
    {
      //String to add to ListBox
      string ListText;
      double Amount = Convert.ToDouble(txtAmount.Text);
      int ListTextLength = txtDescription.TextLength + (Amount.ToString("C")).Length;
      ListText = txtDescription.Text + new string('.', 55 - ListTextLength) + Amount.ToString("C");

      //Add string to the ListBox
      frmParent.ListSales.lstBox.Items.Add(ListText);

      //Increment the arrays
      int i = frmParent.strSalesText.Length;     
      Array.Resize(ref frmParent.strSalesText, i + 2);

      //Add transaction to the arrays
      frmParent.strSalesText[i] = txtDescription.Text;
      frmParent.strSalesText[i +1] = txtAmount.Text;

      //Calculate total of all transactions
      frmParent.sngTotalSales += Convert.ToSingle(txtAmount.Text);

      //The labels below must have Modifiers set to Public on their forms

      //Add total to ListForm
      frmParent.ListSales.lblTotal.Text = frmParent.sngTotalSales.ToString("C");

      //Add total to the Balance form
      frmParent.Balance.lblSales.Text = frmParent.sngTotalSales.ToString("C");

      //Copy all to 'Add Purchase' then change all Sales to Purchases up to here
      ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

      //Calculate Balance and display on Balance form
      Single sngBalance = frmParent.sngTotalSales - frmParent.sngTotalPurchases;
      frmParent.Balance.lblBalance.Text = sngBalance.ToString("C");

      //Clear TextBoxes for next entry
      txtAmount.Text = "0";
      txtDescription.Text = "";
      txtDescription.Focus();
    }

As is mentioned in the comment, the code is copied to the Add Purchase button and Sales is changed to Purchases except the last bit. We can now make transactions.

Picture
When the application is closed it saves the data. I have done it by creating another, temporary, array. Then the number of Sales is recorded in this new array followed by the Sales and Purchases.

The new array is saved as a text file.

    private void frmParent_FormClosing(object sender, FormClosingEventArgs e)
    {
      int SalesLength = strSalesText.Length;
      int DataLength = 1 + SalesLength + strPurchasesText.Length;

      //Create DataFile array to hold number of sales and the actual sales and purchases
      string[] DataFile = new string[DataLength];

      //Record number of sales
      DataFile[0] = SalesLength.ToString();

      //Record sales
      int i;
      for (i = 1; i < SalesLength; i += 2)
        {          
          DataFile[i] = strSalesText[i - 1];
          DataFile[i + 1] = strSalesText[i];
        }

      //Record purchases
      int y = 0;
      for (int x = i; x < DataLength; x += 2)
        {
          DataFile[x] = strPurchasesText[y];
          DataFile[x + 1] = strPurchasesText[y + 1];
          y += 2;
        }
      //write the file
      File.WriteAllLines("BigAccounting.txt", DataFile);
    }

The picture shows the first four lines are Sales. The file is in the Debug folder.
Picture
Finally the file is read back in to a temporary array in the Form_Load method. The data is then fed to the Sales and Purchases arrays and the Lists and the Balance form.

      if (File.Exists("BigAccounting.txt"))
      {
        //Construct the strings for the List Boxes and Balance form
        string strText, strAmount;
        string ListText;
        int ListTextLength;

        Single sngAmount;
        int i = 0, x;
        int DataLength;
        int Sales, Purchases;

        //Temporary array
        string[] DataFile = new string[0];
        DataFile = File.ReadAllLines("BigAccounting.txt");
        DataLength = DataFile.Length;        

        //Get the number of Sales and set its array
        Sales = Convert.ToInt16(DataFile[0]);
        Array.Resize(ref strSalesText, Sales);

        //Calculate the number of Purchases and set its array
        Purchases = DataLength - Sales - 1;
        Array.Resize(ref strPurchasesText, Purchases);

        //Extract the Sales
        for (x = 1; x <= Sales; x += 2)
        {          
          strSalesText[x - 1] = DataFile[x];
          strSalesText[x] = DataFile[x + 1];

          strText = strSalesText[x - 1];
          strAmount = strSalesText[x];
          sngAmount = Convert.ToSingle(strAmount);

          //Construct Sale string to add to ListBox
          ListTextLength = strText.Length + (sngAmount.ToString("C")).Length;
          ListText = strText + new string('.', 55 - ListTextLength) + sngAmount.ToString("C");
          ListSales.lstBox.Items.Add(ListText);

          //Add the amount to the Sales total
          sngTotalSales += sngAmount;
        }
        //Show the Sales total in the Sales form Total Box and also the Balance form
        ListSales.lblTotal.Text = sngTotalSales.ToString("C");
        Balance.lblSales.Text = sngTotalSales.ToString("C");
        
        //Extract purchases which start at Sales + 1
        for (x = Sales + 1; x < DataLength - 1; x += 2)
        {
          strPurchasesText[i] = DataFile[x];
          strPurchasesText[i + 1] = DataFile[x + 1];

          strText = strPurchasesText[i];
          strAmount = strPurchasesText[i + 1];
          sngAmount = Convert.ToSingle(strAmount);

          //Construct Purchase string to add to ListBox
          ListTextLength = strText.Length + (sngAmount.ToString("C")).Length;
          ListText = strText + new string('.', 55 - ListTextLength) + sngAmount.ToString("C");
          ListPurchases.lstBox.Items.Add(ListText);

          //Add the amount to the Purchases total
          sngTotalPurchases += sngAmount;
          i += 2;        
        }
        //Show the Purchases total in the Purchases form Total box and the Balance form
        ListPurchases.lblTotal.Text = sngTotalPurchases.ToString("C");
        Balance.lblPurchases.Text = sngTotalPurchases.ToString("C");

        //Calculate and display the balance on the balance form
        sngAmount = sngTotalSales - sngTotalPurchases;
        Balance.lblBalance.Text = sngAmount.ToString("C");
      }
    }

That's the basic application. From here lots more features to add come to mind. Cheers.
Proudly powered by Weebly