Introduction
This is an extension to CListViewCtrl
for WTL (Windows Template Library). It supports exchange of most OLEDB datatypes (excluding blob types) between an OLEDB source and a virtual listview control placed in a view window or on a dialog. It was developed and tested with MS SQL Server but should work with any OLEDB accessible database.
Development environment
This template is compatible with WTL 8.0 and the samples were created in Visual Studio 2008. However, earlier versions of WTL and VS should be supportable with minor modifications.
Background
The WTLVirtualList
interfaces an OLEDB consumer to an owner-supplied data (LVS_OWNERDATA
) report-style listview control. A handler provides data in response to LVN_GETDISPINFO
messages. This control dynamically creates listview columns using the consumer-supplied column names and displays an in-place edit control in response to a double click on a subitem. It supports bookmarks for row identification and manipulation, and provides menu handlers for common operations such as move, add, and delete. Column data editing is accomplished with an in-place edit control.
Using the code
The starting point for using this class in your application is generating an OLEDB consumer class for your database table. See Introduction to WTL OLEDB Database Applications for details on how to create an OLEDB consumer class using the ATL Object Wizard. Make a few simple modifications to your consumer class as outlined below to support the bookmark function. Download the sample projects and consult the Titles.h or Customers.h fils if you need assistance.
- Add
CBookmark<4> m_Bookmark;
and DBSTATUS m_dwBookmarkStatus;
as member variables
- Add
pPropSet->AddProperty(DBPROP_IRowsetLocate, true, DBPROPOPTIONS_OPTIONAL);
to the GetRowsetProperties
function
- Add
BOOKMARK_ENTRY_STATUS(m_Bookmark, m_dwBookmarkStatus)
to the column map
Add a member variable to MainFrm or MainDlg
After your consumer is created and modified, you need to add the WTLVirtualList
header to your project and add the CWTLVirtualList<Cxxxxx> m_view;
member variable (replace xxxxx with your consumer class name) to your dialog or frame. Initialization for a view window is handled automatically but make sure you add REFLECT_NOTIFICATIONS()
to the main frame message map.
Dialog-based applications
You need to add a listview control to your dialog using the resource editor and then place the following code in OnInitDialog
to initialize the virtual listview.
m_view.Init(GetDlgItem(IDC_LIST1));
int col = 0;
if (!m_view.GetShowBookmarks()) col = 1;
m_view.SetColumnWidth(col, LVSCW_AUTOSIZE_USEHEADER);
m_view.SetBarColor(BLUEBAR);
Menu or button mapping
You'll also want to add command handlers to the message map and, if needed, overridden event handlers for the data commands. As noted above, the virtual list class contains a set of default menu identifiers and event handlers in CLVMenuCommands
that handle ordinary data functions. You would need to override the default handler if you need to set key and/or default values when inserting a new record. For example:
LRESULT OnDataNew(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
m_view.m_data.ClearRecordMemory();
TCHAR* CustomerID = _T("ZZ997"); _tcsncpy_s(m_view.m_data.m_CustomerID, _tcslen(CustomerID) + 1, CustomerID, _TRUNCATE);
return m_view.OnDataNew(wNotifyCode, wID, hWndCtl, bHandled);
}
Properties
Get/SetBarColor
- color of alternating data rows. Choices are NOBAR
, BLUEBAR
, GRAYBAR
, GREENBAR
, and REDBAR
, but you can add any color you want to the enum.
Get/SetReadOnly
- data can be modified or not.
Get/SetShowBookmarks
- a bookmark is an internal row ID. This ID is limited to the consumer presentation and is independent of any key values in the data.
Get/SetSingleSelect
- one row or multiple rows can be selected.
Under the covers
WTLVirtualList
uses a handler for the LVN_GETDISPINFO
notification to synchronize on-screen data display with fetches of data from the data source and a conversion function (OledbToString
) to format the data for display in the list view. Initial load and scrolling are common triggers for the data fetch.
LRESULT OnLVGetDispInfo(int, LPNMHDR pNMHDR, BOOL&)
{
if (pNMHDR->hwndFrom != m_hWnd) return 0;
if (!IsValidRow()) return SetRowCount();
LVITEM* pItem = &((NMLVDISPINFO*)pNMHDR)->item;
if (pItem->mask & LVIF_TEXT)
{
if (pItem->iSubItem == 0) {
ULONG row = SetActiveRow(pItem->iItem);
_ltot_s(row, pItem->pszText, MAXOLEDBNUM, 10);
}
else OledbToString(m_prgBindings[pItem->iSubItem], pItem->pszText); }
return 0;
}
A handler for NM_CUSTOMDRAW
paints alternate row colors and could be extended to support other visual trinkets. Also, there are handlers for mouse clicks, edit control, and scroll bars to provide support for those functions.
About the samples
The dialog application uses the titles table from the Pubs database while the view application uses customers from Northwind. You will either need access to a database server with these databases to use the samples or generate a consumer class for your specific table and add it to the project. You may also need to modify the connection string in the consumer classes to point to your database. They are currently set to localhost with Integrated Security.