Click here to Skip to main content
15,881,600 members
Articles / Multimedia / GDI+

C++ / CLI Introduction and Implementation of FCFS using GDI Library

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
9 Mar 2016CPOL4 min read 15.5K   207   2   1
C++ / CLI into to using C++ CLI and using GDI library

Introduction

Today, we are going to go through how to use C++ in a GUI project using CLI (Common Language Interface) and we are going to discuss FCFS (first come first serve) algorithm and how to draw it using the GDI library and we are going to go step by step into creating your first CLI project till publishing.

The "Using the Code: section is divided into:

  1. Setting up your CLI project
  2. Simple test
  3. Start working
  4. Heading towards processing what is inside the table
  5. How to Parse the Text Boxes Inside the Table
  6. Draw using the GDI library
  7. Publish our work

Background

FCFS (first come first serve) is an algorithm that the OS uses for sorting which process to use the CPU... simply which process will come now will be served now, then the other, then the other.

We are going to implement this using the GDI library.

Using the Code

1. Setting Up

Start with creating a new empty clr project:

Image 1

Add new form:

Image 2Image 3

Add this bit of code in your form.cpp:

C#
using namespace System;
using namespace System::Windows::Forms;

[STAThread]//leave this as is
void main(array<String^>^ args) {
 Application::EnableVisualStyles();
 Application::SetCompatibleTextRenderingDefault(false);
 <<projectName>>::<<formName>> form; // replace<<...>> //don't write << and >> 
                                     // just replace what is inside
 Application::Run(%form);
}

Image 4

Open properties:

Image 5

Under Configuration Properties > Linker > Advanced, change Entry Point to "main" (without quotation marks).

Image 6

Under Configuration Properties > Linker > System, change SubSystem to "Windows (/SUBSYSTEM/WINDOWS)".

Image 7

2. Simple Test

In your designer, let us just start with dragging a button into your form:

Image 8

Double click this button and a function in the backcode would be automatically added to you and add this simple code to test if your program works just fine.

C#
private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
 {
  MessageBox::Show("hi");
 }

Image 9

Now just run: Image 10

If this appeared, then all your configurations are just right !!

3. So Let's Start on Working

First, let's change the name of the button we just added from properties:

Image 11

Let's add a table to the form:

Image 12

Change some of its properties, just change column number to be three:

Image 13

Now, just add 3 labels and change their names like what we did with button properties>>appearance>>text.

Image 14

Now let's return back to the back code and modify our old button_click function but before define an int:

C#
  int u = 1;//to hold the number of rows

private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
 {
  TextBox^ t1 = gcnew TextBox();    //define a text box
  TextBox^ t2 = gcnew TextBox();    //define a text box
				                    //both will then go under the first column
  
  Button^ b1 = gcnew Button();      //define a new button that will be 
                                    //a selectable button to change colors

  b1->Text = "color" + u.ToString();//change the text that appears to the user
  b1->Name = "color" + u.ToString();//change the text that you be able to access 
                                    //the button within the back code

  b1->Click += gcnew System::EventHandler(this, &cli_fcfs::MyForm::OnClick);
  //add a click event on this button

  tableLayoutPanel1->Controls->Add(t1, 0, u);//here, you would add the first text box 
                                             //to the new row in the first col
  tableLayoutPanel1->Controls->Add(t2, 1, u);//here, you would add the second text box 
                                             //to the new row in the second col

  tableLayoutPanel1->Controls->Add(b1, 2, u);//add the color button to the third column

  u++;//increment a counter to hold the value of number of rows
 }

It would be like this:

Image 15

When you create the onclick event, this would be created:

C#
 void OnClick(System::Object ^sender, System::EventArgs ^e); // a constructor

Button^ temp = gcnew Button();//specify a new button 

};
}

void cli_fcfs::MyForm::OnClick(System::Object ^sender, System::EventArgs ^e)//function itself
{
 temp = (Button^)(Object^)sender;  //to define the temp button with the clicked button
	//here we just type casted the sender as a general object
	//then define it as a button

 button2->Visible = true;    //after some seconds, 
                             //I will go through creating the color options so this code 
			                 // will be illustrated even more
 pictureBox1->Visible = true;

	   	//but simply you would have a picture box for selecting colors 
        //and a button to view which color is selected
		//normally this would be invisible
		//when you click the generated button both the picture box 
        //and the button would be visible 
}

This would look like:

Image 16

So when you run your code, it should look something like this when you click on the add button:

Image 17

4. Heading Towards Processing What Is Inside the Table

Begin with adding a button for processing:

Image 18

and double click it to create a function in the back code.

Now, let's add the picture box that I have told you about:

Image 19

and in the properties>>image, put this image:

Image 20

and add some events to this picture box.

Add a mouse move event so that when user just moves the mouse, the color selected would be captured in a temp storage:

Image 21

Until he clicks the mouse ... then the picture box would disappear ...and the color would be captured.

So, let's add another event.

Image 22

Also let's add a button to show the user which color he will select if he clicks the mouse.

Image 23

And change is properties >>flat style to flat and properties >>text to nothing

Now let's make button & the picture box and the button invisible when the user first opens the form as we need them to be invisible until user clicks them.

Image 24

Now let's modify pictureBox1_MouseMoveon:

MC++
Color pixel; //define a color outside the function to be easily accessed


private: System::Void pictureBox1_MouseMove
         (System::Object^  sender, System::Windows::Forms::MouseEventArgs^  e)
{
 Bitmap ^ bmpSource = reinterpret_cast<Bitmap ^>
         (pictureBox1->Image); //put the image of th picture box into a bitmap
 pixel = bmpSource->GetPixel(e->X, e->Y);//get the color of mouse position 
 button2->BackColor = pixel;//set this color to the button of temp storage
}

Now, let's modify pictureBox1_MouseClick:

MC++
private: System::Void pictureBox1_MouseClick
(System::Object^  sender, System::Windows::Forms::MouseEventArgs^  e)
{
 pictureBox1->Visible = false; 
 button2->Visible = false;
//make the picture and the button invisible

 temp->BackColor = pixel;// save the temp color to the button 
                         // that raised the event from the first place
}

5. How to Parse the Text Boxes Inside the Table

We will discuss two types of parsing elements in your form, the first is how to parse controls in columns of a table. The second would be later discussed as to how to parse controls if you know their name.

But first, let's define two lists that we would put our elements in. We define them outside of any function.

MC++
ArrayList names;
ArrayList cpu_burst_names;

Then, let's start with the first method inside the process_Click:

MC++
private: System::Void process_Click(System::Object^  sender, System::EventArgs^  e)
{
 for (int i = 1; i < u; i++)
 {
  TextBox^ t1 = gcnew TextBox();//define a temp text box
  t1 = (TextBox^)tableLayoutPanel1->GetControlFromPosition(0, i);//parse the table 
                                                                 //from a specified position
                                                                 //and type cast it and 
                                                                 //put it in the temp text box

  names.Add(t1->Text);                 //now add the text inside the temp text box to the list
 }

// same for the next column
 for (int i = 1; i < u; i++)
 {
  TextBox^ t1 = gcnew TextBox();;
  t1 = (TextBox^)tableLayoutPanel1->GetControlFromPosition(1, i);
  cpu_burst_names.Add(t1->Text);
 }

 draw();    //then draw
}

6. Let's Draw Using the GDI Library

Simply start with creating a function called draw():

MC++
   void draw()
   {
    auto g = this->CreateGraphics(); //this will define your starting graphics

    int count = 0;//just a counter for rows
    int x = 50;//for coordinates
    int sum_cpu = 0;//to view the total time for FCFS

    for (int i = 0; i < names.Count; i++)//just a loop to iterate on all names 
					//with the same loop, we will iterate through cpu burt times
    {
     String^ color_name = "color" + (i + 1); //make a string to hold the name of the button 
                                             //to find it
     Control^ ctn1 = FindControl(color_name);//a function n that I will talk about later 
                                             //which the second way to parse your form for a 
					                         //specified control just if you know its name

     Pen^  my_pen = gcnew Pen((Color)ctn1->BackColor);//make a pen with the 
                                                      //color of the button
     String^ a = (cpu_burst_names[i]->ToString());    //string of the time
     int^  width;
     width = Convert::ToInt32(a);//convert time into int
     g->DrawRectangle(my_pen, x, tableLayoutPanel1->Size.Height, *width * 10, 50);
			//draw the outline of the rectangle with the width if the time
			//and its y to be at the end of your tabel
			//it would be even better to make outline a white color 
            //not like what it states here
			//and only when you fill the rectangle you fill with 
            //the specified color of the button

     Rectangle r(x, tableLayoutPanel1->Size.Height, *width * 10, 50);
//define a rectangle just the same as when you drew it
//but we define it to be able to put the name of the process 
//in the middle of this rectangle 

     //just some properties to be able to draw the strings
     StringFormat^ sf = gcnew StringFormat();
     SolidBrush^ br = gcnew SolidBrush(Color::Black);
     System::Drawing::Font^ f = gcnew System::Drawing::Font("Arial", 10);

	 //define a solid brush to be able to draw the rectangle with the needed color 
     SolidBrush^ baaaa = gcnew SolidBrush((Color)ctn1->BackColor);
     g->FillRectangle(baaaa, r);//now fill the rectangle
     g->DrawString(names[i]->ToString(), f, br, midp(r).X, midp(r).Y, sf);
	 // add the name of the process in the middle of the rectangle 
     // so we define the function of the middle 
	 // that would be later discussed

	 //now we need to view the sum of the cpu burst time
     sum_cpu = sum_cpu + Convert::ToInt32(cpu_burst_names[i]->ToString());
     int^ temp = sum_cpu;
     System::String^ str = temp->ToString();//define the number to a string
     g->DrawString(str, f, br, r.Right - 10, r.Bottom, sf);
	 //draw the string at the end of each process

     x = x + *width * 10;//update the coordinates
    }
}

Now let's define the function that parses the form for a special control and returns that control:

MC++
Control^ FindControl(String^ strControlName)
{
 if (strControlName->Length == 0 ||
     this->Controls->Find(strControlName, true)->Length == 0)
  return nullptr;


 return this->Controls->Find(strControlName, true)[0];
}

Now, we are going to write the function of the middle:

MC++
Point midp(Rectangle r)
   {
    Rectangle a = (Rectangle)r; //take the rectangle
    int x = a.Location.X;
    int y = a.Location.Y;
    int h = a.Height;
    int w = a.Width;
    Point pp;
    pp.X = x + w / 2 - 5; //calculate mid point x//me 5
    pp.Y = y + h / 2 - 5; //calculate mid point y//me 5
    return pp;
   }

It simply calculates the middle point of a rectangle so that we display the name of the process in the middle.

So at the end, it should look something like this:

Image 25

7. Let's Publish Our Work

Ideally, you should have made your project release not debug ... but for a weird reason, this didn't work with me.

So simply after debugging your project ...go to its directory >>debug>>yourName.exe and copy this file.

It could need some dependencies ... so look for them inside Visual Studio bin files:

 
it would be very important for me to know what do you think these tutorials ... are they up to what you have expected ?? ... it would be really important for me to hear your feedback

Points of Interest

We would like to invite you to our tutorials using GDI in C#:

History

  • 9th March, 2016: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Junior)
Egypt Egypt
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionErrors Pin
Member 1379825425-Apr-18 11:20
Member 1379825425-Apr-18 11:20 
I try to build your application but I get error messages:
error C3352: 'void System::Windows::Forms::Control::OnClick(System::EventArgs ^)' : the specified function does not match the delegate type 'void (System::Object ^,System::EventArgs ^)'

I changed "void main" to "int main" 

error C3845: 'cli_fcfs3::MyForm::u': only static data members can be initialized inside a ref class or value type

end so on...

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.