Sample Application
Problem
How to edit the MSFlexGrid cell?
Solution
The idea is simple. When you want to edit the text in a cell, you only need to retrieve the cell's rectangle (that is Top, Bottom, and Left) and place a Combobox control over it. The combobox control will manage all the keyboard input. When the editing is finished, the text in the Combobox control is written into the cell, replacing the previous text. Then, the Combobox is hidden until you want to edit another cell again.
Step 1
Select the Dialog Based option in the AppWizard and accept all the default setting.
Step 2
Create a new dialog resource with IDD_COMBO_DLG. Choose resource from Visual C++'s Insert Menu. The Insert Resource dialog appears. Click on Dialog, and then click New. Visual C++ creates a new dialog resource, as shown here.
Step 3
Choose Add To Project from Visual C++'s Project menu, choose Components And Controls from the submenu. Select Registered Activex Controls, and then choose Microsoft FlexGrid Control, Version 6.0 (SP6). Visual C++ will generate the wrapper class for the control. And add the Combo Box from the control palette.
Step 4
Use ClassWizard to add data member to the CflexGridComboclass. Click on the member variables tab, and then add the data members as shown:
| Control IDS |
Type |
Member |
IDC_COMBO |
CcomboBox |
m_cCombo |
IDC_MSFLEX |
CMSFLexGrid |
m_FlexGrid |
Step 5
Use Class Wizard to map the WM_INITDIALOG and event handler functions for Edit Control EN_KILLFOCUS and MSFlexGrid control Click.
Step 6
The OnInitDialog member function needs to set a column width and assign the value for MSFlexGrid. With the Help of SetColWidth(index, width) function, I used to set width of the each column in the MSFlexGrid and initialize, to set text for fixed Row in the MSFlexGrid using the function SetTextMatrix(Rowindex, Colindex, string). Combobox is hidden until you want to edit the cell.
BOOL CFlexGridCombo::OnInitDialog()
{
CDialog::OnInitDialog();
m_FlexGrid.SetColWidth( 0, 1500);
m_FlexGrid.SetColWidth( 1, 1500);
m_FlexGrid.SetColWidth( 2, 1500);
m_FlexGrid.SetTextMatrix( 0, 0, "Name");
m_FlexGrid.SetTextMatrix( 0, 1, "Computer Science");
m_FlexGrid.SetTextMatrix( 0, 2, "Mathematics");
m_FlexGrid.SetTextMatrix( 0, 3, "Status");
m_cCombo.ShowWindow(SW_HIDE);
return TRUE; }
Step 7
Edit the file FlexCombo.h. Add the following public member function:
void DisplayControl(CRect &rectData);
Step 8
In the DisplayControl function, with the help of the CMSFlexGrid Object, I used to get the WindowRect. Using GetCellLeft(), GetCellWidth(), GetCellTop() and GetCellHeight() function, the MSFlexGrid cell left, width and Height are easily found out and assigned to the Crect variable, rectData.bottom, rectData.top, rectData.left and rectData.right.
void CFlexGridCombo :: DisplayControl(CRect &rectData)
{
CMSFlexGrid *pGridData = 0;
pGridData = &m_FlexGrid;
CRect rectWnd;
pGridData->GetWindowRect(&rectWnd);
ScreenToClient(&rectWnd);
int nleft = rectWnd.left+(pGridData->GetCellLeft()/15);
int ntop = rectWnd.top+(pGridData->GetCellTop()/15); int nright = pGridData->GetCellWidth()/15;
int nbottom = pGridData->GetCellHeight()/15;
rectData.bottom = nbottom;
rectData.top = ntop;
rectData.left = nleft;
rectData.right = nright;
}
Step 9
When the particular column of the cell is clicked. First, retrieve the cell's rectangle (that is Left, Right, Top and Bottom) using the function DisplayControl. With help of the AddString function, all the strings are added in the ComboBox and ComboBox control displayed in its current state. Using the MoveWindow function, the ComboBox control is placed in the particular cell of the FlexGrid.
void CFlexGridCombo::OnClickMsflex()
{
CRect rectCntrl;
DisplayControl(rectCntrl);
CString mPrevText;
CMSFlexGrid *pGridData = 0;
int iCol = m_FlexGrid.GetColSel();
CString str;
pGridData = &m_FlexGrid;
m_cCombo.ShowWindow(SW_NORMAL);
m_cCombo.ResetContent();
m_cCombo.MoveWindow(rectCntrl.left,rectCntrl.top,
rectCntrl.right,rectCntrl.bottom,TRUE);
if( iCol == 0)
{
m_cCombo.AddString("ShanmugaRaja");
m_cCombo.AddString("Ganesh Mangal");
m_cCombo.AddString("Deepesh");
m_cCombo.AddString("Sathish");
m_cCombo.AddString("Mehta");
m_cCombo.AddString("Annamalai");
m_cCombo.AddString("Java Senthil");
}
if( ( iCol == 1 ) || ( iCol == 2) )
{
for( int i=0; i<=100; i++ )
{
str.Format("%d",i);
m_cCombo.AddString(str);
}
}
if( iCol == 3 )
{
m_cCombo.AddString("Pass");
m_cCombo.AddString("FAIL");
}
m_cCombo.SetFocus();
UpdateData(FALSE);
}
Step 10
Whenever Combobox control loses focus, the KillFocus event is triggered and using SetTextMatrix function, value are placed in the corresponding cell and then, the ComboBox box is hidden until you want to edit another cell again.
void CFlexGridCombo::OnKillfocusCombo()
{
CString strCombo;
int iRow, iCol;
iRow = m_FlexGrid.GetRowSel();
iCol = m_FlexGrid.GetColSel();
m_cCombo.GetWindowText( strCombo );
m_FlexGrid.SetTextMatrix( iRow, iCol, strCombo );
m_cCombo.ShowWindow(SW_HIDE);
}
Step 11
Build and test the application.
Finally
I hope my control helps you to edit MSFlexGrid. All friends of CodeProject can use my ActiveX if it is useful.
If you have any ideas, I hope to know and if you find any problems, you can tell me.
Thanks to CodeProject and to all.
History
- 5th June, 2010: Initial version