CIS Logo SVC Logo

   Computing & Information Systems
   Department

 

Schoology Facebook        Search CIS Site      Tutorials

Software Design Using C++



Second Advanced Windows Forms Example



The Plan


We wish to improve upon the Fourth Intermediate Windows Forms Example, the one that displayed in a ListBox the square roots of the first so many positive integers. Our first improvement is to use a new control, a ListView, that gives us a nicer view of the data. Notice how it gives us column headings so that we can label the column for the original numbers and the column for the square roots. However, the square root data is formatted inconsistently. Some of them have many decimal places, whereas roots that are whole numbers (such as the square root of 4, which is 2) are shown with no decimal point and no decimal places. It would be nice to display all of the roots in a consistent manner as shown in this picture. That will be our other improvement.

Getting Started


If you still have your Fourth Intermediate Windows Forms Example project, create a new C++ Windos Forms App project (perhaps named Roots2). Then copy the controls from the old form to the new one, and copy the code as well. Refer to the copying directions in this previous example if need be. If you do not have your old project for the Fourth Intermediate Windows Forms Example you could recreate it.

Adjusting the Controls


Click on the ListBox control and then press the Delete key. That's a quick way to get rid of that old ListBox. That will mean, of course, that much of old code no longer makes sense, but we will take care of that later. Then drag a ListView control from the Toolbox and place it where the ListBox had been. Resize it to be about the same size as the control just removed.

Make sure that the ListView control is selected and go to the Properties Window. Change the name to RootListView. Change the BackColor (background color) to a light yellow. If necessary, click the + sign in front of the Font property so that you can see all of the items listed within it. Set Bold to True. That's the only change to the Font property, so you can click on the - sign and collapse that stuff to a single line. Next, change the ForeColor to a bright blue. For the app in the pictures above, the ActiveCaption color found under System was used. Make sure that the GridLines property is set to True. That puts in vertical lines to separate columns and horizontal lines to separate the rows. Make sure that the Scrollable property is True, though it should be so by default. We want the user to be able to scroll through the list of roots. The View property should be set to Details (and not to SmallIcon or one of the other choices).

Save all of your files. Also right click on the new project in Solution Explorer and set this project to be the startup project.

Code for the First Improvement


Open your Form1.cpp file and change the code for your click handler function so that it looks like this:


System::Void Form1::StartButton_Click(System::Object * sender, System::EventArgs * e)
   {
   long k, Count;
   double Root;
   ListViewItem * Item;

   RootListView->Clear();
   RootListView->Columns->Add(S"Number", 64, HorizontalAlignment::Right);
   RootListView->Columns->Add(S"Root", 196, HorizontalAlignment::Right);
   Count = NumberBox->Text->ToInt32(NULL);

   for (k = 1; k <= Count; k++)
      {
      Root = Math::Sqrt(k);
      Item = new ListViewItem(k.ToString());
      Item->SubItems->Add(Root.ToString());
      RootListView->Items->Add(Item);
      }
   }

Notice that we set up Item as a pointer to a ListViewItem, the type of thing that we can put into our ListView. You might want to name this variable ItemPtr if you need a reminder that it is a pointer to an object and not the object itself. The essential thing that we do with this Item variable is to point it to a new object containing one row of data and then add that object to the Items collection of RootListView.

However, before we get to the details of that, we first clear any old data out of RootListView. Then we add the headings for our two columns. Recall that S"Number" is a way to create a string literal. Thus Number is the first heading. The heading is aligned to the right inside of a field 64 pixels wide. The second heading is set up in a similar way. It is also possible to set up the column headings by using the Properties Window with the ListView control. For further information use Help, Search and enter ListView.

The structure of the loop is similar to that of our old application. However, once we have a new value of k, we convert it to a string and stick it in a new ListViewItem object and have Item point to that object. You might wonder what SubItems refers to. These are items that get displayed (at least in Details view) to the right of the main item (the value of k) for each line. Thus we add the computed square root here. Finally, now that we have built up the desired ListViewItem, we add it to our ListView control. It makes sense once you try it out!

At this point it would be best to save all of your files. Then build and run your application to see that it works reasonably. The running app should look like the one shown in this picture.

Code for the Second Improvement


Here, we want to format those square roots consistently. To be able to do this we first need to make a few small additions to Form1.h. Open your Form1.h file in Code View. The prototype for the click handler function at the bottom of the file should be fine as is. At the top of the file put in these two additions (shown here with the comment "added for NumberFormatInfo"). No other changes or additions should be needed.


#pragma once

   #using <mscorlib.dll>   // added for NumberFormatInfo

namespace Roots2
{
   using namespace System;
   using namespace System::ComponentModel;
   using namespace System::Collections;
   using namespace System::Windows::Forms;
   using namespace System::Data;
   using namespace System::Drawing;
   using namespace System::Globalization;  // added for NumberFormatInfo

Then, in Form1.cpp revise the code for our click handler as follows:


System::Void Form1::StartButton_Click(System::Object * sender, System::EventArgs * e)
   {
   long k, Count;
   double Root;
   ListViewItem * Item;

   RootListView->Clear();
   RootListView->Columns->Add(S"Number", 64, HorizontalAlignment::Right);
   RootListView->Columns->Add(S"Root", 196, HorizontalAlignment::Right);
   Count = NumberBox->Text->ToInt32(NULL);

   CultureInfo * MyCI = new CultureInfo(S"en-US", false);
   NumberFormatInfo * nfi = MyCI->NumberFormat;
   nfi -> NumberDecimalDigits = 12;

   for (k = 1; k <= Count; k++)
      {
      Root = Math::Sqrt(k);
      Item = new ListViewItem(k.ToString());
      Item->SubItems->Add(Root.ToString(S"N", nfi));
      RootListView->Items->Add(Item);
      }
   }

It probably seems strange to see the creation of a CultureInfo object. The code above has the pointer MyCI point to this new object. You can use Help, Search in Visual Studio to look up information about the CultureInfo class. Although it is indeed used to work with language and other information that varies between cultures, it is also used to format numbers, which is why we use it here.

The next thing done in the above code is to set the nfi pointer so that it points at the NumberFormatInfo object inside of our CultureInfo object. The NumberFormat property is used to get this NumberFormatInfo object. Inside our NumberFormatInfo object we place 12 into the NumberDecimalDigits property. That is the key to getting the same number of decimal places displayed for all of our square roots. (Often we would use a lot fewer decimal place, but since we are using double precision reals, we have a lot of decimal places available. According to the help system in Visual Studio, up to 15 digits may be possible.) Finally, when we add the new root as a subitem, we convert it to a string while specifying nfi as the pointer to the formatting information to use. For more information on the use of formatting information with ToString, use the help system to look up double.ToString.

Try It Out


Save all of your files, then build your new project. If there are syntax errors, fix them and build again. Then run your program by using Debug, Start Without Debugging. Try it out and make sure that it works correctly.

Back to the main page for Software Design Using C++

Author: Br. David Carlson with contributions by Br. Isidore Minerd
Last updated: August 27, 2009
Disclaimer