Up

Graphics Programming in Visual C++/CLR

A simple example in Visual C++/CLR 2013

Another example using Graphics: The Game of Life

How to create a new Windows Form Application in Visual C++/CLR 2013 is explained at this website.

On Errors when Opening a Project

How to use OpenCV in Visual C++/CLR on a .NetFramework application is explained at this website.

 

Visual C++/CLR provides an easy way of drawing a graph. A sample program in Visual C++/CLR 2013 was written to simulate the logistic equation (I. Stewart, 2012, gIn pursuit of the unknown: 17 equations that changed the worldh Basic Books ). Figure 1 shows a result of simulation, in which a chaos is obtained.

 

Figure 1

 

The upper left of Figure 1 is shown in Figure 2.

 

Figure 2

 

Values of k and X0 are those of  and  in the following logistic equation

When we set other values, e.g., 2 and 0.1 as shown in Figure 3, and click ReStart button, the corresponding results will be obtained as shown in Figure 4.

 

Figure 3

 

Figure 4

 

Stewart (2012) explains that unstable results (chaos) will be obtained if .

 denotes proportion of individuals of specified type in a population, so

.

But, from (1),

.

Hence, if , then we may have . In this case, the value of  is set to be 1.

 

Release version of the program can be downloaded and executed by clicking the name LogisticEqWithoutTimer.exe . If a runtime error like g***.dll is not installed.h, install Visual Studio Express 2013 for Windows Desktop, which can be gotten at the Microsoft Website

http://www.microsoft.com/visualstudio/eng/downloads

After installation of Visual Studio Express 2013, the necessary files will be installed.

 

The program will draw the lines instantly. If you want to draw the lines with some time intervals, a program for that purpose is also prepared, which is introduced in the latter half of this website.

 

A graphics handler is used in drawing in Visual C++/CLR. A graphics handler is defined as follows.

               pictureBox1->Image = gcnew Bitmap(pw, ph);

               g = Graphics::FromImage(pictureBox1->Image);

With the above handler g, you can draw on the image component of pictureBox1.

Execute command

g->DrawLine( pnBk, a, b, c, d )

A line will be drawn from point (a, b) to point (c, d) with pen pnBk.

Lines in Figure 1 are drawn by the following codes

               while(ti < 100){

                             //

                             //                                                    Update the values and draw the results.

                             //

                             Xt = Xtp1;

                             Xtp1 = vk * Xt * (1.0 - Xt);

                             if (Xtp1 > 1) Xtp1 = 1.0;

                             g->DrawLine(pnBk, xpos(ti / 100.0), ypos(Xt), xpos((ti + 1.0) / 100.0), ypos(Xtp1));

                             ti++;

               }

 

The whole source codes of the program are as follows

===============================================================================================================

                            int ph, pw;                                                                   //            Height and width of pictureBox1

                            int x0, y0, x1, y1;                            //            The origin (0, 0) and point (1, 1) on pictureBox1->Image (pixel)

                            double Xt, Xtp1, vk;                        //            Xtp1 = vk * Xt * (1.0 - Xt)

                            int ti;                                                                           //            discrete time

 

                            //

                            //                          Transform x, 0 < x < 1, to xpos, x0 < xpos < x1.

                            //

                            int xpos(double x){

                                          return int(x0 + x * (x1 - x0));

                            }

                            //

                            //                          Transform y, 0 < y < 1, to ypos, y0 < ypos < y1.

                            //

                            int ypos(double y){

                                          return int(y0 - y * (y0 - y1));

                            }

 

                            Graphics ^g;                                   //                          A Graphics handle

 

              private: System::Void MyForm_Load(System::Object^  sender, System::EventArgs^  e) {

                                                         //

                                                         //                                      Maximize the form.

                                                         //

                                                         this->WindowState = System::Windows::Forms::FormWindowState::Maximized;

                                                         Update();

                                                         //

                                                         //                                      Set the position and size of pitureBox1.

                                                         //

                                                         pictureBox1->Top = 0;

                                                         pictureBox1->Left = buttonReStart->Left + buttonReStart->Width + 1;

                                                         pictureBox1->Width = this->ClientSize.Width - pictureBox1->Left;

                                                         pictureBox1->Height = this->ClientSize.Height;

                                                         pw = pictureBox1->Width;

                                                         ph = pictureBox1->Height;

                                                         //

                                                         //                                      Prepare an image component and a Graphics handle.

                                                         //

                                                         pictureBox1->Image = gcnew Bitmap(pw, ph);

                                                         g = Graphics::FromImage(pictureBox1->Image);

                                                         //

                                                         //                                      Set the origin at (x0, y0) and point (1, 1) at (x1, y1).

                                                         //

                                                         x0 = int(pw * 0.05);

                                                         y0 = int(ph * 0.8);

                                                         x1 = int(pw * 0.95);

                                                         y1 = int(pw * 0.1);

 

                                                         DrawCurve();                                //                          Draw the graph (ti, Xt).

              }

 

 

                                           //

                                           //                                                                  The function to draw the graph.

                                           //

                                           void DrawCurve(){

 

                                                         pictureBox1->Image = pictureBox1->Image;                                       //                          Make the Graphics handle effective.

                                                         //

                                                         //                                      Paint over the image area in white.

                                                         //

                                                         Brush ^ bshWt = gcnew SolidBrush(Color::White);

                                                         g->FillRectangle(bshWt, 0, 0, pw, ph);

                                                         //

                                                         //                                      Draw the frame, in which the graph will be drawn.

                                                         //

                                                         Pen ^ pnBk = gcnew Pen(Color::Black, 2);

                                                         array<Point> ^ xy = { Point(xpos(0.0), ypos(0.0)), Point(xpos(1.0), ypos(0.0)),

                                                                       Point(xpos(1.0), ypos(1.0)), Point(xpos(0.0), ypos(1.0)),

                                                                       Point(xpos(0.0), ypos(0.0)) };

                                                         g->DrawLines(pnBk, xy);

                                                         //

                                                         //                                                    Set the coordinate values.

                                                         //

                                                         //                                                    Set value 1 on the vertical axis.

                                                         String ^ str = "1";

                                                         using System::Drawing::Font;

                                                         Font ^ fnt = gcnew Font("Times New Roman", ypos(0.0) - ypos(0.05), GraphicsUnit::Pixel);

                                                         Brush ^ bshBk = gcnew SolidBrush(Color::Black);

                                                         SizeF sizeStr = g->MeasureString(str, fnt);

                                                         g->DrawString(str, fnt, bshBk, xpos(-0.005) - sizeStr.Width, ypos(1.0) - sizeStr.Height / 2);

                                                         //                                                    Set value 0 on the vertical axis.

                                                         str = "0";

                                                         sizeStr = g->MeasureString(str, fnt);

                                                         g->DrawString(str, fnt, bshBk, xpos(-0.005) - sizeStr.Width, ypos(0.0) - sizeStr.Height / 2);

                                                         //                                                    Set value 0 on the horizontal axis.

                                                         g->DrawString(str, fnt, bshBk, xpos(0.0) - sizeStr.Width / 2, ypos(-0.01));

                                                         //                                                    Set value 100 on the horizontal axis.

                                                         str = "100";

                                                         sizeStr = g->MeasureString(str, fnt);

                                                         g->DrawString(str, fnt, bshBk, xpos(1.0) - sizeStr.Width / 2, ypos(-0.01));

                                                         //

                                                         //                                                    Set the initial values.

                                                         //

                                                         Xtp1 = double::Parse(textBoxX0->Text);

                                                         vk = double::Parse(textBoxK->Text);

                                                         //                                                    Set the initial value of the discrete time ti.

                                                         ti = 0;

                                                         //

                                                         //                                                                 If ti < 100, update the values.

                                                         //

                                                         while(ti < 100){

                                                                       //

                                                                       //                                                    Update the values and draw the results.

                                                                       //

                                                                       Xt = Xtp1;

                                                                       Xtp1 = vk * Xt * (1.0 - Xt);

                                                                       if (Xtp1 > 1) Xtp1 = 1.0;

                                                                       g->DrawLine(pnBk, xpos(ti / 100.0), ypos(Xt), xpos((ti + 1.0) / 100.0), ypos(Xtp1));

                                                                       ti++;

                                                         }

                                           }

private: System::Void buttonReStart_Click(System::Object^  sender, System::EventArgs^  e) {

                                           DrawCurve();

}

private: System::Void buttonClose_Click(System::Object^  sender, System::EventArgs^  e) {

                                           this->Close();

}

=============================================================================================================

 

The files of the program are packed as ZIP file LogisticEqWithoutTimer.zip . Download this ZIP file and unzip it, then you can opened the program by Visual Studio 2013.

 

If an error message is shown, when the unzipped project is opened, you can simply ignore it (Figure A1).

 

Figure A1

 

Delete the pane that would show the form which caused the error message, by clicking gX on the tab (Figure A1).

 

Figure A2

 

Double click the name of the form header file, the pane of which was deleted at the previous step, in Solution Explorer pane (Figure A2).

Then, the form will be successfully shown (Figure A3).

 

Figure A3

 

 

The above program displays the results by Graphics instantaneously. If you want to observe the process, lines should be drawn with some intervals. For this purpose, a timer component can be used, which is explained in the next section.

 

 

Drawing a graph with a timer component

  To use a timer component, click icon of Timer in Toolbox, paste on the form. Then timer component timer1 will be shown below the form (Figure 5).

 

Figure 5

 

Then replace the following codes of the above program

 

               while(ti < 100){

                             //

                             //                                                    Update the values and draw the results.

                             //

                             Xt = Xtp1;

                             Xtp1 = vk * Xt * (1.0 - Xt);

                             if (Xtp1 > 1) Xtp1 = 1.0;

                             g->DrawLine(pnBk, xpos(ti / 100.0), ypos(Xt), xpos((ti + 1.0) / 100.0), ypos(Xtp1));

                             ti++;

               }

 

with the following

 

               //

               //                                                    Set timer1.

               //

               timer1->Interval = 100;

               timer1->Enabled = true;

 }

private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {

               timer1->Enabled = false;                                          //                          Stop timer1.

               //

               //                                                                  If ti < 100, update the values.

               //

               if (ti < 100){

                             //

                             //                                                    Update the values and draw the results.

                             //

                             Xt = Xtp1;

                             Xtp1 = vk * Xt * (1.0 - Xt);

                             if (Xtp1 > 1) Xtp1 = 1.0;

                             Pen ^ pnBk = gcnew Pen(Color::Black, 2);

                             pictureBox1->Image = pictureBox1->Image;

                             g->DrawLine(pnBk, xpos(ti / 100.0), ypos(Xt), xpos((ti + 1.0) / 100.0), ypos(Xtp1));

                             ti++;

 

                             timer1->Enabled = true;               //                          Start timer1.

               }

}

 

Lines are drawn on timer events, which occurs with interval timer1->Interval (msec). The executable program file LogisticEqWithTimer.exe can be downloaded and executed.

 

A Graphics handler becomes ineffective after some time. Hence, when drawing is performed over some duration, a graphics handler must be activated. In the above code, this activation is done by the following code

               pictureBox1->Image = pictureBox1->Image;

By this code, handler g becomes effective, so the results of processing by g is displayed on pictureBox1, i.e., on the display.

 

The program files are packed in ZIP file LogisticEqWithTimer.zip. Click zip file name LogisticEqWithTimer.zip and download it.  The unzipped file can be opened by Visual Studio 2013.

 

On Errors when Opening projects

 

Errors may occur, when opening a project by Visual Studio. These errors may be ignored.

For example, an error like the one in Figure A1 can be ignored, and you can build the project, for example.

 

Figure A1

 

An error like the one shown in Figure A2 can be also ignored. In this case, click mark X to delete the pane on which the error is indicated.

 

Figure A2

 

Double click the form file name (gMyForm.hh in case of Figure A3, ), to display the form.

 

Figure A3

 

The form of MyForm.h will be displayed by Form Designer (Figure A4).

 

Figure A4

 

When the error like that in Figure A2 is shown again, repeat the process of deleting the pain with the error message, and then double clicking the name of the form in the Solution Explorer pane. If the second trial also failed, delete the pane for the form with the error message by clicking the X icon at the right corner of the tag, and wait until the access lamp of the disc drive, in that the project files are put, goes out. After the lamp goes out, double click the name of the form in the Solution Explorer pane. The form will be successfully shown by the designer. It seems that Visual Studio needs some time to prepare to display the form.

 

 

Up