Click here to Skip to main content
Click here to Skip to main content

Tagged as

Simple Grid - A Win32 message based grid control

, 6 May 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
A simple to use grid control for Windows SDK C applications.

Figure1

Figure1 Original Baby Grid Demo

Figure2

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.

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;
    
        /* Initialize common controls. Also needed for MANIFEST's */
    
        icc.dwSize = sizeof(icc);
        icc.dwICC = ICC_WIN95_CLASSES/*|ICC_COOL_CLASSES|ICC_DATE_CLASSES|
                       ICC_PAGESCROLLER_CLASS|ICC_USEREX_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;
    
        //Get hinstance if this code is compiled into and called from a dll 
        // as well as if it were compiled into the executable.  (XP and later)
        GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
         (LPCTSTR)New_SimpleGrid, &hinst);
    
        //Only need to register the property grid once
        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)
    {
        //
        // Create image list
        //
        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);
        }
    
        // Set Row height to accommodate the graphics
        SimpleGrid_SetRowHeight(hGrid,34);
    
        //
        // Create Columns
        //
    
        // Column type
        // Column header text
        // Optional data (ex: combobox choices)
        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
        };
    
        // Add the columns
        for(int k = NELEMS(lpColumns), m = 0; 0 < k; --k, ++m)
        {
            SimpleGrid_AddColumn(hGrid, &lpColumns[m]);
            SimpleGrid_SetColWidth(hGrid, m, 100);
        }
    
        //
        // Add some rows
        //
        for(int i = 0; i < 2; ++i) 
            SimpleGrid_AddRow(hGrid, _T("")); //Don't care about row header text
    
        //
        // Set cells to data
        //
    
        // Column number
        // Row number
        // Item (cell) value
        SGITEM lpItems[] = {
            // Combo column
            0, 0, (LPARAM)_T("Zaparozhets"),
            0, 1, (LPARAM)_T("Citroen"),
    
            // Button column
            1, 0, (LPARAM)_T("#1 On"),
            1, 1, (LPARAM)_T("#2 On"),
    
            // Image column
            2, 0, (LPARAM) 0,
            2, 1, (LPARAM) 0,
    
            // Link column
            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
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    lpColumn
         Pointer to a SimpleGrid column.
    
    Return Values
    The zero-based index of the added column if successful, otherwise SG_ERROR.
    */

    SimpleGrid_AddRow

    Add a column to the grid.

    INT SimpleGrid_AddRow(
         HWND hGrid
         LPTSTR lpszHeader
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    lpszHeader
         The row header text string.
    
    Return Values
    The zero-based index of the added row if successful, otherwise SG_ERROR
    */

    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
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    szHeader
         The row header text string.
    dwAlignment
         The desired text alignment flag: GSA_LEFT, GSA_GENERAL,
         or GSA_RIGHT.
    aryData
         An array of values.
    count
         The number of elements in aryData.
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_Enable

    Enables or disables mouse and keyboard input to the specified grid.

    BOOL SimpleGrid_Enable(
         HWND hGrid
         BOOL fEnable
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    fEnable
         TRUE to allow input, otherwise FALSE.
         
    Return Values
    TRUE If the window was previously disabled, otherwise false.
    */

    SimpleGrid_EnableEdit

    Enable or disable editing in the grid.

    VOID SimpleGrid_EnableEdit(
         HWND hGrid
         BOOL fSet
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    fSet
         TRUE to enable editing in grid, FALSE to disable.
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_ExtendLastColumn

    Set the grid to extend the last column to the end of the client area.

    VOID SimpleGrid_ExtendLastColumn(
         HWND hGrid
         BOOL fSet
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    fSet
         TRUE to extend the last column, otherwise FALSE.
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_GetColCount

    Get the number of columns in grid.

    INT SimpleGrid_GetColCount(
         HWND hGrid
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    
    Return Values
    The column count.
    */

    SimpleGrid_GetColumnHeaderText

    Get the text displayed in the column header.

    INT SimpleGrid_GetColumnHeaderText(
         HWND hGrid
         INT iCol
         LPTSTR lpszBuf
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The number of the column.
    lpszBuf
         A buffer to receive the column header text.
    
    Return Values
    ERROR_SUCCESS otherwise SG_ERROR if desired cell is out of bounds.
    */

    SimpleGrid_GetColumnHeaderTextLen

    Retrieve the length of a string of column header text.

    INT SimpleGrid_GetColumnHeaderTextLen(
         HWND hGrid
         INT iCol
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The number of the column.
    
    Return Values
    The length of the string, in characters, excluding the terminating null character  if 
    successfull, othewise SG_ERROR
    */

    SimpleGrid_GetColumnType

    Get the type of data represented in this cell.

    DWORD SimpleGrid_GetColumnType(
         HWND hGrid
         INT iCol
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The number of the column.
    
    Return Values
    One of the following column types: GCT_EDIT, GCT_COMBO, 
    GCT_BUTTON, GCT_CHECK, GCT_LINK, or GCT_IMAGE, 
    otherwise SG_ERROR if desired cell is out of bounds.
    */

    SimpleGrid_GetColWidth

    Get the width (in pixels) of a column.

    INT SimpleGrid_GetColWidth(
         HWND hGrid
         INT iCol
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The number of the column.
    
    Return Values
    The width of the desired column (in pixels), otherwise SG_ERROR if desired column 
    is out of bounds.
    */

    SimpleGrid_GetCursorCol

    Get the column of the cursor.

    INT SimpleGrid_GetCursorCol(
         HWND hGrid
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    
    Return Values
    The number of the column the cursor currently occupies.
    */

    SimpleGrid_GetCursorRow

    Get the column of the cursor.

    INT SimpleGrid_GetCursorRow(
         HWND hGrid
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    
    Return Values
    The number of the row the cursor currently occupies.
    */

    SimpleGrid_GetHeaderRowHeight

    Get the height of the header row.

    INT SimpleGrid_GetHeaderRowHeight(
         HWND hGrid
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    
    Return Values
    The height (in pixels) of the header row.
    */

    SimpleGrid_GetImageColumnImageList

    Get the image list associated with an image column.

    HIMAGE SimpleGrid_GetImageColumnImageList(
         HWND hGrid
         INT iCol
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The number of the column.
    
    Return Values
    The image list associated with the column if successful, otherwise NULL.
    */

    SimpleGrid_GetItemData

    Get the content of an individual item (cell).

    INT SimpleGrid_GetItemData(
         HWND hGrid
         LPSGIETEM pItem
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    pItem
         A pointer to a SGIETEM struct.
    
    Return Values
    ERROR_SUCCESS, otherwise SG_ERROR if desired cell is out of bounds
    */

    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
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The column index of the item.
    iRow
         The row index of the item.
    pszText
         Pointer to a buffer to recieve text.
    
    Return Values
    The return value is not meaningful.
    */

    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
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The column index of the item.
    iRow
         The row index of the item.
    
    Return Values
    The length of the data, in characters, excluding the terminating null character 
    if successfull, othewise SG_ERROR.
    */

    SimpleGrid_GetItemProtection

    Get the item's (cell's) protection flag.

    INT SimpleGrid_GetItemProtection(
         HWND hGrid
         INT iCol
         INT iRow
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The column index of the item.
    iRow
         The row index of the item.
    
    Return Values
    SG_ERROR if desired cell is out of bounds, TRUE if it is protected, otherwise FALSE.
    */

    SimpleGrid_GetRowCount

    Get the number of rows in grid.

    INT SimpleGrid_GetRowCount(
         HWND hGrid
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    
    Return Values
    The row count.
    */

    SimpleGrid_GetRowHeaderText

    Get the text displayed in the row header.

    INT SimpleGrid_GetRowHeaderText(
         HWND hGrid
         INT iRow
         LPTSTR lpszBuf
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The number of the row.
    lpszBuf
         A buffer to receive the row header text.
    
    Return Values
    ERROR_SUCCESS otherwise SG_ERROR if desired cell is out of bounds.
    */

    SimpleGrid_GetRowHeaderTextLen

    Retrieve the length of a string of row header text.

    INT SimpleGrid_GetRowHeaderTextLen(
         HWND hGrid
         INT iCol
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iRow
         The number of the row.
    
    Return Values
    The length of the string, in characters, excluding the terminating null character  if 
    successfull, othewise SG_ERROR
    */

    SimpleGrid_GetRowHeight

    Get the height (in pixels) of the rows.

    INT SimpleGrid_GetRowHeight(
         HWND hGrid
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    
    Return Values
    The height (in pixels) of the rows
    */

    SimpleGrid_GetTitle

    Get the title text of the grid.

    INT SimpleGrid_GetTitle(
         HWND hGrid
         INT lpch
         LPTSTR cchMax
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    lpch
         The address of a character buffer for text.
    cchMax
         The maximum number of characters to copy.
         
    Return Values
    If the function succeeds, the return value is the length, in characters, 
    of the copied string, not including the terminating null character. If the 
    window has no title bar or text, if the title bar is empty, or if the window 
    or control handle is invalid, the return value is zero.
    */

    SimpleGrid_GetTitleLength

    Get the length, in characters, of the grid's title bar text.

    INT SimpleGrid_GetTitleLength(
         HWND hGrid
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    
    Return Values
    If the function succeeds, the return value is the length, 
    in characters, of the text otherwise 0. 
    */

    SimpleGrid_RefreshGrid

    Cause the grid to redraw itself.

    VOID SimpleGrid_RefreshGrid(
         HWND hGrid
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_ResetContent

    Remove all data, rows, and columns from the grid.

    VOID SimpleGrid_ResetContent(
         HWND hGrid
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    
    Return Values
    The return value is not meaningful.
    */

    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
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The col index of the cell.
    iRow
         The row index of the cell.
    fOverwritemode
         TRUE to overwrite cell contents, FALSE to edit the current contents of the cell.
    
    Return Values
    ERROR_SUCCESS otherwise SG_ERROR if desired cell is out of bounds
    */

    SimpleGrid_SetAllowColResize

    Configure column resizing.

    VOID SimpleGrid_SetAllowColResize(
         HWND hGrid
         BOOL fSet
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    fSet
         fSet TRUE for resizeable columns, FALSE locks in column widths.
    
    Return Values
    The return value is not meaningful.
    */

    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
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    fSet
         fSet TRUE to autosize columns to updated content, 
         otherwise FALSE.
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetColsNumbered

    Sets what is displayed in the Column headers.

    VOID SimpleGrid_SetColsNumbered(
         HWND hGrid
         BOOL fSet
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    fSet
        TRUE to display Column hexavigesimal digits, FALSE to display header text.
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetColumnHeaderText

    Set the text to be displayed in the column header.

    INT SimpleGrid_SetColumnHeaderText(
         HWND hGrid
         INT iCol
         LPTSTR lpszTex
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The index of the column.
    lpszTex
         The text string to display.
         
    Return Values
    ERROR_SUCCESS otherwise SG_ERROR if desired cell is out of bounds.
    */

    SimpleGrid_SetColWidth

    Set the width (in pixels) of a given column.

    INT SimpleGrid_SetColWidth(
         HWND hGrid
         INT iCol
         INT nWidth
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The index of the column.
    nWidth
         The desired width (in pixels) of the column.
         
    Return Values
    ERROR_SUCCESS otherwise SG_ERROR if desired column is out of bounds.
    */

    SimpleGrid_SetCursorPos

    Set the cursor position (or currently selected cell) in the grid.

    INT SimpleGrid_SetCursorPos(
         HWND hGrid
         INT iCol
         INT iRow
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The col index of the cell.
    iRow
         The row index of the cell.
         
    Return Values
    ERROR_SUCCESS otherwise SG_ERROR if desired cell is out of bounds.
    */

    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
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    fSet
        fSet TRUE to use double buffering, FALSE turns double buffering off.
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetEllipsis

    Set the display of text in cell.

    VOID SimpleGrid_SetEllipsis(
         HWND hGrid
         BOOL fSet
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    fSet
        TRUE to draw ellipsis, FALSE to truncate text in short cell.
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetGridLineColor

    Sets the color of the gridlines.

    VOID SimpleGrid_SetGridLineColor(
         HWND hGrid
         COLORREF clrGrdLine
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    clrGrdLine
        A COLORREF value. 
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetHeaderRowHeight

    Set the height (in pixels) of the header row.

    VOID SimpleGrid_SetHeaderRowHeight(
         HWND hGrid
         INT iHeight
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iHeight
        The desired height (in pixels) of the header row. 
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetHeadingFont

    Set the font used in the grid headers.

    VOID SimpleGrid_SetHeadingFont(
         HWND hGrid
         HFONT hFont
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    hFont
        The handle to a font. 
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetHilightColor

    Sets the background color of highlighted cells.

    VOID SimpleGrid_SetHilightColor(
         HWND hGrid
         COLORREF clrHilt
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    clrHilt
        A COLORREF value. 
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetHilightTextColor

    Sets the text color of highlighted cells.

    VOID SimpleGrid_SetHilightTextColor(
         HWND hGrid
         COLORREF clrHlText
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    clrHlText
        A COLORREF value.
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetImageColumnImageList

    Set the image list associated with an image column.

    HIMAGELIST SimpleGrid_SetImageColumnImageList(
         HWND hGrid
         INT icol
         HIMAGELIST himl
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    icol
        The index of a column of type GCT_IMAGE. 
    himl
        The handle to the image list. 
    
    Return Values
    The previous image list associated with the column if successful, otherwise NULL.
    */

    SimpleGrid_SetItemData

    Set the content of an individual cell.

    INT SimpleGrid_SetItemData(
         HWND hGrid
         LPSGITEM pItem
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    pItem
        A pointer to a SGIETEM struct. 
    
    Return Values
    ERROR_SUCCESS otherwise SG_ERROR if desired cell is out of bounds.
    */

    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
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The column index of the item.
    iRow
         The row index of the item.
    pszText
         The text string.
    
    Return Values
    The return value is not meaningful.
    */

    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
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    pItem
         A pointer to a SGIETEM struct.
    dwAlign
         One of the following alignments: GSA_LEFT, GSA_GENERAL, or GSA_RIGHT.
    
    Return Values
    ERROR_SUCCESS otherwise SG_ERROR if desired cell is out of bounds
    */

    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
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The column index of the item.
    iRow
         The row index of the item.
    dwAlign
         One of the following alignments: GSA_LEFT, GSA_GENERAL, or GSA_RIGHT.
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetItemProtection

    Set protection status of an individual cell.

    VOID SimpleGrid_SetItemProtection(
         HWND hGrid
         LPSGIETEM pItem
         BOOL fSet
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    pItem
         A pointer to a SGIETEM struct.
    fSet
         TRUE to protect cell FALSE to allow changes.
    
    Return Values
    ERROR_SUCCESS otherwise SG_ERROR if desired cell is out of bounds
    */

    SimpleGrid_SetItemProtectionEx

    Set protection status of an individual cell.

    VOID SimpleGrid_SetItemProtectionEx(
         HWND hGrid
         INT iCol
         INT iRow
         BOOL fSet
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iCol
         The column index of the item.
    iRow
         The row index of the item.
    fSet
         TRUE to protect cell FALSE to allow changes.
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetProtectColor

    Sets the background color of protected cells.

    VOID SimpleGrid_SetProtectColor(
         HWND hGrid
         COLORREF clrProtect
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    clrProtect
         A COLORREF value. 
    
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetRowHeaderText

    Set the text to be displayed in the column header.

    INT SimpleGrid_SetRowHeaderText(
         HWND hGrid
         INT iRow
         LPTSTR lpszTex
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iRow
         The index of the row.
    lpszTex
         The text string to display.
         
    Return Values
    ERROR_SUCCESS otherwise SG_ERROR if desired cell is out of bounds.
    */

    SimpleGrid_SetRowHeaderWidth

    Set the width (in pixels) of the row header column.

    INT SimpleGrid_SetRowHeaderWidth(
         HWND hGrid
         INT nWidth
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    nWidth
         The desired width (in pixels) of the row headers.
         
    Return Values
    ERROR_SUCCESS otherwise SG_ERROR if desired cell is out of bounds.
    */

    SimpleGrid_SetRowHeight

    Set the height (in pixels) of the rows.

    VOID SimpleGrid_SetRowHeight(
         HWND hGrid
         INT iHeight
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iHeight
         The desired height (in pixels) of the rows.
         
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetRowsNumbered

    Set whether the selected row will be highlighted.

    VOID SimpleGrid_SetRowsNumbered(
         HWND hGrid
         BOOL fSet
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    fSet
         TRUE to display row numbers, FALSE to display header text.
         
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetSelectionMode

    Set whether and how the selected row will be highlighted.

    VOID SimpleGrid_SetSelectionMode(
         HWND hGrid
         INT iMode
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iMode
         iMode One of the following selection mode options: GSO_ROWHEADER, GSO_CELL, or GSO_FULLROW.
         
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetTitle

    Set the text of the grid title.

    BOOL SimpleGrid_SetTitle(
         HWND hGrid
         LPTSTR lpsz
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    lpsz
         The title text.
         
    Return Values
    TRUE if successful, otherwise FALSE.
    */

    SimpleGrid_SetTitleFont

    Set the font used to display the grid title.

    VOID SimpleGrid_SetTitleFont(
         HWND hGrid
         HFONT hFont
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    hFont
         The handle to a font.
         
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_SetTitleHeight

    Set the height of the grid title.

    VOID SimpleGrid_SetTitleHeight(
         HWND hGrid
         INT iHeight
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    iHeight
         The desired height (in pixels) of the title text.
         
    Return Values
    The return value is not meaningful.
    */

    SimpleGrid_ShowIntegralRows

    Set how the grid displays the top and bottom visible rows.

    VOID SimpleGrid_ShowIntegralRows(
         HWND hGrid
         BOOL fShow
         );
    /*Parameters
    hGrid
         Handle to the SimpleGrid control.
    fShow
         TRUE to display bottom visible row at integral height, FALSE allows the display of 
         a partial row.
         
    Return Values
    The return value is not meaningful.
    */

    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;
    
    /*Members
    hdr
         Specifies an NMHDR structure. The code member of the NMHDR structure identifies 
         the notification being sent.
    col
         The column index of the item.
    row
         The row index of the item.
    dwType
         Column type (thus cell type) identifier.
    
    Remarks
         The address of this structure is specified as the lParam parameter of the 
         WM_NOTIFY message for most SimpleGrid control notification messages.*/

    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; 
     
    /*Parameters
    pnm
         Pointer to an NMGRID structure containing notification data.
    
    Return Values
    No return value.*/

    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; 
     
    /*Parameters
    pnm
         Pointer to an NMGRID structure containing notification data.
    
    Return Values
    No return value.*/

    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; 
     
    /*Parameters
    pnm
         Pointer to an NMGRID structure containing notification data.
    
    Return Values
    No return value.*/

    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; 
     
    /*Parameters
    pnm
         Pointer to an NMGRID structure containing notification data.
    
    Return Values
    No return value.*/

    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;
    
    /*Members
    hdr
         Specifies an NMHDR structure. The code member of the NMHDR structure identifies 
         the notification being sent.
    col
         The column index of the item.
    row
         The row index of the item.
    dwType
         Column type (thus cell type) identifier.
    wVKey
         Virtual key code.
    
    Remarks
         The address of this structure is specified as the lParam parameter of the 
         WM_NOTIFY message for the SGN_KEYDOWN notification message.*/

    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; 
     
    /*Parameters
    pnm
         Pointer to an NMSGKEYDOWN structure containing notification data.
    
    Return Values
    No return value.*/

    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;
    
    /*Members
    hdr
         Specifies an NMHDR structure. The code member of the NMHDR structure identifies 
         the notification being sent.
    col
         The column index of the item.
    row
         The row index of the item.
    dwType
         Column type (thus cell type) identifier.
    hFocus
         Handle of window receiving or loosing focus.
    
    Remarks
         The address of this structure is specified as the lParam parameter of the 
         WM_NOTIFY message for SGN_GOTFOCUS and SGN_LOSTFOCUS 
         notification messages.*/

    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; 
     
    /*Parameters
    pnm
         Pointer to an NMSGFOCUS structure containing notification data.
    
    Return Values
    No return value.*/

    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; 
     
    /*Parameters
    pnm
         Pointer to an NMSGFOCUS structure containing notification data.
    
    Return Values
    No return value.*/

    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.

    License

    This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

    Share

    About the Author

    David MacDermot

    United States United States
    No Biography provided

    Comments and Discussions

     
    QuestionFor data demonstration, post msg to (simple grid or parent windows of simple grid), which is more efficient? Thanks. PinprofessionalMember 1036280230-Aug-14 16:02 
    AnswerRe: For data demonstration, post msg to (simple grid or parent windows of simple grid), which is more efficient? Thanks. PinmemberDavid MacDermot2-Sep-14 7:31 
    QuestionDoes Simple Grid support Custom Drawing ? PinprofessionalMember 1036280221-Jul-14 3:58 
    AnswerRe: Does Simple Grid support Custom Drawing ? PinmemberDavid MacDermot21-Jul-14 12:10 
    GeneralRe: Does Simple Grid support Custom Drawing ? PinprofessionalMember 1036280221-Jul-14 14:27 
    QuestionHard to use 'simpleGrid' in VS2010 for a novice programmer. PinprofessionalMember 1036280215-Jun-14 15:29 
    SuggestionNo error in debug and build, but the grid can't display in vs2010 win32 window project. PinprofessionalMember 1036280214-Jun-14 17:11 
    AnswerRe: No error in debug and build, but the grid can't display in vs2010 win32 window project. PinmemberDavid MacDermot16-Jun-14 7:04 
    GeneralRe: No error in debug and build, but the grid can't display in vs2010 win32 window project. PinprofessionalMember 1036280230-Jun-14 18:05 
    AnswerHow to subclass an existing control PinmemberDavid MacDermot1-Jul-14 8:38 
    GeneralRe: How to subclass an existing control PinprofessionalMember 103628022-Jul-14 4:08 
    QuestionDo SimpleGrid can't trigger WM_LBUTTONDBLCLK and WM_RBUTTONDBLCLK Msg ??---- Re: How to subclass an existing control PinprofessionalMember 103628027-Jul-14 19:46 
    AnswerHow to enable WM_LBUTTONDBLCLK and WM_RBUTTONDBLCLK messages in a control [modified] PinmemberDavid MacDermot8-Jul-14 6:09 
    GeneralRe: How to enable WM_LBUTTONDBLCLK and WM_RBUTTONDBLCLK messages in a control PinprofessionalMember 1036280211-Jul-14 4:45 
    AnswerRe: How to enable WM_LBUTTONDBLCLK and WM_RBUTTONDBLCLK messages in a control PinmemberDavid MacDermot11-Jul-14 7:44 
    GeneralStill can't receive WM_LBUTTONDBLCLK and WM_RBUTTONDBLCLK messages in SimpleGrid PinprofessionalMember 1036280218-Jul-14 4:35 
    GeneralRe: No error in debug and build, but the grid can't display in vs2010 win32 window project. PinmemberAnthony Oyovwe30-Aug-14 6:08 
    QuestionDifficult For New Users PinmemberAnthony Oyovwe5-May-14 7:24 
    AnswerRe: Difficult For New Users [modified] PinmemberDavid MacDermot5-May-14 13:41 
    GeneralRe: Difficult For New Users [modified] PinmemberAnthony Oyovwe6-May-14 7:24 
    NewsRe: Difficult For New Users PinmemberDavid MacDermot6-May-14 8:12 
    GeneralRe: Difficult For New Users PinmemberAnthony Oyovwe6-May-14 8:53 
    GeneralRe: Difficult For New Users PinmemberDavid MacDermot6-May-14 11:13 
    GeneralRe: Difficult For New Users PinmemberAnthony Oyovwe7-May-14 12:52 
    GeneralRe: Difficult For New Users PinmemberDavid MacDermot7-May-14 14:19 

    General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

    | Advertise | Privacy | Mobile
    Web01 | 2.8.141022.2 | Last Updated 6 May 2014
    Article Copyright 2013 by David MacDermot
    Everything else Copyright © CodeProject, 1999-2014
    Terms of Service
    Layout: fixed | fluid