www.pudn.com > VCListCtrl.rar > ListCtrlDemoDlg.cpp
// ListCtrlDemoDlg.cpp : implementation file
//
// Written by matt weagle (matt_weagle@hotmail.com)
// Copyright (c) 2000.
//
//
// This code may be used in compiled form in any way you desire. This
// file may be redistributed unmodified by any means PROVIDING it is
// not sold for profit without the authors written consent, and
// providing that this notice and the authors name is included. If
// the source code in this file is used in any commercial application
// then a simple email would be nice.
//
// This file is provided "as is" with no expressed or implied warranty.
// The author accepts no liability if it causes any damage whatsoever.
// Consider yourself lucky if it works, unlucky if it doesn't.
//
// Thanks to Chris Maunder (chris@codeproject.com) for the
// foregoing disclaimer.
//
// Please use and enjoy. Please let me know of any bugs/mods/improvements
// that you have found/implemented and I will fix/incorporate them into this
// file.
//
#include "stdafx.h"
#include "ListCtrlDemo.h"
#include "ListCtrlDemoDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#include "Hyperlink.h"
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
CHyperLink m_cEmail;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
virtual BOOL OnInitDialog();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
DDX_Control(pDX, IDC_EMAIL, m_cEmail);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CListCtrlDemoDlg dialog
CListCtrlDemoDlg::CListCtrlDemoDlg(CWnd* pParent /*=NULL*/)
: CDialog(CListCtrlDemoDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CListCtrlDemoDlg)
m_nItems = 100;
m_nSelectItem = 0;
m_bImage = FALSE;
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CListCtrlDemoDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CListCtrlDemoDlg)
DDX_Control(pDX, IDC_LOG, m_Log);
DDX_Control(pDX, IDC_LIST_CTRL, m_cListCtrl);
DDX_Control(pDX, IDC_LIST_CTRL_MODE, m_cTabListMode);
DDX_Text(pDX, IDC_LIST_CTRL_NUMITEMS, m_nItems);
DDV_MinMaxInt(pDX, m_nItems, 0, 32257);
DDX_Text(pDX, IDC_LIST_CTRL_SELECTITEM, m_nSelectItem);
DDV_MinMaxInt(pDX, m_nSelectItem, 0, 32567);
DDX_Check(pDX, IDC_BK_IMAGE, m_bImage);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CListCtrlDemoDlg, CDialog)
//{{AFX_MSG_MAP(CListCtrlDemoDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_NOTIFY(TCN_SELCHANGE, IDC_LIST_CTRL_MODE, OnSelchangeListCtrlMode)
ON_BN_CLICKED(IDC_UPDATE_ITEM_COUNT, OnUpdateItemCount)
ON_BN_CLICKED(IDC_STYLES_EX, OnStylesEx)
ON_BN_CLICKED(IDC_STYLES, OnStyles)
ON_BN_CLICKED(IDC_GET_SELECTED, OnGetSelected)
ON_BN_CLICKED(IDC_ITEM_SELECT, OnItemSelect)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_CTRL, OnItemchangedListCtrl)
ON_NOTIFY(NM_CLICK, IDC_LIST_CTRL, OnClickListCtrl)
ON_NOTIFY(NM_RCLICK, IDC_LIST_CTRL, OnRclickListCtrl)
ON_BN_CLICKED(IDC_CLEAR_LOG, OnClearLog)
ON_BN_CLICKED(IDC_BK_IMAGE, OnBkImage)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CListCtrlDemoDlg message handlers
BOOL CListCtrlDemoDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// Initial extended style for the list control on this dialog
DWORD dwStyle = m_cListCtrl.GetExtendedStyle();
dwStyle |= LVS_EX_FULLROWSELECT;
m_cListCtrl.SetExtendedStyle(dwStyle);
// initialize the standard and custom hot cursors
m_hCustomHotCursor= AfxGetApp()->LoadCursor(IDC_HOTCURSOR);
m_hHotCursor= m_cListCtrl.GetHotCursor();
m_bHotCursor = FALSE;
// Setup the tab header
InitTabCtrl();
// Setup the column headings
InitListCtrlCols();
// Create the image list that is attached to the list control
InitImageList();
// Insert the default dummy items
InsertItems();
return TRUE; // return TRUE unless you set the focus to a control
}
void CListCtrlDemoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CListCtrlDemoDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CListCtrlDemoDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
/////////////////////////////////////////////////////////////////////////////
/*
InitImageList
Create the image list that is associated with the list control. Then
attach the list of images to the control so that we can add items with
images.
Params
None
Returns
BOOL Image list created and attached?
*/
/////////////////////////////////////////////////////////////////////////////
BOOL CListCtrlDemoDlg::InitImageList()
{
// Create 256 color image lists
HIMAGELIST hList = ImageList_Create(32,32, ILC_COLOR8 |ILC_MASK , 8, 1);
m_cImageListNormal.Attach(hList);
hList = ImageList_Create(16, 16, ILC_COLOR8 | ILC_MASK, 8, 1);
m_cImageListSmall.Attach(hList);
// Load the large icons
CBitmap cBmp;
cBmp.LoadBitmap(IDB_IMAGES_NORMAL);
m_cImageListNormal.Add(&cBmp, RGB(255,0, 255));
cBmp.DeleteObject();
// Load the small icons
cBmp.LoadBitmap(IDB_IMAGES_SMALL);
m_cImageListSmall.Add(&cBmp, RGB(255,0, 255));
// Attach them
m_cListCtrl.SetImageList(&m_cImageListNormal, LVSIL_NORMAL);
m_cListCtrl.SetImageList(&m_cImageListSmall, LVSIL_SMALL);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
/*
InitTabCtrl
Setup the tab control with the different modes for the list control.
Params
None
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::InitTabCtrl()
{
m_cTabListMode.InsertItem(0, _T("Icon"));
m_cTabListMode.InsertItem(1, _T("Small Icon"));
m_cTabListMode.InsertItem(2, _T("List"));
m_cTabListMode.InsertItem(3, _T("Details"));
}
/////////////////////////////////////////////////////////////////////////////
/*
OnSelchangeListCtrlMode
Whent the user changes the mode of the list control, we need to update
the list control styles and then insert the new items.
Params
(standard)
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::OnSelchangeListCtrlMode(NMHDR* pNMHDR, LRESULT* pResult)
{
// Get the current data and don't redraw while we decide what to do.
UpdateData(TRUE);
m_cListCtrl.SetRedraw(FALSE);
// Remove whatever style is there currently
m_cListCtrl.ModifyStyle(LVS_ICON | LVS_LIST | LVS_REPORT | LVS_SMALLICON ,0);
// Switch the tab mode
switch (m_cTabListMode.GetCurSel())
{
case 0: // Icon mode
m_cListCtrl.ModifyStyle(0, LVS_ICON);
break;
case 1: // Small icons
m_cListCtrl.ModifyStyle(0, LVS_SMALLICON);
break;
case 2: // List mode
m_cListCtrl.ModifyStyle(0, LVS_LIST);
break;
case 3: // Details mode
m_cListCtrl.ModifyStyle(0, LVS_REPORT);
break;
}
// Fill the list control
InsertItems();
m_cListCtrl.SetRedraw(TRUE);
*pResult = 0;
}
/////////////////////////////////////////////////////////////////////////////
/*
InsertItems
Insert the items into the list control.
Params
None
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::InsertItems()
{
// Delete the current contents
m_cListCtrl.DeleteAllItems();
// Use the LV_ITEM structure to insert the items
LVITEM lvi;
CString strItem;
for (int i = 0; i < m_nItems; i++)
{
// Insert the first item
lvi.mask = LVIF_IMAGE | LVIF_TEXT;
strItem.Format(_T("Item %i"), i);
lvi.iItem = i;
lvi.iSubItem = 0;
lvi.pszText = (LPTSTR)(LPCTSTR)(strItem);
lvi.iImage = i%8; // There are 8 images in the image list
m_cListCtrl.InsertItem(&lvi);
// Set subitem 1
strItem.Format(_T("%d"), 10*i);
lvi.iSubItem =1;
lvi.pszText = (LPTSTR)(LPCTSTR)(strItem);
m_cListCtrl.SetItem(&lvi);
// Set subitem 2
strItem.Format(_T("%s"), COleDateTime::GetCurrentTime().Format(_T("Created: %I:%M:%S %p, %m/%d/%Y")));
lvi.iSubItem =2;
lvi.pszText = (LPTSTR)(LPCTSTR)(strItem);
m_cListCtrl.SetItem(&lvi);
}
}
/////////////////////////////////////////////////////////////////////////////
/*
InitListCtrlCols
This is called when we first create the list control as well as part of the
RecreateListControl(...) call. The reason is that when we destroy
and then create the list control in response to changing list control
styles we lose the column information.
Params
None
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::InitListCtrlCols()
{
// Insert some columns
CRect rect;
m_cListCtrl.GetClientRect(&rect);
int nColInterval = rect.Width()/5;
m_cListCtrl.InsertColumn(0, _T("Item Name"), LVCFMT_LEFT, nColInterval*3);
m_cListCtrl.InsertColumn(1, _T("Value"), LVCFMT_LEFT, nColInterval);
m_cListCtrl.InsertColumn(2, _T("Time"), LVCFMT_LEFT, rect.Width()-4*nColInterval);
}
/////////////////////////////////////////////////////////////////////////////
/*
OnUpdateItemCount
When the user presses the refresh button, we simply redirect control
to the Tab handler.
Params
None
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::OnUpdateItemCount()
{
// TODO: Add your control notification handler code here
NMHDR nmhdr;
LRESULT lResult;
OnSelchangeListCtrlMode(&nmhdr, &lResult);
}
/////////////////////////////////////////////////////////////////////////////
/*
OnStylesEx
Handler for the Extended Styles button. We show the dialog from which
the user can view and change the extended styles available to the list
control.
Params
None
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::OnStylesEx()
{
CListCtrlStylesExDlg dlg(&m_cListCtrl);
dlg.SetUseHotCursor(m_bHotCursor);
if (dlg.DoModal() != IDOK)
return;
// Just recreate the control with the new styles, since some styles can't be
// dynamically reset
RecreateListControl(m_cListCtrl.GetStyle(), dlg.GetStyles());
m_bHotCursor = dlg.GetUseHotCursor();
if (m_bHotCursor)
m_cListCtrl.SetHotCursor(m_hCustomHotCursor);
else
m_cListCtrl.SetHotCursor(m_hHotCursor);
}
/////////////////////////////////////////////////////////////////////////////
/*
OnStyles
Handler for the Styles button. We show the dialog from which
the user can view and change the styles available to the list
control.
Params
None
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::OnStyles()
{
// TODO: Add your control notification handler code here
CListCtrlStylesDlg dlg(&m_cListCtrl);
if (dlg.DoModal() != IDOK)
return;
// Just recreate the control with the new styles, since some styles can't be
// dynamically reset
RecreateListControl(dlg.GetStyles(), m_cListCtrl.GetExtendedStyle());
}
/////////////////////////////////////////////////////////////////////////////
/*
OnGetSelected
Handler for the "Get Selected" button. We step through the list
control using the GetFirstSelectedItemPosition call. As we loop through
and find slected items, we create a string which is eventually dumped
to the log edit control.
This could also be done using a loop such as
int n = GetNextItem(-1, LVNI_SELECTED);
while (n >= 0)
{
// Do somthing with item n
n = GetNextItem(n, LVNI_SELECTED);
}
Params
None
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::OnGetSelected()
{
// Get the selected items in the control
POSITION p = m_cListCtrl.GetFirstSelectedItemPosition();
CString msg = _T("");
while (p)
{
int nSelected = m_cListCtrl.GetNextSelectedItem(p);
if (msg.IsEmpty())
msg = _T("The following items are selected: ");
CString str;
str.Format(_T("%s"), m_cListCtrl.GetItemText(nSelected, 0));
if (p)
str += _T(", ");
msg += str;
}
if (msg.IsEmpty())
msg = _T("There are no selected items");
m_Log.AppendString(msg);
}
/////////////////////////////////////////////////////////////////////////////
/*
RecreateListControl
Some CListCtrl styles cannot be dynamically set once the window has been
created. For instance, LVS_NOLABELWRAP, LVS_NOCOLUMNHEADER, and
LVS_NOSORTHEADER all require control recreation. Rather than check for
individual style flags, we just recreate the control whenever the user
changes the list control states.
Params
dwStyles ListControl styles to use in CListCtrl::Create()
dwStylesEx Extended styles to apply to created CListCtrl
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::RecreateListControl(const DWORD &dwStyles, const DWORD &dwStylesEx)
{
CRect rect;
m_cListCtrl.GetWindowRect(&rect);
ScreenToClient(&rect);
m_cListCtrl.DestroyWindow();
m_cListCtrl.Create(dwStyles, rect, this, IDC_LIST_CTRL);
// CListCtrl::SetExtendedStyle works differently for LVS_EX_XXX styles than
// CWnd::ModifyStyleEx works for CWnd extended styles. It sends a LVM_SETEXTENDEDLISTVIEWSTYLE
// message to the underlying CListCtrl, whereas ModifyStyleEx resolves to _AfxModifyStyle,
// which turns into ::SetWindowLong(GWL_EXSTYLE). These calls don't seem to give the
// same results. For extended styles, always use CListCtrl::SetExtendedStyle or
// ListView_SetExtendedListViewStyle
m_cListCtrl.SetExtendedStyle( dwStylesEx);
// For standard CWnd extended styles, you can use this:
m_cListCtrl.ModifyStyleEx(0, WS_EX_CLIENTEDGE);
// Re attach the image lists
m_cListCtrl.SetImageList(&m_cImageListNormal, LVSIL_NORMAL);
m_cListCtrl.SetImageList(&m_cImageListSmall, LVSIL_SMALL);
// Re create the columns for report mode
InitListCtrlCols();
// Insert the items again
InsertItems(); // repopulate with a new item group
// Show the image if needed
EnableBkImage(m_bImage);
}
/////////////////////////////////////////////////////////////////////////////
/*
OnItemSelect
When the user enters an index that they would like to select, first
check the the index is in bounds. If so, set the state of the item
and ensure that the item is visible in the list.
Params
None
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::OnItemSelect()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE);
// Select this item in the list control
int nCount = m_cListCtrl.GetItemCount();
if (m_nSelectItem >= nCount)
{
AfxMessageBox(_T("You entered an out of range index."));
m_nSelectItem = 0;
}
else
{
m_cListCtrl.SetItemState(m_nSelectItem, LVIS_SELECTED, LVIS_SELECTED | LVIS_FOCUSED);
m_cListCtrl.EnsureVisible(m_nSelectItem, FALSE);
}
UpdateData(FALSE);
}
/////////////////////////////////////////////////////////////////////////////
/*
OnItemchangedListCtrl
Handler for the LVN_ITEMCHANGED message which is sent in response
to the user changing some item in the list control
Params
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::OnItemchangedListCtrl(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
CString str;
str.Format(_T("OnItemchangedListCtrl. Item index: %d"), pNMListView->iItem);
m_Log.AppendString(str);
*pResult = 0;
}
/////////////////////////////////////////////////////////////////////////////
/*
OnItemchangedListCtrl
Handler for the NM_CLICK message which is sent in response
to the user changing left-clicking somewhere in the control
Params
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::OnClickListCtrl(NMHDR* pNMHDR, LRESULT* pResult)
{
CPoint point;
::GetCursorPos(&point);
CString str;
str.Format(_T("OnClickListCtrl. Cursor position is x: %d, y: %d"), point.x, point.y);
m_Log.AppendString(str);
*pResult = 0;
}
/////////////////////////////////////////////////////////////////////////////
/*
OnItemchangedListCtrl
Handler for the NM_RCLICK message which is sent in response
to the user right clicking somewhere in the control. This might
be a good place to show a context menu.
Params
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::OnRclickListCtrl(NMHDR* pNMHDR, LRESULT* pResult)
{
m_Log.AppendString(_T("CListCtrlDemoDlg::OnRclickListCtrl"));
CPoint ptCursor;
GetCursorPos(&ptCursor);
CString str;
str.Format(_T("\tMouse position: x=%d, y=%d"), ptCursor.x, ptCursor.y);
m_Log.AppendString(str);
*pResult = 0;
}
/////////////////////////////////////////////////////////////////////////////
/*
OnItemchangedListCtrl
Handler for the NM_RCLICK message which is sent in response
to the user right clicking somewhere in the control. This might
be a good place to show a context menu.
Params
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::OnClearLog()
{
// TODO: Add your control notification handler code here
m_Log.SetWindowText(_T(""));
}
/////////////////////////////////////////////////////////////////////////////
/*
OnInitDialog
Setup the email adress
Params
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
BOOL CAboutDlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_cEmail.SetURL(_T("mailto:matt_weagle@hotmail.com"));
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
/////////////////////////////////////////////////////////////////////////////
/*
OnBkImage
Toggle the state of the background image
Params
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::OnBkImage()
{
// TODO: Add your control notification handler code here
m_bImage = !m_bImage;
EnableBkImage(m_bImage);
}
/////////////////////////////////////////////////////////////////////////////
/*
EnableBkImage
Helper function to show/hide the background image. It's factored
out of the EnableBkImage call because the control needs to be
recreated when the user changes the Extended Styles
Params
BOOL show/hide the image
Returns
void
*/
/////////////////////////////////////////////////////////////////////////////
void CListCtrlDemoDlg::EnableBkImage(BOOL bEnable)
{
if (bEnable)
{
/*
There are two ways to include a background image:
(1) Specify a valid filepath and load the bitmap handle from there
(2) Specify a valid URL using the res:protocol (preferred).
(2) Is preferable because you don't need to include a separate file
with your application. You can embed the BMP in the resource fork
and use the RES: protocol to have the ListControl load it. See
http://www.microsoft.com/mind/0199/cutting/cutting0199.asp for more
information about the RES: syntax. This idea was suggested by Nick Hodapp
(http://www.codetools.com/script/Articles/list_articles.asp?userid=162)
Both methods are included for completeness, but the sample
application uses the embedded BMP. Note that specifying a HBITMAP
in the struct is not currently supported.
*/
// Load the resource and apply it to the background
/* TCHAR szBuffer[_MAX_PATH];
VERIFY(::GetModuleFileName(AfxGetInstanceHandle(), szBuffer, _MAX_PATH));
CString sPath;
sPath.Format(_T("res://%s/#2/#142"),szBuffer);
LVBKIMAGE bki;
bki.ulFlags = LVBKIF_STYLE_TILE | LVBKIF_SOURCE_URL ;
bki.pszImage = sPath.GetBuffer(sPath.GetLength());
bki.cchImageMax = sPath.GetLength();
VERIFY(m_cListCtrl.SetBkImage( &bki));
*/
/*
Construct the path to the BMP. Although the CListCtrl::SetBkImage docs
indicate that you can use an HBITMAP, the latest docs on the LVBKIMAGE
underlying struct indicates that the LVBKIMAGE.hbm member is not used.
*/
TCHAR szBuffer[_MAX_PATH];
VERIFY(::GetModuleFileName(AfxGetInstanceHandle(), szBuffer, _MAX_PATH));
CString sPath = (CString)szBuffer;
sPath = sPath.Left(sPath.ReverseFind('\\') + 1);
sPath += "bk.bmp";
BOOL a = m_cListCtrl.SetBkImage( sPath.GetBuffer(sPath.GetLength()), TRUE);
sPath.ReleaseBuffer();
// Whichever one you choose, log the path used
CString str;
str.Format(_T("Set background image: %s"), sPath.GetBuffer(sPath.GetLength()));
m_Log.AppendString(str);
sPath.ReleaseBuffer();
}
else
{
m_cListCtrl.SetBkImage( HBITMAP(0));
m_Log.AppendString(_T("Cleared background image."));
}
}