Representation of data is one of the central aspects of any application. Tabular representation of data is the most common method of representing given data. Each language/framework provides its own technique, in the form of controls, to present data in tabular format. MFC (Microsoft Foundation Classes) is no exception. One of the controls that it provides is the MSFlexGrid control.

In this discussion, I will focus on the basics of MSFlexGrid. The first section will be about the whys and wherefores of MSFlexGrid. In the second section, I will focus on the steps required to use MSFlexGrid. The third and fourth sections will be about using MSFlexGrid in a real-world application. That’s the outline for this discussion.

MSFlexGrid – What is it?

Simply put, Microsoft FlexGrid or MSFlexGrid is a control that is used to display and operate upon tabular data. It provides a flexible way to sort, merge, and format tables. The table generated by MSFlexGrid can have strings as well as pictures. Thus, MSFlexGrid provides all the essential services expected from control that works on tabular data.

To understand control, it’s essential to know two main aspects of control. They are properties and events. The former is concerned with the attributes of the control such as its look, its rows, columns, and so forth, whereas the latter is concerned with changes in the attributes of the control.

Properties are the methods (also called getters and setters) that help in controlling the attributes or data-fields of a control. The most commonly used properties of MSFlexGrid are:

  • GetRows and SetRows
  • GetTextArray and SetTextArray
  • GetRowSel and GetColSel
  • GetTextMatrix and SetTextMatrix

As you have seen, each property is a combination of getter and setter methods. Below I will discuss each one in detail.

First, the two methods called GetRows and SetRows, are known together as the Rows property. This property is used to get or set the number of rows in a grid. SetRows takes an integer argument that tells how many rows there will be in the grid. Similarly, the GetRows method returns the number of rows in the currently displayed grid.

GetTextArray and SetTextArray together form the TextArray property. This property can be used to set or retrieve the values without using Rows and the corresponding Cols properties. Both GetTextArray and SetTextArray take an argument of the long data-type. This argument is used to retrieve or set the value of the cell specified by the argument. The argument is calculated by multiplying the required row’s number with the column value returned by GetCol, and adding it to the value of the required column number. GetTextArray returns the value of the cell determined by the value in the passed argument. SetTextArray accepts one more argument of type LPCTSTR (which is another name for const char*). The second argument is used to set the new value of the cell specified by the first argument.

Together, GetColSel and SetColSel form the ColSel property. The ColSel property can be used to get the value of a selected column or set the value of a selected column. GetColSel returns a long value indicating the selected column. SetColSet takes a long value that indicates the column to be selected. Akin in its behavior to the ColSel property, there is also a RowSel property that performs a similar operation on rows.

The GetTextMatrix and SetTextMatrix methods together form the TextMatrix property. This property can be used to retrieve or set the value of an arbitrary cell without changing Row and Col properties. The GetTextMatrix takes two arguments of the long type specifying the row and column whose value needs to be retrieved. The SetTextMatrix, along with the two long arguments, takes an extra argument of type LPCTSTR. The third argument is the value that needs to be set in the cell specified by the first two arguments.

Now that we’ve covered all the properties, it’s time to look at events. By definition, an Event is “a change in the state of an object.” The most common events supported by MSFlexGrid are OnKeyPress and OnDblClick. Both of these are common to other controls as well.

The OnKeyPress event is fired when the MSFlexGrid has focus, and the user presses any key. The ASCII value of the pressed key is available through the keyAscii argument. It is of the type short FAR*.

The OnDblClick event, as the name suggests, occurs when the user double clicks a cell. It doesn’t pass on any values.

That completes an overview of MSFlexGrid. Next, let us look at the steps involved in using MSFlexGrid in an application.

The following are the steps required to use MSFlexGrid in an application.

1. Including MSFlexGrid in the project.

2. Setting up the properties of the MSFlexGrid.

3. Declaring an MSFlexGrid variable and using it.

Of these, the first step is divided into different sub-steps.

Including MSFlexGrid in the project

Since FlexGrid is also an ActiveX control, the steps to include it in a project are the same as for adding any other ActiveX control. First, you must open the Components and Controls dialog by selecting it from the Add To Project sub-menu of Project menu. The dialog box that comes up contains all the ActiveX controls that can be added to the current project.

Next, in the dialog box, select “Registered ActiveX Controls.” From the new list that appears, select “Microsoft Hierarchical FlexGrid Control.” Click on the Insert button to add the control to the current project. The added control will appear in the resource editor’s Controls toolbar.

If the control needs to be used as part of a dialog (which is usually the case), perform the steps for adding the controls to a dialog.

Setting up the properties of the MSFlexGrid

The next step is to set up the properties of the FlexGrid. The easiest way is to use the Properties Page to change the default properties to the required values. The other way is to do it programmatically. However, to do so, a declaration of a variable corresponding to the FlexGrid is needed.

Declaring MSFlexGrid variable and using it

Using the “Add Member Variable,” add a variable for FlexGrid. This variable can be used to either change the properties of the FlexGrid or to call the FlexGrid’s methods. For example, if the name of the declared variable is m_Edit_Grid, then one would clear the existing values in the FlexGrid by calling the clear method. The statement would be:

m_Edit_Grid.clear();

That completes the second section. The next section will focus on a small application that will use the MSFlexGrid control.

The application that is going to be developed is based on an example provided by Miss Sormita Chakraborty. The application will take user input and save the input data. The application components will include an SDI window and a dialog that contains the MSFlexGrid. So let’s get started.

The first step is to create an SDI-based application. Then we will add a dialog to the application. Since these are common steps, I will not elaborate on them here. After taking these steps, we will add an MSFlexGrid component by using Components and the controls dialog box. Next, we add a variable for representing the grid control. Let’s name it m_edit.

Then add the following code in the function for the KeyPressed event:

void CEditGrid::OnKeyPressGrid(short FAR* KeyAscii)

{

 

 

ASSERT (KeyAscii != NULL);

 

m_edit.SetWindowText(GetText());

if (*KeyAscii == 13)

{

m_edit.SetSel(0,-1);

}

else

{

CString str;

str = (CString)*KeyAscii;

 

m_edit.SetSel(-1,-1);

m_edit.ReplaceSel(str);

}

 

//Adjust for border height and

//Convert from twips to screen units

m_edit.MoveWindow(((GetCellLeft() – m_lBorderWidth) * m_nLogX)/1440,

((GetCellTop() – m_lBorderHeight) * m_nLogY)/1440,

(GetCellWidth()* m_nLogX)/1440,

(GetCellHeight()* m_nLogY)/1440, FALSE);

m_edit.ShowWindow(SW_SHOW);

m_edit.SetFocus();

}

The code checks to see whether the key pressed has a value of 13. If not, it is saved in a string variable named str. Then it sets the value in the grid. Next, the data retrieved needs to be saved. For that, two arrays are declared in the class that provides the edit functionality for the grid, which is named CEditGrid. The following are the statements:

public:

int m_nLogY;

int m_nLogX;

int i;

int j;

int count;

 CString inputx[200][2];

CString inputy[200][2];

virtual ~CEditGrid();

// virtual void GetInput(CString buf);

virtual void CEditGrid::GetTextGrid();

//other parts not shown for brevity

Once that is done, the values are taken from the grid. The following method contains the logic

void CEditGrid::GetTextGrid()

{

CString strx;

CString stry;

long h=CMSFlexGrid::GetCol()-1;

long r=CMSFlexGrid::GetRow()-1;

if(h==0)

{

inputx[r][h]=CMSFlexGrid::GetText();

i++;

}

else

if(h==1)

{

inputy[r][h]=CMSFlexGrid::GetText();

j++;

}

count++;

}

This method is called from the onUpdateGrid method of the EditGrid class.

//This function is called to update the grid whenever a user leaves a cell

//after making some changes to any cell of the grid.

void CEditGrid::OnUpdateGrid()

{

//Check to see if edit is visible

BOOL bVisible = ::GetWindowLong(m_edit.GetSafeHwnd(), GWL_STYLE) & WS_VISIBLE;

if (bVisible)

{

CString cStr;

m_edit.GetWindowText(cStr);

SetText(cStr);

m_edit.SetWindowText(“”);

m_edit.ShowWindow(SW_HIDE);

GetTextGrid(); //This function is called from here to get the //multiple digit inputs from the grid

}

}

Next we need to set up the part of the program that saves the entered data. In the handler for the OK button of the dialog box, provide the following code:

void CDLGFLEXGRID::OnOK()

{

CString inpx[50];

CString inpy[50];

FILE *fp;

// TODO: Add extra validation here

int k = m_grid.count;

int f = m_grid.i;

int g = m_grid.j;

int a , b;

a = 0;

b = 0;

fp = fopen(“dat.txt”, “w”);

for(int q = 0; q < f; q++)

{

inpx[a] = m_grid.inputx[q][0];

fprintf(fp, ” a=%d %dn”,a,atoi(inpx[a]) );

a++;

}

for(int m = 0;m < g; m++)

{

 

inpy[b] = m_grid.inputy[m][1];

fprintf(fp, ” b=%d %dn”,b,atoi(inpy[b]));

b++;

 }

fclose(fp);

CDialog::OnOK();

}

The first step is to declare the arrays to hold values of the two columns. Here the arrays are named inpx and inpy. Then the total count of the cells, the count of two columns, is retrieved.

The next step is to open the file to write out the input values. To do so, the example makes use of conventional File I/O API. Then the arrays (inpx and inpy) are populated with the values of the two columns. The arrays are populated by iterating over the values of the instance level arrays containing the values entered by the user. Finally, each value is converted to an integer and saved in the file.

That completes the small application that makes use of FlexGrid. However, this leaves a question regarding the serialization of the values in MFC. The answer is there is an API to do so. That will be discussed in the future.

Previous articleFile Handling and Streams in C++
Next articleConst Correctness in C++