Virtual Grid Control(Merge Header)

来源:百度文库 编辑:神马文学网 时间:2024/04/28 21:37:33
http://www.codeproject.com/KB/miscctrl/virtgrid.aspx 
  • Download demo EXE - 54.1 Kb
  • Download demo project - 108 Kb

Note: Demo project utilizes the great CRollupCtrl written by Johann Nadalutti. Many thanks Johann.

Contents

  • Introduction
  • How to use
  • Required files
  • Structure
  • Some frequently used methods
  • What's new
  • Known bugs and limitations
  • History

Introduction

It is a very simple grid. It is a custom control derived from CWnd. It is inspired by the excellent Delphi TGridView component written by Roman Mochalov. Header of the grid is a separate logical object (separate from non-fixed, "working" part of the grid). Non-fixed part of the grid can work only in virtual mode, i.e., data for display is stored outside the grid and loaded only by query when the grid needs repainting. That is why the grid is called "virtual". If you don't understand my explanation of control's "virtuality", then I'd recommend you to read "Virtual list view description" of CListCtrl in the MSDN help.

The control features:

  • derived from CWnd, though has almost all CListCtrl features (in virtual mode);
  • can be tuned to look like CListCtrl in report mode;
  • smooth horizontal cell scrolling;
  • title tips for both header sections and regular cells;
  • possibility to forbid setting the cursor for certain cells;
  • multiline, multisectional, hierarchical (with possibility of designing one section per several columns) grid header as separated (from regular cells) logical object;
  • code auto-generation for columns and header construction;
  • possibility of word wrap in grid header;
  • header sections can be flat or 3D (button-like);
  • handling of mouse-clicking at header cells (in button mode);
  • in-cell edit and combo controls (appropriate style can be set for each cell individually);
  • changing column width with mouse at runtime (with possibility to forbid this operation for certain columns);
  • column width constraints (min width / max width restrictions);
  • cell text alignment for each cell individually (left, right, center);
  • in-cell images;
  • in-cell check controls (check box-like or radio button-like);
  • fixed columns (always in the left side of the grid);
  • fixed columns can be flat or 3D (button-like);
  • single cell selection (default) or whole row selection;
  • background and text colors for each cell individually;

How to use

First, insert into your dialog template custom control. Just like this:

Don't forget to write "CVirtualGridCtrl" as the class name in the Custom Control Properties dialog box.

Second, include VirtualGridCtrl.h in your dialog's header file and declare a variable of type CVirtualGridCtrl. It goes something like this:

Collapse Copy Code
//{{AFX_DATA(CVirtualGridDemoDlg)//}}AFX_DATACVirtualGridCtrl m_grid;

Third, add next line in the DoDataExchange function of your dialog CPP source file. Like this:

Collapse Copy Code
//}}AFX_DATA_MAPDDX_Control(pDX, IDC_GRID, m_grid);

Note

Alternatively, you can use CVirtualGridCtrl::Create:

Collapse Copy Code
CVirtualGridCtrl m_grid;bSuccess = m_grid.Create(rect, pParentWnd, nID);

where rect is the dimensions, pParentWnd is the parent window, and nID is the ID. This could be the only way to use custom controls in some cases (e.g., if you're writing something based on specific MFC extensions, such as AutoCAD's ObectARX application).

Fourth, add the following files to your project:

  • VirtualGridCtrl.h and VirtualGridCtrl.cpp
  • GridButton.h and GridButton.cpp
  • GridEdit.h and GridEdit.cpp
  • GridListBox.h and GridListBox.cpp
  • TitleTip.h and TitleTip.cpp
  • MemDC.h

If you run the project after completing all these operations, you'll see such a thoughtful picture:

Actually, I'm not sure this result would suit you. So what to do next? You're probably thinking I'll give you some boring instructions such as "add some code", "add this line", "add that line", "press Enter" etc.? I'm glad to disappoint you. Let's walk another way. Launch demo executable. In the demo application window, press the "Header and columns properties" button. You'll see something like this:

In the "Columns" list view, shift-select all items and delete them by clicking the "Remove" button: we're going to start from scratch. Click the "Apply" button, and then click the "Add" button six times. This will add six columns to the grid with default parameters (column's caption is empty, width is 64, max width is 10000 etc.). Press the OK button. Our dialog box would look like this:

Drag manually (I mean using mouse) header sections to be like this:

Click the "Header and columns properties" button again and go to "Headers" page:

Select the very first subtree item in the "Header sections" tree, set the item's Text property to "Points", Alignment property to Center, and click the "Apply" button:

Click (just in case) the "Points" tree item again and press the "Add" button twice. Set the Text property to two recently added sections as "#" and "Point name" respectively.

Using this simple technique, format the grid's header until it takes the shape like this:

In the "Virtual Grid properties" property sheet, select the "Columns" page again and set the properties you like for each column. Note that "Alignment" property here works for regular cells only and ...actually not all features here are already implemented.

After completing all required formatting tasks on columns and headers, go to "Code generation" tab:

Check the "Allow edit grid cells" check box and set "Initial row count" to 5. Then, click the "Generate" button. After this, we can watch such a picture:

After clicking the "Select and copy" button, all recently generated code will be copied into clipboard. All you need is to paste the generated code into your OnInitDialog() method. After compiling and running your own project, you should see such a picture:

Whoa! But they are empty! Non-fixed cells, I mean. Don't worry, just use VGN_GETDISPINFO notification message. This allows you to to set cell text, cell text color, cell background color, and cell image... the same way it is implemented in standard CListCtrl (in virtual mode).

The following notification messages are also available:

  • VGN_CELLACCEPTCURSOR - if you want to allow (or suppress) cell selection;
  • VGN_GETEDITSTYLE - if you want to choose cell style (see below);
  • VGN_GETALLOWEDIT - if you want to allow (or suppress) cell editing;
  • VGN_EDITBUTTONPRESS - if you want to handle ellipsis button click (see below);
  • VGN_GETEDITLIST - if you want to use in-cell combo boxes (see below);
  • VGN_EDITACCEPTKEY - if you want to suppress the input into in-cell edit control some characters (or numbers);
  • VGN_EDITCANCELED - if you want to handle the event when user hits Escape key while in-cell editing;
  • VGN_GETCELLTEXTINDENT - if you want to set horizontal cell's text offset;
  • VGN_DRAWCELL - if you want to implement custom cell painting;
  • VGN_GETCELLIMAGEINDENT - if you want to offset cell's image (if present);
  • VGN_HEADERCLICKING - emitted immediately before mouse click at header section (if the header is not flat);
  • VGN_HEADERCLICK - emitted immediately after mouse click at header section;
  • VGN_GETCHECKKIND - if you want to set cell's check style (no check / check box / radio button);
  • VGN_GETCHECKSTATE - if you want to set cell's check state (checked / unchecked / indeterminate);
  • VGN_CHECKCLICK - if you want to handle cell's check clicking.

("VGN" stands for "Virtual Grid Notification".)

What is cell style? By default, if you double-click grid cell (if this cell allows selection and editing) it launches in-place editing. You can override this by setting geEllipsis style. In this case, in addition to in-place edit, a button with ellipsis will appear. Clicking this button will generate VGN_EDITBUTTONPRESS notify message.

Since v. 1.03, you can also set gePickList style. In this case, in addition to in-place edit, there will appear something like a combo box. (Actually, it is not a full-fledged combo, it is just a button and list box below it, but functionality is almost the same). Reasonable question: how to use it? Simple enough. You should decide: to use combo boxes in each cell in given column or to set cell's style individually.

First case is much easier: this could be done automatically using the demo's code generation feature. In the Header and columns properties dialog box, select desired column and change its Edit style property to gePickList. The button to the right to Edit style combo will be enabled.

Press the button and enter desired combo box items into the dialog box that must appear:

After that, generate the code and insert it into your OnInitDialog procedure.

Second case is also easy enough: just handle VGN_GETEDITLIST notification message by filling the listStrings field in the VGITEM structure.

Required files

  • VirtualGridCtrl.h and VirtualGridCtrl.cpp
  • GridButton.h and GridButton.cpp
  • GridEdit.h and GridEdit.cpp
  • GridListBox.h and GridListBox.cpp
  • TitleTip.h and TitleTip.cpp (Based on code written by Zafir Anjum and modified by Chris Maunder)
  • MemDC.h (Keith Rule's memory Device Context class)

Structure

The main grid class is (it was to be expected) CVirtualGridCtrl. Grid header is represented by CGridHeader class. CGridHeader includes CGridHeaderSections class that could be simplistically considered as an array of CGridHeaderSection objects. Grid's fixed columns are represented by CGridFixed class. Grid columns, both fixed and regular, are represented by CGridColumns class. Each separate column is represented by CGridColumn class. Since the grid can work only in virtual mode, there's no need to hold a huge array of grid cell objects. The very simple CGridCell class containing only cell's column and row, can be thought of as "on-duty" class for grid-to-programmer communication purposes only, not to store any information.

All regular grid cells are represented by single CGridRows objects, containing such info as number of regular grid rows and height of each row (since grid's virtuality, all grid rows are of the same height).

The VGITEM structure was developed for use in notification messages:

Collapse Copy Code
struct VGITEM  {//  ------------  "Traditional" ListCtrl-like part  ------------    int mask;           //  LVIF_TEXT, LVIF_IMAGE, LVIF_COLOR    int nColumn;        //  Cell's column (0 - based)    int nRow;           //  Cell's row (0 - based)    CString strText;    //  For use with VGN_GETDISPINFO                        //  (with LVIF_TEXT mask)    int nAlign;         //  LVCFMT_LEFT, LVCFMT_RIGHT,                        //    LVCFMT_CENTER    int nImage;         //  Cell's image index (- 1) if no                        //  image required//  -------  Extended, VirtualGridCtrl-like part  ------    BOOL bAcceptCursor;        //  For use with VGN_CELLACCEPTCURSOR    BOOL bReadOnly;            //  For use with VGN_GETEDITSTYLE    BOOL bEditAcceptKey;       //  For use with VGN_EDITACCEPTKEY    BOOL bDefDraw;             //  *reserved*    GridEditStyle style;       //  For use with VGN_GETEDITSTYLE    CStringArray listStrings;  //  For use with VGN_GETEDITLIST    CPoint indent;     //  For use with VGN_GETCELLTEXTINDENT    RECT rc;           //  *reserved*    CDC *pDC;          //  To set cell's background and text                       //  colors...    GridCheckKind checkKind; //  For use with VGN_GETCHECKKIND    int nCheckState;         //  For use with VGN_GETCHECKSTATE    CGridHeaderSection *pSection;    //  For VGN_HEADERCLICKING /                    //      VGN_HEADERCLICK                    //  handling};

Some frequently used methods

  • BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID)

    You construct a CVirtualGridCtrl in two steps. First call the constructor, then call Create, which creates the virtual grid control and attaches it to the CVirtualGridCtrl object.

  • BOOL GetDoubleBuffered()

    Is currently using the CMemDC?.

  • void SetDoubleBuffered(BOOL bDoubleBuffered = TRUE)

    To use or not to use CMemDC...

  • int GetFontHeight(CFont *pFont)

    Simple approximate calculation of font height using CDC::GetTextExtent().

  • GridCheckStyle GetCheckStyle()

    Retrieves the style of cell's check boxes. Possible values: cs3D (default), csFlat (using the DFCS_FLAT style).

  • BOOL GetAlwaysSelected()

    Is the focus always be shown?

  • BOOL GetAlwaysEdit()

    Always show in-cell edit control?

  • BOOL GetAllowEdit()

    Is the in-cell edit control visible? Note: Although the edit control can be visible, it is not necessary that the cell could be edited. Editing possibility is controlled by m_bReadOnly field of appropriate column or the whole grid. (Use GetReadOnly() / SetReadOnly() for this).

  • int GetRowCount()

    Retrieves current number of regular grid rows.

  • void SetRowHeight(int nHeight = 17)

    Set the height for every grid row.

  • BOOL GetRowSelect()

    To select the whole row or single cell only?

  • BOOL GetAllowSelect()

    Is cell selection allowed?

  • void SetFixedCount(int nCount)

    Setting amount of fixed columns.

  • CGridColumns * GetGridColumns()

    Retrieves the pointer to grid's CGridColumns object.

  • CGridCell GetCellFocused()

    Retrieves currently selected regular grid cell (or cell with column and row both set to -1 if no cell is actually selected).

  • int AddColumn(LPCTSTR lpCaption = _T(""), int nWidth = 64, int nAlignment = LVCFMT_LEFT)

    Adds new column to the grid with caption set to lpCaption, width set to nWidth, and text alignment set to nAlignment.

  • void SetRowCount(int nCount)

    Sets total amount of grid rows.

What's new

Scrolling (both horizontal and vertical) is working now more or less properly (at last!). Double buffering is re-implemented (using Keith Rule's CMemDC class). Cell check style is implemented. Button-like 3D header sections and fixed columns is introduced. Amount of notification messages is increased.

Known bugs and limitations

(Actually there're more unknown ones).

  • Still weakly documented.
  • Source code is not message based. Please give me advice: is it really worth to be implemented?

History

  • 1.00 - September 11, 2002

    First release.

  • 1.01 - September 17, 2002
    • Added horizontal scroll bar functionality (not yet ideal).
    • Added VGN_SETDISPINFO notification handling. Now the grid is really Virtual.
    • Added arrow keys and Home/End keyboard navigation through cells.
    • In-place editing is now implemented (by pressing character key, not necessarily double clicking the cell).
    • Fixed bug: now text is really focused in focused cell.
  • 1.02 - January 9, 2003
    • Completely rewritten from scratch. Not completely compatible with previous subversions.
    • New hierarchical header is based on tree ideology. Introduced some code generation features.
  • 1.03 - January 22, 2003
    • Added tool tips functionality.
    • Combo box-like cell style is introduced.
    • Different combination of grid styles now implemented.
    • Fixed columns are implemented.
    • Fixed bug: memory leaks are prevented in one of the destructors.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Yuriy Zabroda


Member
Occupation: Software Developer (Senior) Location: Ukraine
Other popular Miscellaneous articles:
  • MFC Grid control 2.26 A fully featured MFC grid control for displaying tabular data. The grid is a custom control derived from CWnd
  • Themed Windows XP style Explorer Bar A fully customizable Windows XP style Explorer Bar that supports Windows XP themes and animated expand/collapse with transparency.
  • TaskbarNotifier, a skinnable MSN Messenger-like popup in C# and now in VB.NET too The TaskbarNotifier class allows to display an MSN Messenger-like animated popup with a skinned background
  • CPPToolTip v2.1 A class that allows you to display your data for a control as tooltip
  • Formula Editor Formula-editor for editing and exporting mathematical content
 (#)