Friday, October 28, 2011

[C++] - Memory Segmentation in C++

Introduction - Memory Segments

In the previous article, we saw about the pointer and reference variables in the context of stack memory. There are 3 more important memories that every c++ programmer should be aware of it. Below is the four important memory segmentation:
  1. Stack Memory Segments
  2. Heap Memory Segments
  3. Code Segmentation
  4. Data Segmentation
In this article, we will have a look at these memory segments with a simple example. The example is just for understanding the purpose and it does nothing actually excepting printing something.

Memory Segments - An example

The complete example is shown below:

// CPPTST.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <conio.h>
//MemSeg01: Declare a Global Variable
int x = 10;

//MemSeg02: Store address of the Global variable in a Global Pointer
int* px = &x;

//MemSeg03:  Function definition. Takes a number and prints it
void PrintNo(int x)
{
 int y;
 y = x;
 printf("The given number is %d", x);
}


int _tmain(int argc, _TCHAR* argv[])
{
 //MemSeg04: Declare a loval variable and declare a pointer and store the address of local variable
 int m = 12;
 int* pm = &m;

 //MemSeg05: Local pointer storing the Global Address
 int* pgx = &x;

 //MemSeg06: Local pointer storing the heap address and assigning a value to the heap
 int *pInt = new int;
 *pInt = 22;

 //MemSeg07: Local pointer to a function that returns void and takes int
 void (*pFun)(int);

 //MemSeg08: Pointer storing the base address of the function
 pFun = &PrintNo;

 //MemSeg09: Calling the function through function pointer
 pFun(117);
   

 return 0;
}

Let us explore the example in terms of the memory segmentations.

Code Memory Segment

Well. The code is displayed above. What will you do with it? The first thing is compiling it and then linking the code. Let use assume that the above code is placed in the MyProgram.CPP file. When you compile, the compiler will translate this human readable language into something that called as object code. If there are 20 such files, the job of the compiler is to generate twenty different object files and prompt any errors that do not comply to the C++ syntax. Then the linker will go through all 20-object files to form an executable that is the .exe file.

What happens when you double click the exe name? The exe is considered as a process by the operating system and once the process is committed, the M/c code (exe) is loaded into the memory and processor will access these machine instructions to perform specified action. This memory is called Code Segment. In out example, the translated code goes as exe, and when the exe is executed, the instructions are loaded into the memory called code segment.

Let us take the first statement in the Program entry:

//MemSeg04: Declare a local variable and declare a pointer and store the address of local variable
int m = 12;

The above code will be translated and packed in the exe as a machine-readable language. In the VS2005 IDE, I kept a breakpoint on the above-shown statement and once the breakpoint is hit, using the context menu I asked for show Assembly code. The Assembly revealed is shown below:




The address marked in Red box shows it stores the assembly command MOV (It may be mapped to number and then in terms of zeros and ones that is low and high voltage. We no need to go that much deep into the electronics of it). The Address in the Red box is actually allocated in the Code Segment. A pointer can store this address also.

Data Memory Segment

As the name implies it is the segment for application data. Do you heard your senior asking multiple questions when you declare a global variable? He asks, because the global variables go and sit in the data segment of the memory. So what? If it sits there, it lives until the program dies and there is no ways to say get lost. Think about a big project and 1000 of people worked on it (Even in maintenance) for last 10 to 20 years declared plenty of global variables even when it is avoidable by alternate techniques. When the program loads (in Code segment) it needs to allocate space for all those variables and allocated space is never cleared until the program exits. That is why we call these global variables and constants are application data. The memories associated to these global are known as data segment memory and it will get cleared when the program is removed.

In our example the following two statements are occupying the memory in the data segment.

//MemSeg01: Declare a Global Variable
int x = 10;
//MemSeg02: Store address of the Global variable in a Global Pointer
int* px = &x;

Note that the pointer px is holdling the address of some data segment memory allocated to variable integer x. Also, the space required for holding that address also allocated in the data segment. Here, the value in the px, x can be changed. But, the space allocated for it cannot be washed out.

Heap Memory Segment

Allocating and clearing the memory in the memory segment for Stack, Code and data is taken care by the system. But, heap memory is given in the hands of C++ programmer. They can create byes of memory as well as clear it whenever they want.  So the programmer determines the lifetime of the memory allocated. Consider the statement below taken from the example:

//MemSeg06: Local pointer storing the heap address and assigning a value to the heap
int *pInt = new int;
*pInt = 22;

In the above statements, space required to store an integer value is allocated in the heap. The allocated address is stored in the variable pInt. The variable pInt is inside the main function and so the space for variable pInt is allocated in the stack holding address in the heap (Enough to store an integer).  So when we go out of the function all the stack memory associated to it is cleared. But, the allocated heap becomes un attended or blocked stating in use. Because system will not clear it and programmer should do that. To clear that heap, before you lose the address in the stack for pInt, you should use the statement delete pInt.

What happens if the above two statements are next to the comment MemSeg01 that is not inside any of the function? Well. Heap memory is stored in data segment variable pInt.

Stack Memory Segment

It is the memory segment where almost everybody declares and uses the variables. When you declare a variable inside the function that goes to the stack segment of the memory. All the stack segments wiped out once you go out of the function and when you come inside the some other function a new stack segment for that function is created. So this is a less costly segment as it lives till corresponding function returns back to the caller.
Let us assume Program main calls the function A. Here first the Stack Segment for Main is created, then when you are inside the function A, main programs stack segment becomes un-accessible and at the same time stack segment for Function A is created. When the function A return the control to main program, stack segment for A is cleared and stack segment for program main (Still lives, it became temporarily un-accessible) becomes available. You can refer my previous post for detailed example about stack segment.

In our example the below two statements in the main is created in stack segment:

//MemSeg04: Declare a loval variable and declare a pointer and store the address of local variable
int m = 12;
int* pm = &m;

Before we close

Below is the Illustration of memory segment and variable involved in our sample.




We know that a pointer can hold an address. In our example,

Pm – is holding the address of memory in stack segment
Pgx – is holding the address of the memory in the data segment
Pint – is holding the address of the memory in the heap segment
PFun – is holding the address of the memory (Starting address or base address of the void PrintNo(int x) ) in the code segment.

Pfun?

That is function pointer, I will write about it later. There is a nice movie in HBO, I will spend sometime there.



Tuesday, October 18, 2011

[C#] - Display information on C# StatusStrip

1. What is StatusStrips?

"StatusStrip" is a family of strip controls like MenuStrip and ToolbarStrips, which is Status Strips used to display some quick help and information to the user who is using the application. A status strip control will look like the one shown below:



C# status strip control allows you add even combo and textboxes to the status. In this example we will have a look at how we add a StatusBar to the application and how will we use it. Then we will look at some of the important properties and use that efficiently.

2. About the Sample

The screenshot of the sample in created in C# is shown below:



The black colored narrow strip is the status strip and it has three slots in it. The computation section (Sorry for the spelling mistake in the button. Lazy to change it for now] will calculate the sum of the number you enter. On iteration of the numbers, a delay is introduced intentionally to simulate that it is a long running process. During that time Computing please wait to appear in the first status slot. The second slot will show current border style and the third one shows your last input given for computing the summation section.

You can set two kinds of border style to the status bar in the sample using the border style section. Once a border style is picked it can be applied to the top side of the slot or bottom side of the slot or can be applied to all 4 sides. The applied sides can be revoked by un-checking the check boxes.

The spring check boxes allow expanding the slot to occupy the remaining free space. We will start the sample now.

3. Adding Status bar and Setting the properties

From the Menus & Toolbar section, the StatusStrip Control is added to the form. Once StatusStrip Control is added, the status labels (Three slot has three labels in the sample) are added using the edit items option of the status bar. Then inside the property dialog, you can the individual property for the status bar items. This is shown in the below video:



4. Assigning initial texts in the status

The StatusLabel in the status bar can be accessed by its name. In the form load event handler, we are placing some initial text. Event handler is code given below:

//Status 001: Set status Labels
private void StatusBarSample_Load(object sender, EventArgs e)
{
    //Access the Status Labels by Name
    SLabel1.Text = "Idle";
    SLabel2.Text = "Default";
    SLabel3.Text = "0.0";
}

SLabel1 to SLabel3 is added in the previous step and its text property is set during the form load. So the initial display of the form will show above set texts in the status labels.



5. Showing informative text dynamically

When is it required to show informative text? Say when the application is going on the long process it needs to be informed to the user. Some people display an hourglass icons and some display a 'please wait message' in the status bar. We are going to display the 'please wait message' in the status bar. The compute button will calculate some summation of the given number and a thread delay is introduced to show it is along running process.

The Compute Summation button click handler is shown below:

//Status 002: Compuate Summation
private void btnSum_Click(object sender, EventArgs e)
{
    //Status 002_1: Declarations and some initialization
    long endno = long.Parse(txtInput.Text);
    long sum = 0;
    lblResult.Text = "";

    //Status 002_2: Set the text for status and start computation. Do not forget Application.doevents()
    SLabel1.Text = "Computing Please Wait..";
    for (long cnt = 1; cnt < endno + 1; cnt++)
    {
        Thread.Sleep(10);
        Application.DoEvents();
        sum = sum + cnt;
    }
    lblResult.Text = sum.ToString();

    //Status 002_3: Set the status as Idle
    SLabel1.Text = "Idle";
    SLabel3.Text = "Last Input: " + txtInput.Text;
}

In the above code,

The Thread.Sleep(10); is used to hang the sample for 10 milliseconds in each iteration. Before the long process (Made long) starts we are displaying the status label the please wait message using the statement: SLabel1.Text = "Computing Please Wait.."; and at the end, we are changing the status label to Idle meaning that application is not busy now. Also, we are setting the input processed in the last status label.

    SLabel1.Text = "Idle";
    SLabel3.Text = "Last Input: " + txtInput.Text;

It should be noted that even though we set the status label Please wait, it will not get displayed when the application too busy. That is when the application busy it has no time to make any user interface changes and displaying the new label text appears only when the application goes to normal stage from the busy stage. Then it will be no use when the label does not display computing please wait when required. The call to Application.DoEvents() will serve the processing of any waiting events in our case it is updating the status label from model to computing please wait. How the status label displays the waiting message is shown in the below video:



6. Setting Border Style using Status slot edges

Note that in section 3 of this article we added three ToolStripStatusLabels to our status strip. In this section, we are going to set the border style to the edges of the control.



Member name
Description

Adjust
The border is drawn outside the specified rectangle, preserving the dimensions of the rectangle for drawing.

Bump
The inner and outer edges of the border have a raised appearance.

Etched
The inner and outer edges of the border have an etched appearance.

Flat
The border has no three-dimensional effects.

Raised
The border has raised inner and outer edges.

RaisedInner
The border has a raised inner edge and no outer edge.

RaisedOuter
The border has a raised outer edge and no inner edge.

Sunken
The border has sunken inner and outer edges.

SunkenInner
The border has a sunken inner edge and no outer edge.

SunkenOuter
The border has a sunken outer edge and no inner edge.

The above table shows all the available border styles. In this Example, I had taken only two of them. The Source code for applying and revoking the BorderStyle to the Sides of the Status label is explained below.

1) First, an Enumeration type is declared. This enumeration is capable os holding the value for the sides. The enum variable is initialized to None first.

//Status 003: Used for the Borderside property
ToolStripStatusLabelBorderSides applyto = ToolStripStatusLabelBorderSides.None ;

2) When you select the Border Style using either "Sunken outer" or "Etched", We are making a call to the user-defined function "ApplyBorderStyle". Code is below:

//Status 005: Once we have the border sides, we can apply the border styple
private void radSunken_CheckedChanged(object sender, EventArgs e)
{
    ApplyBorderStyle();
}

3) In the ApplyBorderStyle function, we are assigning the combination of BorderSides stored in the applyto variable to all three status labels. The checkbox event handler will assign the sides or revokes it from this variable. After applying the sides in effect, we setting the border style by checking radSunken.Checked == true and when it is true, the corresponding border style is set followed by updating the status label2 to show that is current border style.

//Status 006: Apply Border style
private void ApplyBorderStyle()
{
    SLabel1.BorderSides = applyto;
    SLabel2.BorderSides = applyto;
    SLabel3.BorderSides = applyto;

    if (radSunken.Checked == true)
    {
        SLabel1.BorderStyle = Border3DStyle.SunkenOuter;
        SLabel2.BorderStyle = Border3DStyle.SunkenOuter;
        SLabel3.BorderStyle = Border3DStyle.SunkenOuter;
        SLabel2.Text = "Sunken Outer";
    }
    else
    {
        SLabel1.BorderStyle = Border3DStyle.Etched;
        SLabel2.BorderStyle = Border3DStyle.Etched;
        SLabel3.BorderStyle = Border3DStyle.Etched;
        SLabel2.Text = "Etched";
    }
}

4)  To apply or revoke the sides in effect, the bitwise OR(|), bitwise XOR(^) is used like below:

applyto = applyto | ToolStripStatusLabelBorderSides.Top;  To apply a side
applyto = applyto ^ ToolStripStatusLabelBorderSides.Top;  To revoke a side
           
The above bitwise operations are used when you do check and uncheck on the checkboxes that specifies the edges in which the border style will be applied.     Below is the available border sides, which taken from the ToolStripStatusLabelBorderSides enumeration:

{
        None = 0,
        Left = 1,
        Top = 2,
        Right = 4,
        Bottom = 8,
        All = 15,
    }

The above two statement that applies and then revokes the Top borderside is depicted as follows:



The checkbox event handler will apply and revoke the corresponding edge using the method specified above. Note that after storing the required sides in the variable applyto, we are making a call to the "ApplyBorderStyle()" and we already saw that the called function will apply your selected border styles to the edges that are applicable. The code for that is shown below:

//Status 004: Store the bordersides for applying the border style
private void chkTop_CheckedChanged(object sender, EventArgs e)
{
    //Apply the side using bitwise Or Operator. Remove the style using the Xor
    if( chkTop.Checked == true )
        applyto = applyto | ToolStripStatusLabelBorderSides.Top;
    else
        applyto = applyto ^ ToolStripStatusLabelBorderSides.Top;
    ApplyBorderStyle();
}

private void chkLeft_CheckedChanged(object sender, EventArgs e)
{
    if (chkLeft.Checked == true)
        applyto = applyto | ToolStripStatusLabelBorderSides.Left;
    else
        applyto = applyto ^ ToolStripStatusLabelBorderSides.Left;
    ApplyBorderStyle();
}

private void chkAll4_CheckedChanged(object sender, EventArgs e)
{

    if (chkAll4.Checked == true)
    {
        chkTop.Checked = true;
        chkLeft.Checked = true;
        applyto = applyto | ToolStripStatusLabelBorderSides.All;
    }
    else
    {
        chkTop.Checked = false;
        chkLeft.Checked = false;
        applyto = ToolStripStatusLabelBorderSides.None;
    }
    ApplyBorderStyle();
}

Below is the video that shows testing the Border style code explained above.




7. RenderMode property of the StatusStrip

The Render Mode is just a different style for the status bar. As I applied the background image for the status bar the render mode has a very little effect. Below is the code that makes use of the "RenderMode Property":

//Status 008: Set different Render Mode
private void radRModeSystem_CheckedChanged(object sender, EventArgs e)
{
    if (radRModeSystem.Checked == true )
        statusSt.RenderMode = ToolStripRenderMode.System;
}

private void radRModeProf_CheckedChanged(object sender, EventArgs e)
{
    if(radRModeProf.Checked == true )
        statusSt.RenderMode = ToolStripRenderMode.Professional ;
}

8. Spring Property of the Status Items

As the name suggests it performs the spring action on the status slots. When the "Spring Property" is set to true, the slot expands to occupy the remaining free area in the status bar. When more than one slot has Spring property set to true, they share the remaining free space on the status strip together.

Below is the checkbox handler code for setting the spring property for either first slot or second slot or for both.  I intentionally do not provide setting the spring property for the third slot so that you can know that third slot always fit the text it is holding.

//Status 007: Set the Spring effect for status bar
private void chkSpringLb1_CheckedChanged(object sender, EventArgs e)
{
    if (chkSpringLb1.Checked == true)
        SLabel1.Spring = true;
    else
        SLabel1.Spring = false;
}

private void chkSpringLb2_CheckedChanged(object sender, EventArgs e)
{
    if (chkSpringLb2.Checked == true)
        SLabel2.Spring = true;
    else
        SLabel2.Spring = false;
}


See you all in the next article. The sample is developed in VS2005 IDE. If you have the latest one, just accept the conversion asked by the dialog of your latest IDE.

Source Code : Download

Thursday, October 13, 2011

[C++] - Reference vs Pointers

Introduction - Reference and Pointers


A pointer is a notation that says it points to something. In C++ or C that something is known as an address. The next question, what is address? Hey, Rachel! Where do you stay? She will give her address to her new friend so that he can locate her living place. The context is same in c++ also. Every value stored by your program will occupy some memory location.

Here we will see some basics of what are pointer variable, reference variable, and a normal variable.

A simple pointer and reference to a variable


A variable is declared as follows:
int                    x;

Here,
X is the variable name
int specified the type of data that can be stored in x.

Let us assume that the variable shown above is declared in the void main of the program. The variable scope is inside the main and we know that the variable occupies some memory in the call stack of main. Now the x is a naming given to the location in the stack that is allocated by the void main function. Using the assignment operator and the variable x the location is accessed. So the address involved is hidden behind the scene and all you know is variable name x and internally is has an association to a location in the stack memory of the main function.

Now have a look at the variable declaration below:
int&      refto_x  = x;

Here,
refto_x is reference variable and that references the variable x. Int& specifies the reference notation and reference to what data type.

The reference variable should be initialized when it is declared. See… in our example statement we declared a reference variable refto_x and initialized it with the assignment = x. What does that say? Well. X is a naming notation used internally to read or write from a specific memory location in a stack (When x is not a global variable and declared inside some function) and simply it is a variable declared already. And refto_x is a naming notation for the naming x. That means refto_x is simply one more naming given to the location represented by the variable x.

Now look at the statement below:
int * pointerto_x = &x;

Here,
int * - Represents pointer to an integer
pointerto_x – A variable name given to the pointer variable
&x – Address of the variable x.

In the above declaration, a pointer variable pointerto_x is declared and at the same time initialized to have the address of the variable x. Note that in the above statement unlike reference it is not just one more name to the location represented by x. It has it own location represented by a variable pointerto_x and that location can store address location and when it access that location it treats that address location to read or write integer sized data.

Basic explanation for reference and pointers


Let us explore the pointer, reference and a normal variable with an example. Consider the below four statements:

int _tmain(int argc, _TCHAR* argv[])
{
 //Declare an integer variable, then have a pointer and reference to it
 int x;
 int& refto_x = x;
 int * pointerto_x = &x;
 x = 10;
}
First, we declared an integer variable x and then had a reference to it in the variable refto_x. Then the pointer variable pointerto_x is declared and initialized to hold the address of the variable x. Finally, we assigned value 10 to the variable x. Have a look at the below picture:



The above three variable creation and assignment of value 10 is depicted as above. First, to store the value 10 we need some bits in memory. Second as the variable x is declared inside the _tmain () function and value 10 is assigned to the variable x, memory in the stack holds the value 10.  To read or write from this memory location we use the variable x.

Read:
p = x + 15;
In the above statement, the value in the stack memory identified by the variable x is read then assigned to variable p after summing it with a value 15.

Write:
x = p - 10;
In the above statement the value in p is decremented by 10 then written to the memory location identified by the variable x.

So, according to x, the read or write operation defined by the variable x and it position in relation to the assignment operator =. C++ developers call the variable name and its corresponding memory location as naming association.

Now explaining the reference is easy. In our example statements above, refto_x is just one more naming association to the same stack memory. That means x and refto_x both corresponds to the same memory in the stack. What about pointerto_x? It stores the address of the memory location for x or refto_x.

The above four statements can further explained in detail by using the below depiction:



1.      FE100B12: Memory address of stack that holds value 10
2.      FF820CD7: Again, memory address of stack that holds address of some other memory in stack (32 bit address or 64 bit address)
3.      Variable x is associated to the memory location FE100B12
4.      Variable refto_x is also associated to the memory location FE100B12
5.      Variable pointerto_x is associated to the memory location FF820CD7

Note that x, refto_x and pointerto_x all declared inside the main () and have an association to the stack memory. I will talk about heap later and that is different.

The value in the location is shown above. If you just read the content of the pointer variable pointerto_x, then you will get memory location of the variable. To read the content, you should de-reference the pointer.

int m = * pointerto_x;

In the above statement we specifed that we do not want the content of pointerto_x (Which is an address), But we want the actual value in the address which stored in the pointerto_x.

Code and Example


Below is the complete example and output:

#include "stdafx.h"
#include <conio.h>



int _tmain(int argc, _TCHAR* argv[])
{

            //Declare an integer variable, then have a pointer and reference to it
            int                     x;
            int&       refto_x  = x;
            int * pointerto_x = &x;

            //Assing a value to x and print the value in it using value, refernce and pointer
            x = 10;
            printf("X=%d\n", x);
            printf("Value in x through refto_x=%d\n", refto_x);
            printf("Value in x tnrough pointerto_x=%d\n", *pointerto_x );

            //Now check the address of all the three variables
            printf("********* Adress of Value, reference, pointer variables *********\n");
            printf("Address of x=%d\n", &x);
            printf("Address of refto_x=%d\n", &refto_x);
            printf("Address of pointerto_x=%d\n", &pointerto_x );
           
            //Special case
            printf("Then what is stored in pointerto_x? It is %d, address of x", pointerto_x);

            getch();
            return 0;
}
#include "stdafx.h"
#include 

int _tmain(int argc, _TCHAR* argv[])
{
 //Declare an integer variable, then have a pointer and reference to it
 int                     x;
 int&       refto_x  = x;
 int * pointerto_x = &x;

 //Assing a value to x and print the value in it using value, refernce and pointer
 x = 10;
 printf("X=%d\n", x);
 printf("Value in x through refto_x=%d\n", refto_x);
 printf("Value in x tnrough pointerto_x=%d\n", *pointerto_x );

 //Now check the address of all the three variables
 printf("********* Adress of Value, reference, pointer variables *********\n");
 printf("Address of x=%d\n", &x);
 printf("Address of refto_x=%d\n", &refto_x);
 printf("Address of pointerto_x=%d\n", &pointerto_x );

 //Special case
 printf("Then what is stored in pointerto_x? It is %d, address of x", pointerto_x);

 getch();
 return 0;
}
Output


Saturday, October 01, 2011

[C#] - Using ToolStrip control with ToolStrip Button and ToolStrip Icon

1. Introduction to Tool Strips

Just Like Menustrip Control, "ToolStrip Control" also a relatively large piece of placeholder where you can place icon buttons, combo box, labels etc. To have an understanding have a look at the below picture:


In the top of the form, a toolbar is placed and there are number of toolbar buttons in the toolbar’s left and right-hand side. The toolbar can be moved anywhere in the form and like menu items they can be hooked to the command handler routine.

People usually place some important commands in the toolbar. The traditional way of user interface designing is to pick the important commands from the menu and place that in the toolbar as an iconic button for quicker access to those command through mouse clicks.

2. About the Sample

Screen shot of the sample application at runtime is shown below:



The toolbar is placed at the top of the form. For demonstration purpose, I kept three buttons on the right-hand side. In the sample placing the check mark on the Display Image and Text will show the quick command text for the toolbar buttons and at the same time the radio buttons below it gets enabled. And these radio button controls the text position in relation to the toolbar button icon.

Normal Flow under the ToolBar layout, when checked, moves the toolbar buttons to the next row when there is no room to display the entire icon buttons in one row. When Horizontal Overflow radio button is checked, the toolbar buttons are stacked over a vertical narrow barrel. This is shown below:



Now, I will walk you through creating the sample shown above.


3. Adding the Toolbar to form

The toolbar is available in the "Menus & Toolbar" group. First, the ToolStrip control is added, and then the toolbar buttons are added to it.  The appearance will not be impressive after the tool strip buttons are added. So an image of icon size should be assigned to it. The image will usually correspond to the task that button will do. Say for example the Quit toolbar button above shows a cross icon-saying sample is going to be stopped. Creating the toolbar button is shown in the below video:



4. Inserting Standard toolbar buttons

Visual studio provides some standard buttons say New document, Open Document, Cut, Copy etc., so that you can directly start hooking the associated handler to it by writing the one. In this sample also we added these standard buttons. However, there are no events hooked to it, I just kept it so that It will be useful to explain the overflow later. The below video shows adding the standard toolbar buttons:

Video: 


5. Aligning toolbar buttons

Sometimes it is required to align the toolbar buttons to the right side of the toolbar. User Interface designers like to keep the very frequently accessed buttons on the toolbar on the right side of the toolbars. Say for example the help and quit buttons may go on the right side of the toolbar. The below video shows how do we align three toolbar buttons and a separator on the right side of the toolbar. After the alignment, the order may be adjusted as it depends on in what order you are changing the alignment from left to right. The "Alignment Property" of each toolbar buttons helps you to decide the location of the toolbar buttons in the toolbar.

Video:  


6. Display Style of the Toolbar buttons

Each toolbar button has the ability to display and associated text along with their tool icons. It will be good for appearance when the associated text is small enough. Say for example, for the cut icon, the cut is short enough and there is nothing wrong if you put the text as 'move to clipboard'. But the appearance of the toolbar is awkward when the other buttons also use such a long text. You may be asking, I am having a image manipulator application, the icon text I need is Blur the Image then Shear. How do I describe that in short text and does the user understand it if I do?  Well., use whatever text you want with a short terms like Sh.Blur and describe full text in the status bar like Blur the Image then Shear. We will see status bar in the next article.

When we want to display a short text along with the image icon, first you need to set the text property for each toolbar buttons.

Source Code for Display Style


Look at the screen shot at section 2, when the Display Image and Text checkbox is checked, we are going to set each toolbar button to display the associated text in it. Have a look at the below code:


//ToolBar 02: Display text and Image for toolbar buttons
private void chkImgTxt_Click(object sender, EventArgs e)
{
    //Iterate through all the buttons and set the required property
    foreach (ToolStripItem item in tlstrip.Items)
    {
        if (chkImgTxt.Checked == true)
        {
            radTextFirst.Enabled = true;
            radImageFirst.Enabled = true;
            item.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
        }
        else
        {
            radTextFirst.Enabled  = false;
            radImageFirst.Enabled = false;
            item.DisplayStyle = ToolStripItemDisplayStyle.Image;
        }
    }
}

Click event of the checkbox is handled. First, we are iterating through all the toolbar buttons in the ToolStrip control tlstrip.  Inside the iteration, we are setting the "DisplayStyle Property" of the toolbar buttons by getting the values from "ToolStripItemDisplayStyle" enumeration. Also note that we are disabling the radio buttons (radTextFirst, radImageFirst) that control the relative position of the text with images based the checkbox check state. The radio button event handler just makes use the "TextImageRelation Property" to set the relative position of the text with toolbar by assigning the property value from TextImageRelation. Below is the code for it:


//ToolBar 03: Check the Radio button state and set the Relation between Text, Icon Image
private void radTextFirst_CheckedChanged(object sender, EventArgs e)
{
    foreach (ToolStripItem item in tlstrip.Items)
    {
        if (radImageFirst.Checked == true)
            item.TextImageRelation = TextImageRelation.ImageBeforeText;
        else
            item.TextImageRelation = TextImageRelation.TextBeforeImage;
    }
}

The above code behavior at runtime is shown in the below video.

Video: 



7. Managing toolbar button overflow

The ToolStrip control sometimes cannot provide enough room for all the Iconic buttons and other ToolStrip controls. Usually, it happens when the user resizes the parent window of the ToolStrip control. The "CanOverFlow Property" allows toolbar buttons overflow to a separate row or in a stack one on top of the other one. In our example setting the toolbar button to display text along with the image makes some toolbar buttons go away. But when you enable CanOverFlow option, you will still able to access the overflow buttons.

First, the checkbox click event is handled and the handler will set the CanOverFlow property to true when it checkbox is in checked state. Below is the code for it:


//ToolBar 05: Layout style is set to Flow when Overflow is unchecked
private void chkOverflow_CheckedChanged(object sender, EventArgs e)
{
    if (chkOverflow.Checked == false)
    {
        radFlow.Checked = true;
        tlstrip.CanOverflow = false;
        tlstrip.LayoutStyle = ToolStripLayoutStyle.Flow;
    }
    else
        tlstrip.CanOverflow = true;           
}

There are a different type of overflow styles (LayoutStyle Property) available and refer the MSDN for that. Here I just set two important styles to the toolbar using the enumeration "ToolStripLayoutStyle". One is "Flow" and another one is "HorizontalStackWithOverFlow". The Flow will set the overflowing toolbar buttons in the next row and HorizontalStack will place overflowing control one on another and toolbar provides a down-arrow at the end to access the stacked of buttons. The radio button handler is shown below:


//ToolBar 06: Set the Toolbar Layout to Flow
private void radFlow_CheckedChanged(object sender, EventArgs e)
{
    if (radFlow.Checked == true )
        tlstrip.LayoutStyle = ToolStripLayoutStyle.Flow;
}

//ToolBar 07: Items laid out horizantally and when no room, placed in the overflow bar.
private void radHorFlow_CheckedChanged(object sender, EventArgs e)
{
    if (radHorFlow.Checked == true)
        tlstrip.LayoutStyle = ToolStripLayoutStyle.HorizontalStackWithOverflow;
}
Video: 




8. Other Piece of code

1) Overflow is set to false when the form is loading


//ToolBar 04: Set the Overflow to false initially
private void frmToolStripExp_Load(object sender, EventArgs e)
{
    tlstrip.CanOverflow = false;
}

2) Some click handler for the toolbar buttons that we have added to Section 3.


//ToolBar 01: Sample Handlers
private void tsBtn1_Click(object sender, EventArgs e)
{
    MessageBox.Show("Open Notepad");
}

private void tsBtn2_Click(object sender, EventArgs e)
{
    MessageBox.Show("Open Calculator");
}

private void tsBtn3_Click(object sender, EventArgs e)
{
    this.Close();
}
Source Code: Download
Like this site? Tell it to your Firend :)