Figure1 Original Baby Grid Demo
Figure2 New Columns
Table of Contents
Introduction
Periodically a C programmer will ask around the web for a grid that can be used in a non-MFC project. Usually (s)he will be referred to one or both of two published projects. The first from back in 2002 is Win32 Grid Control with Low Overhead (BABYGRID) [^] by David Hillard. The second is my own adaptation of the List view which I initially published in 2009 Win32 SDK Data Grid View Made Easy [^] which better fit my needs at the time than Mr. Hillard's grid.
Now let's face it, it's a sad state of affairs if that is all one has to choose from for use in a Win32/64 C based application. It's been a while since I published anything new and I was ready for a challenge and so decided it was time to tackle BABYGRID by fixing some known deficiencies and adding a few features. It turned out to be somewhat more work than I anticipated but take it all together it was an enjoyable hobby project, somewhere along the way I even began to feel like a coder again!
Background
I first encountered BABYGRID in 2004 or 2005 and used it in an Engineering Automated Test application I wrote for the QA department where I worked. The grid looked and behaved reasonably well for that application but had some limitations and it was difficult to modify the grid as it had been written. Meanwhile the author realized this and, having gained some experience in writing UI elements, wrote a second, better grid, ZEEGrid which he sold for a reasonable price from his web site for a while. Eventually ZEEGrid disappeared from the web along with the author's website. BREAKING NEWS! ZEEGrid is back and is being made available again by the author, David Hillard, at no cost. You can get ZeeGrid from http://www.kycsepp.com, head on over and check it out.
Here is an excerpt from the legacy comments associated with the BABYGRID article on Code Guru. The new version of BABYGRID he mentions here was released as ZEEGrid.
New version of BABYGRID coming soon! Posted by DHillard on 08/11/2004 01:41pm
I have been working on a new version of this grid for several months now.
The new version will be implemented as a DLL with mostly the same programming interface (SendMessage) as this grid. This will allow for easier access to programmers using other languages besides C/C++.
The new version is being developed from the ground up, using a grid engine for direct access to the grid cell contents. This replaces the binary lookup used in this grid. It also draws and displays MUCH faster than BABYGRID using a backbuffer the create the grid display in memory, then bitblting it to the screen.
It also has these features:
- REAL incell editing (using an edit control)
- Merging cells of rows with identical data
- Column reordering
- Search Grid or Search Column
- Sort by Column
- 127 Color Pallette
- 127 Font Pallette
- Protected cells
- Export grid contents to CSV file
- Print grid
- 9 point cell justification
- Cell left and right indents
- Individual cell background, foreground colors
- Column resizing/hiding
- Fixed columns
- No limit on number of columns (other than available memory)
- No limit on rows (also... available memory)
- 127 icon pallette, Can combine cell text with graphic (icon)
(Essentially fixing all the annoying things with BABYGRID).
Sounds pretty good doesn't it? However duplicating Mr. Hillard's efforts would have me biting off more than I could chew at this time and so I focused instead on the following modest improvements to the original grid concept:
- Organize the source into an easily maintainable and understandable format.
- Document and provide macros for all messages to make it easier to use.
- Grid instances created, stored, and destroyed in the manner common to Win32 applications, thus no artificial limits on the number of grids one can create.
- Rewrite portions of the grid to support Unicode.
- Employ optional double buffering (Simple Grid is double buffered by default).
- Replace the storage list box + binary lookup mechanism with a list of vectors for fast access to cell data.
- Provide several different types of columns for editing and displaying data, namely: text, combobox, link, image, button, and checkbox.
- Unlimited rows, 475255 columns (memory permitting of course.)
- Column resizing/hiding and cell protection were preserved from the original BABYGRID code
- In cell justification options: Left, Right, or General (if General set then numeric content is automatically Right justified while alpha content is automatically left justified.)
Using Simple Grid
To begin, include the SimpleGrid control's header file in the project:
#include "SimpleGrid.h"
The SimpleGrid control is a message based, custom control, and as such must be initialized before use. One way to handle this is to call the initializer in the WinMain()
method of the application just after the call to InitCommonControlsEx()
.
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
INITCOMMONCONTROLSEX icc;
WNDCLASSEX wcx;
ghInstance = hInstance;
icc.dwSize = sizeof(icc);
icc.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&icc);
InitSimpleGrid(hInstance);
To make things simple though, I combined this step in the control's pseudo constructor. It is called only once, the first time a new SimpleGrid control is instantiated.
HWND New_SimpleGrid(HWND hParent, DWORD dwID)
{
static ATOM aControl = 0;
static HWND hControl;
HINSTANCE hinst;
GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)New_SimpleGrid, &hinst);
if (!aControl)
aControl = InitSimpleGrid(hinst);
hControl = CreateWindowEx(0, WC_SIMPLEGRID, _T(""), WS_CHILD |
WS_TABSTOP, 0, 0, 0, 0, hParent, (HMENU)dwID, hinst, NULL);
return hControl;
}
The demo code provides several examples of the different ways data can be entered into the grid for display and manipulation. The following snippet shows how to load the grid with columns of various types and then add and set row data accordingly.
void LoadGrid4(HWND hGrid)
{
INT iImages[] = { IDR_BMP_OFF,
IDR_BMP_ON};
HIMAGELIST hImageList = ImageList_Create(32, 32, ILC_COLOR32, NELEMS(iImages), 1);
for(int i = 0; i < NELEMS(iImages); ++i){
HBITMAP hbmp = (HBITMAP)LoadImage(ghInstance, MAKEINTRESOURCE(iImages[i]), IMAGE_BITMAP, 32, 32,
LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
ImageList_Add(hImageList, hbmp, NULL);
}
SimpleGrid_SetRowHeight(hGrid,34);
SGCOLUMN lpColumns[] = {
GCT_COMBO, _T("Combo Column"),
_T("Ford\0Chevy\0Zaparozhets\0Volkswagen\0Toyota\0Honda\0Citroen\0Fiat\0Volvo\0"),
GCT_BUTTON, _T("Button Column"), NULL,
GCT_IMAGE, _T("Image Column"), hImageList,
GCT_LINK, _T("Link Column"), NULL
};
for(int k = NELEMS(lpColumns), m = 0; 0 < k; --k, ++m)
{
SimpleGrid_AddColumn(hGrid, &lpColumns[m]);
SimpleGrid_SetColWidth(hGrid, m, 100);
}
for(int i = 0; i < 2; ++i)
SimpleGrid_AddRow(hGrid, _T(""));
SGITEM lpItems[] = {
0, 0, (LPARAM)_T("Zaparozhets"),
0, 1, (LPARAM)_T("Citroen"),
1, 0, (LPARAM)_T("#1 On"),
1, 1, (LPARAM)_T("#2 On"),
2, 0, (LPARAM) 0,
2, 1, (LPARAM) 0,
3, 0, (LPARAM)_T("The Code Project\0http:\\\\www.codeproject.com\0"),
3, 1, (LPARAM)_T("The Daily WTF: Curious Perversions in "
"Information Technology\0http:\\\\www.thedailywtf.com\0"),
};
for(int i = 0; i < NELEMS(lpItems); ++i)
{
SimpleGrid_SetItemData(hGrid, &lpItems[i]);
}
}
Note: Columns of type GCT_COMBO
store a list of choices (a double null terminated list of strings) that is shared by each cell in the column. Likewise columns of type GCT_IMAGE
store a handle to an image list shared by each cell in that column. Items in columns of type GCT_LINK
however, take a two item list comprised of link text and URL (also double null terminated list of strings.)
What follows is a programming reference for the SimpleGrid control class.
Public data structures
SGCOLUMN
The SGCOLUMN
structure specifies or receives attributes for a SimpleGrid column.
typedef struct tagSGCOLUMN {
DWORD dwType;
LPTSTR lpszHeader;
LPVOID pOptional;
} SGCOLUMN, *LPSGCOLUMN;
Members
dwType
: The column type identifier. The value may be one of the following:
GCT_EDIT
- Column type: Edit GCT_COMBO
- Column type: Dropdown list GCT_BUTTON
- Column type: Button GCT_CHECK
- Column type: Check box GCT_LINK
- Column type: Link GCT_IMAGE
- Column type: Image
lpszHeader
: The column header text. pOptional
: The column optional parameter. The data type depends on the item type as follows:
GCT_EDIT
, GCT_BUTTON
, GCT_CHECK
and GCT_LINK
- NULL (not used). GCT_COMBO
- A double null terminated list of strings (combo items) shared by each cell in column. GCT_IMAGE
- The handle to an image list shared by each cell in column.
SGITEM
The SGITEM
structure specifies or receives attributes for a SimpleGrid item or cell.
typedef struct tagSGITEM{
int col;
int row;
LPARAM lpCurValue;
} SGITEM, *LPSGITEM;
Members
col
: The column index of the item. row
: The row index of the item. lpCurValue
: The item value. The data type depends on the item type as follows:
GCT_EDIT
, GCT_BUTTON
and GCT_COMBO
- item text displayed in the cell (or button text.) GCT_CHECK
- A boolean TRUE or FALSE. GCT_IMAGE
- An integer, the index of the image displayed.
Messages and Macros
Configure the control to do what you want using Windows messages. To make this easy and as a way of documenting the messages, I created macros for each message. If you prefer to call SendMessage()
or PostMessage()
explicitly, please refer to the macro defs in the header for usage.
Note: If a message returns SG_ERROR
use GetLastError()
to discover details of the error.
SimpleGrid_AddColumn
Add a column to the grid.
INT SimpleGrid_AddColumn(
HWND hGrid
LPSGCOLUMN lpColumn
);
SimpleGrid_AddRow
Add a column to the grid.
INT SimpleGrid_AddRow(
HWND hGrid
LPTSTR lpszHeader
);
SimpleGrid_AddRowData
Add a row of data to the grid. (This combines SimpleGrid_AddRow()
, SimpleGrid_SetItemData()
, and SimpleGrid_SetItemTextAlignment()
into one convenient macro.
VOID SimpleGrid_AddRowData(
HWND hGrid
LPTSTR szHeader
DWORD dwAlignment
LPARAM aryData
INT count
);
SimpleGrid_Enable
Enables or disables mouse and keyboard input to the specified grid.
BOOL SimpleGrid_Enable(
HWND hGrid
BOOL fEnable
);
SimpleGrid_EnableEdit
Enable or disable editing in the grid.
VOID SimpleGrid_EnableEdit(
HWND hGrid
BOOL fSet
);
SimpleGrid_ExtendLastColumn
Set the grid to extend the last column to the end of the client area.
VOID SimpleGrid_ExtendLastColumn(
HWND hGrid
BOOL fSet
);
SimpleGrid_GetColCount
Get the number of columns in grid.
INT SimpleGrid_GetColCount(
HWND hGrid
);
SimpleGrid_GetColumnHeaderText
Get the text displayed in the column header.
INT SimpleGrid_GetColumnHeaderText(
HWND hGrid
INT iCol
LPTSTR lpszBuf
);
SimpleGrid_GetColumnHeaderTextLen
Retrieve the length of a string of column header text.
INT SimpleGrid_GetColumnHeaderTextLen(
HWND hGrid
INT iCol
);
SimpleGrid_GetColumnType
Get the type of data represented in this cell.
DWORD SimpleGrid_GetColumnType(
HWND hGrid
INT iCol
);
SimpleGrid_GetColWidth
Get the width (in pixels) of a column.
INT SimpleGrid_GetColWidth(
HWND hGrid
INT iCol
);
SimpleGrid_GetCursorCol
Get the column of the cursor.
INT SimpleGrid_GetCursorCol(
HWND hGrid
);
SimpleGrid_GetCursorRow
Get the column of the cursor.
INT SimpleGrid_GetCursorRow(
HWND hGrid
);
SimpleGrid_GetHeaderRowHeight
Get the height of the header row.
INT SimpleGrid_GetHeaderRowHeight(
HWND hGrid
);
SimpleGrid_GetImageColumnImageList
Get the image list associated with an image column.
HIMAGE SimpleGrid_GetImageColumnImageList(
HWND hGrid
INT iCol
);
SimpleGrid_GetItemData
Get the content of an individual item (cell).
INT SimpleGrid_GetItemData(
HWND hGrid
LPSGIETEM pItem
);
SimpleGrid_GetItemText
Get the text of an individual item.
Note: If the item belongs to a column of type GCT_EDIT
, GCT_COMBO
, or GCT_BUTTON
, the buffer will be filled with the item text. If the item belongs to a column of type GCT_LINK
the buffer will be filled with a contiguous array buffer consisting of an array of two strings: display text and link URL.
VOID SimpleGrid_GetItemText(
HWND hGrid
INT iCol
INT iRow
LPTSTR pszText
);
SimpleGrid_GetItemDataLen
Retrieve the length of data associated with a grid item.
Note: If the item belongs to a column of type GCT_EDIT
, GCT_COMBO
, or GCT_BUTTON
the returned value is the length of the item text. If the item belongs to a column of type GCT_LINK
the returned value is the length of the contiguous array buffer consisting of an array of two strings: display text and link URL. If the item belongs to a column of type GCT_CHECK
or GCT_IMAGE
then 0 is returned since this data is not a string.
INT SimpleGrid_GetItemDataLen(
HWND hGrid
INT iCol
INT iRow
);
SimpleGrid_GetItemProtection
Get the item's (cell's) protection flag.
INT SimpleGrid_GetItemProtection(
HWND hGrid
INT iCol
INT iRow
);
SimpleGrid_GetRowCount
Get the number of rows in grid.
INT SimpleGrid_GetRowCount(
HWND hGrid
);
SimpleGrid_GetRowHeaderText
Get the text displayed in the row header.
INT SimpleGrid_GetRowHeaderText(
HWND hGrid
INT iRow
LPTSTR lpszBuf
);
SimpleGrid_GetRowHeaderTextLen
Retrieve the length of a string of row header text.
INT SimpleGrid_GetRowHeaderTextLen(
HWND hGrid
INT iRow
);
SimpleGrid_GetRowHeight
Get the height (in pixels) of the rows.
INT SimpleGrid_GetRowHeight(
HWND hGrid
);
SimpleGrid_GetTitle
Get the title text of the grid.
INT SimpleGrid_GetTitle(
HWND hGrid
INT lpch
LPTSTR cchMax
);
SimpleGrid_GetTitleLength
Get the length, in characters, of the grid's title bar text.
INT SimpleGrid_GetTitleLength(
HWND hGrid
);
SimpleGrid_RefreshGrid
Cause the grid to redraw itself.
VOID SimpleGrid_RefreshGrid(
HWND hGrid
);
SimpleGrid_ResetContent
Remove all data, rows, and columns from the grid.
VOID SimpleGrid_ResetContent(
HWND hGrid
);
SimpleGrid_SelectCell
Select a cell and set the focus for editing it's contents.
INT SimpleGrid_SelectCell(
HWND hGrid
INT iCol
INT iRow
INT fOverwritemode
);
SimpleGrid_SetAllowColResize
Configure column resizing.
VOID SimpleGrid_SetAllowColResize(
HWND hGrid
BOOL fSet
);
SimpleGrid_SetColAutoWidth
Configure grid columns to auto adjust to fit contents.
Note: This should be set before adding data to the grid.
VOID SimpleGrid_SetColAutoWidth(
HWND hGrid
BOOL fSet
);
SimpleGrid_SetColsNumbered
Sets what is displayed in the Column headers.
VOID SimpleGrid_SetColsNumbered(
HWND hGrid
BOOL fSet
);
SimpleGrid_SetColumnHeaderText
Set the text to be displayed in the column header.
INT SimpleGrid_SetColumnHeaderText(
HWND hGrid
INT iCol
LPTSTR lpszTex
);
SimpleGrid_SetColWidth
Set the width (in pixels) of a given column.
INT SimpleGrid_SetColWidth(
HWND hGrid
INT iCol
INT nWidth
);
SimpleGrid_SetCursorPos
Set the cursor position (or currently selected cell) in the grid.
INT SimpleGrid_SetCursorPos(
HWND hGrid
INT iCol
INT iRow
);
SimpleGrid_SetDoubleBuffer
Set Double buffer to reduce flicker in a grid with many columns.
Note: By default SimpleGrid uses double buffering.
VOID SimpleGrid_SetDoubleBuffer(
HWND hGrid
BOOL fSet
);
SimpleGrid_SetEllipsis
Set the display of text in cell.
VOID SimpleGrid_SetEllipsis(
HWND hGrid
BOOL fSet
);
SimpleGrid_SetGridLineColor
Sets the color of the gridlines.
VOID SimpleGrid_SetGridLineColor(
HWND hGrid
COLORREF clrGrdLine
);
SimpleGrid_SetHeaderRowHeight
Set the height (in pixels) of the header row.
VOID SimpleGrid_SetHeaderRowHeight(
HWND hGrid
INT iHeight
);
SimpleGrid_SetHeadingFont
Set the font used in the grid headers.
VOID SimpleGrid_SetHeadingFont(
HWND hGrid
HFONT hFont
);
SimpleGrid_SetHilightColor
Sets the background color of highlighted cells.
VOID SimpleGrid_SetHilightColor(
HWND hGrid
COLORREF clrHilt
);
SimpleGrid_SetHilightTextColor
Sets the text color of highlighted cells.
VOID SimpleGrid_SetHilightTextColor(
HWND hGrid
COLORREF clrHlText
);
SimpleGrid_SetImageColumnImageList
Set the image list associated with an image column.
HIMAGELIST SimpleGrid_SetImageColumnImageList(
HWND hGrid
INT icol
HIMAGELIST himl
);
SimpleGrid_SetItemData
Set the content of an individual cell.
INT SimpleGrid_SetItemData(
HWND hGrid
LPSGITEM pItem
);
SimpleGrid_SetItemText
Set the text of an individual item (cell).
Note: If the item belongs to a column of type GCT_EDIT
, GCT_COMBO
, or GCT_BUTTON
the string should contain item text. If the item belongs to a column of type GCT_LINK
the the string should be a contiguous array buffer (or double null terminated string) consisting of an array of two strings: display text and link URL.
VOID SimpleGrid_SetItemText(
HWND hGrid
INT iCol
INT iRow
LPTSTR pszText
);
SimpleGrid_SetItemTextAlignment
Set text alignment of an item to left, general, or right.
Note: Setting the alignment to GSA_GENERAL
(default) causes the grid to align text automatically based on content. Numeric data is right aligned while all other text is left aligned. Alignments only apply to columns of type GCT_EDIT
.
INT SimpleGrid_SetItemTextAlignment(
HWND hGrid
LPSGIETEM pItem
DWORD dwAlign
);
SimpleGrid_SetItemTextAlignmentEx
Set text alignment of an item to Left, general, or right.
Note: Setting the alignment to GSA_GENERAL
(default) causes the grid to align text automatically based on content. Numeric data is right aligned while all other text is left aligned. Alignments only apply to columns of type GCT_EDIT
.
VOID SimpleGrid_SetItemTextAlignmentEx(
HWND hGrid
INT iCol
INT iRow
DWORD dwAlign
);
SimpleGrid_SetItemProtection
Set protection status of an individual cell.
VOID SimpleGrid_SetItemProtection(
HWND hGrid
LPSGIETEM pItem
BOOL fSet
);
SimpleGrid_SetItemProtectionEx
Set protection status of an individual cell.
VOID SimpleGrid_SetItemProtectionEx(
HWND hGrid
INT iCol
INT iRow
BOOL fSet
);
SimpleGrid_SetProtectColor
Sets the background color of protected cells.
VOID SimpleGrid_SetProtectColor(
HWND hGrid
COLORREF clrProtect
);
SimpleGrid_SetRowHeaderText
Set the text to be displayed in the column header.
INT SimpleGrid_SetRowHeaderText(
HWND hGrid
INT iRow
LPTSTR lpszTex
);
SimpleGrid_SetRowHeaderWidth
Set the width (in pixels) of the row header column.
INT SimpleGrid_SetRowHeaderWidth(
HWND hGrid
INT nWidth
);
SimpleGrid_SetRowHeight
Set the height (in pixels) of the rows.
VOID SimpleGrid_SetRowHeight(
HWND hGrid
INT iHeight
);
SimpleGrid_SetRowsNumbered
Set whether the selected row will be highlighted.
VOID SimpleGrid_SetRowsNumbered(
HWND hGrid
BOOL fSet
);
SimpleGrid_SetSelectionMode
Set whether and how the selected row will be highlighted.
VOID SimpleGrid_SetSelectionMode(
HWND hGrid
INT iMode
);
SimpleGrid_SetTitle
Set the text of the grid title.
BOOL SimpleGrid_SetTitle(
HWND hGrid
LPTSTR lpsz
);
SimpleGrid_SetTitleFont
Set the font used to display the grid title.
VOID SimpleGrid_SetTitleFont(
HWND hGrid
HFONT hFont
);
SimpleGrid_SetTitleHeight
Set the height of the grid title.
VOID SimpleGrid_SetTitleHeight(
HWND hGrid
INT iHeight
);
SimpleGrid_ShowIntegralRows
Set how the grid displays the top and bottom visible rows.
VOID SimpleGrid_ShowIntegralRows(
HWND hGrid
BOOL fShow
);
SimpleGrid_InsertRow
Add a row to the grid at a given position.
VOID SimpleGrid_InsertRow(
HWND hGrid
INT position
LPTSTR lpszHeader
);
SimpleGrid_DeleteRow
Add a row to the grid at a given position.
VOID SimpleGrid_DeleteRow(
HWND hGrid
INT position
);
Notifications
SimpleGrid provides notifications via WM_NOTIFY
. The lParam
parameter of these notification messages points to one of several notification data structures. In order to simplify documentation the structure and associated messages are grouped together here.
NMGRID
The NMGRID
structure contains information for most SimpleGrid notifications.
typedef struct tagNMGRID {
NMHDR hdr;
INT col;
INT row;
DWORD dwType;
} NMGRID, *LPNMGRID;
SGN_SELCHANGE
The SGN_SELCHANGE
notification message notifies a simple grid control's parent window that an edit operation was initiated in an editable item. This notification code is sent in the form of a WM_NOTIFY
message.
SGN_SELCHANGE
pnm = (NMGRID *) lParam;
SGN_EDITBEGIN
The SGN_EDITBEGIN
notification message notifies a simple grid control's parent window that an edit operation was initiated in an editable item. This notification code is sent in the form of a WM_NOTIFY
message.
SGN_EDITBEGIN
pnm = (NMGRID *) lParam;
SGN_EDITEND
The SGN_EDITEND
notification message notifies a simple grid control's parent window that an edit operation was compleated in an editable item. This notification code is sent in the form of a WM_NOTIFY
message.
SGN_EDITEND
pnm = (NMGRID *) lParam;
SGN_ITEMCLICK
The SGN_ITEMCLICK
notification message notifies a simple grid control's parent window that an item in the received a mouse click. This notification code is sent in the form of a WM_NOTIFY
message.
SGN_ITEMCLICK
pnm = (NMGRID *) lParam;
NMSGKEYDOWN
The NMSGKEYDOWN
structure contains information for the SGN_KEYDOWN
notification.
typedef struct tagNMSGKEYDOWN {
NMHDR hdr;
int col;
int row;
DWORD dwType;
WORD wVKey;
} NMSGKEYDOWN, *LPNMSGKEYDOWN;
SGN_KEYDOWN
The SGN_KEYDOWN
notification message notifies a simple grid control's parent window that a key has been pressed. This notification code is sent in the form of a WM_NOTIFY
message.
SGN_KEYDOWN
pnm = (NMSGKEYDOWN *) lParam;
NMSGFOCUS
The NMSGFOCUS
structure contains information for the SGN_GOTFOCUS
and SGN_LOSTFOCUS
notifications.
typedef struct tagNMSGFOCUS {
NMHDR hdr;
int col;
int row;
DWORD dwType;
HWND hFocus;
} NMSGFOCUS, *LPNMSGFOCUS;
SGN_GOTFOCUS
The SGN_GOTFOCUS
notification message notifies a simple grid control's parent window that the grid now has keyboard and mouse focus. This notification code is sent in the form of a WM_NOTIFY
message.
SGN_GOTFOCUS
pnm = (NMSGFOCUS *) lParam;
SGN_LOSTFOCUS
The SGN_LOSTFOCUS
notification message notifies a simple grid control's parent window that the grid no longer has keyboard and mouse focus. This notification code is sent in the form of a WM_NOTIFY
message.
SGN_LOSTFOCUS
pnm = (NMSGFOCUS *) lParam;
Things to do someday
Make SimpleGrid theme compliant:
- In a previous article [^] I discussed a simple method to make the editor controls borderless. Since then, I moved to Windows 7 and noticed that this didn't always achieve the desired result in a themed window. I took the lazy way out and employed
SetWindowTheme(hwnd, L" ", L" ")
in the editor constructor for the button and combobox. This, in effect, forces these controls to be drawn unthemed while not affecting the rest of the grid. As far as the inactive cells go, The buttons and checks are drawn using DrawFrameControl()
. Theming doesn't seem to extend to them. This gives the grid a rather utilitarian look and feel in a vista/win7 environment.
Final Comments
I documented this source with Doxygen [^] comments for those that might find it helpful or useful. Your feedback is appreciated.
History
- November 13, 2013: Version 1.0.0.0. - Initial Release
- November 15, 2013: Version 1.1.0.0. - Bug Fix
- November 16, 2013: Version 1.2.0.0. - Fixed potential bug condition under X64 operation
- March 06, 2014 Version 1.3.0.0. - Fixed Bug where
SG_RESETCONTENT
message handled incorrectly. - March 07, 2014 Version 1.4.0.0. - Fixed Bug where an active in-cell editor wasn't removed when the grid content was reset.
- March 27, 2014 Version 1.5.0.0. - Several Modifications and Bug fixes:
- Added message
SG_SELECTCELL
and macro def. SimpleGrid_SelectCell().
- Renumbered messages.
- Redefined message
SG_SETCURSORPOS
and macro def. SimpleGrid_SetCursorPos()
so that the column argument is passed as the WPARAM and row argument as LPARAM in order that they might be consistent with the rest of the messages. - Changed the behavior of the grid so that it doesn't initiate a cell edit if just any key is pressed. (Now if the windows key is pressed the selected cell will not go into edit mode when the windows menu launches.)
- Fixed the Factory method
New_SimpleGrid()
so that it should work if it is compiled into a DLL. - Fixed bug where mousing away from a cell during edit resulted in the cell not being updated.
- April 7, 2014 Version 1.6.0.0. - Added an option to the
SG_SELECTCELL
message to Select Cell for either editing or overwriting. This better duplicates a behavior available in spreadsheet software. The macro SimpleGrid_SelectCell()
also reflects this change. - April 8, 2014 Version 1.7.0.0. - Improved the behavior of an in cell edit when
SimpleGrid_SelectCell()
is called with edit mode enabled. Now the left and right arrow keys navagate the in-cell text instead of causing a jump to the next cell. - April 8, 2014 Version 1.8.0.0. - Fixed a bug introduced into the demo by the refactored changes in Version 1.5.0.0. Also refactored notification methods in SimpleGrid.c
- May 6, 2014 Version 1.9.0.0. - Several Modifications and Bug fixes:
- Fixed bug where edited text would be reset after resizing a column.
- Refactored portions to make source easier to port to MSVC++. (For the rest see: Adapting C99 code to MSVC.)
- Editor and button fonts now set to parent grid font.
- January 22, 2015 Version 2.0.0.0 - Fixed a bug introduced in 1.9 where button not destroyed when resizing a button column.
- February 26, 2016 Version 2.1.0.0 - Added two new messages SimpleGrid_InsertRow and SimpleGrid_DeleteRow. Special thanks to Ferenc Hechler for contributing the code to insert a row into the grid.
- March 28, 2016 Version 2.2.0.0 - Fixed the macroes SimpleGrid_GetRowHeaderText and SimpleGrid_GetRowHeaderTextLen.
- June 24, 2018 Version 2.2.1.0 (MSVC project only) - Fixed truncated text bug in MSVC project - Special thanks to Hans-Peter Kalb