Introduction
I currently have had a need for a decent grid control that has the ability to
edit and display numbers, among other things. The best one that I could come up
with within my price range (free) was
Chris Maunder's MFC Grid 2.25 [^].
But unfortunately, for me it needed some modifications to get it to work the
way I wanted. The one modification I present here is the CGridCellNumeric
class, which is used to display and edit numbers and currencies. This class is
a severe modification of the CGridCellNumeric
class that is
included with the MFC Grid. The class uses the computer's locale settings to
display the numbers, but does provide a way for you to override those settings.
The numbers, if you set the cell to use floating point, will be kept to an
accuracy of nine decimal places, even if they are only displayed to two. The
full nine decimal digits are shown, if needed, in the edit control part of the
cell.
Input validation is done on the fly as the user is typing. All validation is
done in the EN_UPDATE
message handler, so any cut/copy and paste
operations are immediately validated. If the user deletes the text in the cell,
the value is set to zero.
Using the CGridCellNumeric class
Download and unzip the file, and save the CPP and header file into the "GridCtrl/NewCellTypes"
folder. They can replace the existing GridCellNumeric files already there. I
used those existing files as the starting point for this code.
To add a CGridCellNumeric
cell to the grid, simply add it as you
would any other cell type:
m_Grid.SetCellType(1,1, RUNTIME_CLASS(CGridCellNumeric));
and you are ready to go. To set the options for the numerical cell, you have to
get a pointer to it, and call one of its member functions.
CGridCellNumeric *pCell = (CGridCellNumeric *)m_Grid.GetCell(1, 1);
pCell->SetFlags(CGridCellNumeric::Currency | CGridCellNumeric::Negative);
pCell->SetNumber(125.36);
The CGridCellNumeric
class is derived from CGridCell
,
and the edit control class (CInPlaceNumEdit
) is derived from CInPlaceEdit
,
so other than the API functions listed below, you can use this cell the same as
any other editable cell that is available for the MFC Grid.
Important changes to class CInPlaceEdit
There is one small, but very important change that has to be made to the CInPlaceEdit
class. You must move the CRect m_Rect
variable from being a
private member to being a protected member of the CInPlaceEdit
class.
This has to done so that the derived CInPlaceNumEdit
class can
reset the initial size of the edit box if needed, and it needs access to the m_Rect
member in order to do so. So in the InPlaceEdit.h file, make the
following changes:
class CInPlaceEdit : public CEdit
{
...
protected:
CRect m_Rect;
...
private:
...
};
Also, but not as important, as it is more a cosmetic thing than anything else,
is to change the size of the space buffer that CInPlaceEdit
uses
to calculate the new size of the edit control as you are typing. Go to the file InPlaceEdit.cpp,
in the function CInPlaceEdit::OnChar()
, line 178, and change the
size of the buffer from two spaces to six spaces:
str += _T(" ");
This change will prevent the edit control from scrolling the text to the left
before it resizes the window.
CGridCellNumeric Class API functions
Return Value:
A DWORD
containing the previous flags, -1 if the new flags could
not be set.
-
DWORD GetFlags()
Gets the current flags. See SetFlags
above for possible values.
Return Value:
A DWORD
containing the current flags.
-
BOOL SetNumber (double Number)
Sets the value of the number displayed in the cell. Even though it is stored as
a double
, the accuracy is guaranteed to only nine decimal points.
Unless specified by SetNumberFmt()
or SetCurrencyFmt()
functions (see below), the numbers will be displayed according to the
computer's locale settings, but the accuracy of the internal number is
guaranteed to nine decimal points, and those decimal points are all shown in
the edit control.
Return Value:
TRUE
if the number was successfully set. FALSE
if not.
-
double GetNumber()
Gets the number currently stored in the cell. This number is guaranteed accurate
to nine decimal points.
Return Value:
A double
containing the number in the cell.
-
void SetNumberFmt (LPNUMBERFMT lpNumberFmt)
Use this function if you want to override the computer's default settings for
how integers and floating point numbers are displayed. You can pass in a
pointer to a NUMBERFMT
structure that is used by the GetNumberFormat()
function. Look up GetNumberFormat()
and NUMBERFMT
in
MSDN for more information.
-
void SetCurrencyFmt (LPCURRENCYFMT lpCurrencyFmt)
Use this function if you want to override the computer's default settings for
how currencies are displayed. You can pass in a pointer to a CURRENCYFMT
structure that is used by the GetCurrencyFormat()
function. Look
up GetCurrencyFormat()
and CURRENCYFMT
in MSDN for
more information.
TODO:
Don't know if I will ever get to it, but I think it would be cool if the cell
supported different based numbers other than just base 10. Another possibility
is to support exponential format. But that is probably going to be more work
than what I am willing to put out.
Credits
-
Chris Maunder for his excellent grid control.
-
Andrew Truckle for his original
CGridCellNumeric
class that this
class is based on.
Updates
-
Sept 15, 2004 - released into the wild.