devendersys
asked on
Using 24bit Bitmap images with CListCtrl's Virtual List
Hi,
I was using a list control to show online data on it. The data comes very fast and i was showing Data as well as image of 24 bit. but it flickers the view since i was custom drawing for each data.
To minimize this flickering, now i am using virtual list of list control for fast retreival of data. it has a tremendous improovment, but there is one problem, it does show the 24bit bitmap on it. it converts it into grey color.
can anybody help me to sort out this problem?
For more information i am using
CListCtrl::OnGetDispInfo(N MHDR* pNMHDR, LRESULT* pResult) [ for fill up the virtual list]
and
CListCtrl::SetItemCount(in t nCount) [ for set the number of rows to display ]
Thanks in advance
devender
I was using a list control to show online data on it. The data comes very fast and i was showing Data as well as image of 24 bit. but it flickers the view since i was custom drawing for each data.
To minimize this flickering, now i am using virtual list of list control for fast retreival of data. it has a tremendous improovment, but there is one problem, it does show the 24bit bitmap on it. it converts it into grey color.
can anybody help me to sort out this problem?
For more information i am using
CListCtrl::OnGetDispInfo(N
and
CListCtrl::SetItemCount(in
Thanks in advance
devender
ASKER
Here is the code
// VirtualListDlg.cpp : implementation file
//
#include "stdafx.h"
#include "VirtualList.h"
#include "VirtualListDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
////////////////////////// ////////// ////////// ////////// ////////// ////////// /
// CVirtualListDlg dialog
CVirtualListDlg::CVirtualL istDlg(CWn d* pParent /*=NULL*/)
: CDialog(CVirtualListDlg::I DD, pParent)
{
//{{AFX_DATA_INIT(CVirtual ListDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_ MAINFRAME) ;
}
void CVirtualListDlg::DoDataExc hange(CDat aExchange* pDX)
{
CDialog::DoDataExchange(pD X);
//{{AFX_DATA_MAP(CVirtualL istDlg)
DDX_Control(pDX, IDC_COMBO_STYLE, m_style);
DDX_Control(pDX, IDC_LIST, m_list);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CVirtual ListDlg, CDialog)
//{{AFX_MSG_MAP(CVirtualLi stDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_A DDTEN, OnButtonAddten)
ON_BN_CLICKED(IDC_BUTTON_C LEAR, OnButtonClear)
ON_NOTIFY(LVN_GETDISPINFO, IDC_LIST, OnGetdispinfoList)
ON_NOTIFY(LVN_ODFINDITEM, IDC_LIST, OnOdfinditemList)
ON_NOTIFY(LVN_ODCACHEHINT, IDC_LIST, OnOdcachehintList)
ON_CBN_SELCHANGE(IDC_COMBO _STYLE, OnSelchangeComboStyle)
ON_NOTIFY(NM_CLICK, IDC_LIST, OnClickList)
ON_NOTIFY(LVN_KEYDOWN, IDC_LIST, OnKeydownList)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
////////////////////////// ////////// ////////// ////////// ////////// ////////// /
// CVirtualListDlg message handlers
BOOL CVirtualListDlg::OnInitDia log()
{
CDialog::OnInitDialog();
// 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
ListView_SetExtendedListVi ewStyle(m_ list.m_hWn d, LVS_EX_FULLROWSELECT|LVS_E X_CHECKBOX ES );
//Create image list
m_imagelist.Create(IDB_BIT MAP, 16, ILC_COLOR24, RGB(255, 255, 255));
m_imagelistLarge.Create(ID B_BITMAP_L ARGE, 32, ILC_COLOR4, RGB(255, 255, 255));
m_list.SetImageList(&m_ima gelist, LVSIL_SMALL);
m_list.SetImageList(&m_ima gelistLarg e, LVSIL_NORMAL);
m_list.InsertColumn(0, _T("Name"), LVCFMT_LEFT, 130);
m_list.InsertColumn(1, _T("Address"), LVCFMT_LEFT, 200);
m_style.SetCurSel(3);
return TRUE; // return TRUE unless you set the focus to a control
}
// 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 CVirtualListDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBK GND, (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 CVirtualListDlg::OnQueryDr agIcon()
{
return (HCURSOR) m_hIcon;
}
void CVirtualListDlg::OnButtonA ddten()
{
//Add 10 elements to the database
for(int i=0; i<10; i++)
m_database.push_back( CSampleData() );
//Resize the list to add the elements to the list
m_list.SetItemCount( m_database.size() );
UpdateCount();
}
void CVirtualListDlg::OnButtonC lear()
{
//Clear database and list.
m_database.clear();
m_list.SetItemCount(0);
UpdateCount();
}
void CVirtualListDlg::UpdateCou nt()
{
CString temp;
temp.Format(_T("%d items."), m_database.size());
GetDlgItem(IDC_STATIC_COUN T)->SetWin dowText(te mp);
}
void CVirtualListDlg::OnSelchan geComboSty le()
{
//Change list view style
DWORD style = 0;
switch( m_style.GetCurSel() )
{
case 0:
style = LVS_ICON;
break;
case 1:
style = LVS_SMALLICON;
break;
case 2:
style = LVS_LIST;
break;
default:
style = LVS_REPORT;
break;
}
//Remove old style, and add new
m_list.ModifyStyle(LVS_TYP EMASK, style);
//Turn on/off check box
if(style == LVS_ICON || style == LVS_SMALLICON)
//Off
ListView_SetExtendedListVi ewStyleEx( m_list.m_h Wnd, LVS_EX_CHECKBOXES, 0);
else
//On
ListView_SetExtendedListVi ewStyleEx( m_list.m_h Wnd, LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES);
}
//This function is called when the list needs data. This is the most
//critical function when working with virtual lists.
void CVirtualListDlg::OnGetdisp infoList(N MHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
//Create a pointer to the item
LV_ITEM* pItem= &(pDispInfo)->item;
//Which item number?
int itemid = pItem->iItem;
//Do the list need text information?
if (pItem->mask & LVIF_TEXT)
{
CString text;
//Which column?
if(pItem->iSubItem == 0)
{
//Text is name
text = m_database[itemid].m_name;
}
else if (pItem->iSubItem == 1)
{
//Text is slogan
text = m_database[itemid].m_sloga n;
}
//Copy the text to the LV_ITEM structure
//Maximum number of characters is in pItem->cchTextMax
lstrcpyn(pItem->pszText, text, pItem->cchTextMax);
}
//Do the list need image information?
if( pItem->mask & LVIF_IMAGE )
{
//Set which image to use
pItem->iImage=m_database[i temid].m_i mage;
//Show check box?
if(IsCheckBoxesVisible())
{
//To enable check box, we have to enable state mask...
pItem->mask |= LVIF_STATE;
pItem->stateMask = LVIS_STATEIMAGEMASK;
if(m_database[itemid].m_ch ecked)
{
//Turn check box on..
pItem->state = INDEXTOSTATEIMAGEMASK(2);
}
else
{
//Turn check box off
pItem->state = INDEXTOSTATEIMAGEMASK(1);
}
}
}
*pResult = 0;
}
//This functions is called when the user "writes" in the list box to find an item.
void CVirtualListDlg::OnOdfindi temList(NM HDR* pNMHDR, LRESULT* pResult)
{
// pNMHDR has information about the item we should find
// In pResult we should save which item that should be selected
NMLVFINDITEM* pFindInfo = (NMLVFINDITEM*)pNMHDR;
/* pFindInfo->iStart is from which item we should search.
We search to bottom, and then restart at top and will stop
at pFindInfo->iStart, unless we find an item that match
*/
// Set the default return value to -1
// That means we didn't find any match.
*pResult = -1;
//Is search NOT based on string?
if( (pFindInfo->lvfi.flags & LVFI_STRING) == 0 )
{
//This will probably never happend...
return;
}
/*
Let's look on a sample list;
Name
Anders
* Anna
Annika
Bob
Emma
Emmanuel
Anna is selected.
If "A" is written, Annika should be selected.
If "AND" is written, Anders should be selected.
If "ANNK" is written, the selection should stay on Anna.
If "E" is written, Emma should be selected.
*/
//This is the string we search for
CString searchstr = pFindInfo->lvfi.psz;
// TRACE(_T("Find: %s\n"), searchstr);
int startPos = pFindInfo->iStart;
//Is startPos outside the list (happens if last item is selected)
if(startPos >= m_list.GetItemCount())
startPos = 0;
int currentPos=startPos;
//Let's search...
do
{
//Do this word begins with all characters in searchstr?
if( _tcsnicmp(m_database[curre ntPos].m_n ame, searchstr, searchstr.GetLength()) == 0)
{
//Select this item and stop search.
*pResult = currentPos;
break;
}
//Go to next item
currentPos++;
//Need to restart at top?
if(currentPos >= m_list.GetItemCount())
currentPos = 0;
//Stop if back to start
}while(currentPos != startPos);
}
//This is called to give you a chance to catch data. Useless in most cases :-)
void CVirtualListDlg::OnOdcache hintList(N MHDR* pNMHDR, LRESULT* pResult)
{
NMLVCACHEHINT* pCacheHint = (NMLVCACHEHINT*)pNMHDR;
/* TRACE( _T("Chache item %d to item %d\n"),
pCacheHint->iFrom,
pCacheHint->iTo );*/
//... cache the data pCacheHint->iFrom to pCacheHint->iTo ...
*pResult = 0;
}
void CVirtualListDlg::ToggleChe ckBox(int item)
{
//Change check box
m_database[item].m_checked = !m_database[item].m_checke d;
//And redraw
m_list.RedrawItems(item, item);
}
//This is called when user clicks on the list.
//If you had check box you have to write code to make them possible to toggle.
void CVirtualListDlg::OnClickLi st(NMHDR* pNMHDR, LRESULT* pResult)
{
NMLISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
LVHITTESTINFO hitinfo;
//Copy click point
hitinfo.pt = pNMListView->ptAction;
//Make the hit test...
int item = m_list.HitTest(&hitinfo);
if(item != -1)
{
//We hit one item... did we hit state image (check box)?
//This test only works if we are in list or report mode.
if( (hitinfo.flags & LVHT_ONITEMSTATEICON) != 0)
{
ToggleCheckBox(item);
}
}
*pResult = 0;
}
//This is called when a key i pressed down
void CVirtualListDlg::OnKeydown List(NMHDR * pNMHDR, LRESULT* pResult)
{
LV_KEYDOWN* pLVKeyDown = (LV_KEYDOWN*)pNMHDR;
//If user press space, toggle flag on selected item
if( pLVKeyDown->wVKey == VK_SPACE )
{
//Check if check boxes are visible
if( IsCheckBoxesVisible() )
{
//Toggle if some item is selected
if(m_list.GetSelectionMark () != -1)
ToggleCheckBox( m_list.GetSelectionMark() );
}
}
*pResult = 0;
}
BOOL CVirtualListDlg::IsCheckBo xesVisible ()
{
DWORD style = m_list.GetStyle();
if( ((style & LVS_TYPEMASK) == LVS_LIST) ||
((style & LVS_TYPEMASK) == LVS_REPORT) )
return TRUE;
return FALSE;
}
// VirtualListDlg.cpp : implementation file
//
#include "stdafx.h"
#include "VirtualList.h"
#include "VirtualListDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//////////////////////////
// CVirtualListDlg dialog
CVirtualListDlg::CVirtualL
: CDialog(CVirtualListDlg::I
{
//{{AFX_DATA_INIT(CVirtual
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_
}
void CVirtualListDlg::DoDataExc
{
CDialog::DoDataExchange(pD
//{{AFX_DATA_MAP(CVirtualL
DDX_Control(pDX, IDC_COMBO_STYLE, m_style);
DDX_Control(pDX, IDC_LIST, m_list);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CVirtual
//{{AFX_MSG_MAP(CVirtualLi
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_A
ON_BN_CLICKED(IDC_BUTTON_C
ON_NOTIFY(LVN_GETDISPINFO,
ON_NOTIFY(LVN_ODFINDITEM, IDC_LIST, OnOdfinditemList)
ON_NOTIFY(LVN_ODCACHEHINT,
ON_CBN_SELCHANGE(IDC_COMBO
ON_NOTIFY(NM_CLICK, IDC_LIST, OnClickList)
ON_NOTIFY(LVN_KEYDOWN, IDC_LIST, OnKeydownList)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//////////////////////////
// CVirtualListDlg message handlers
BOOL CVirtualListDlg::OnInitDia
{
CDialog::OnInitDialog();
// 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
ListView_SetExtendedListVi
//Create image list
m_imagelist.Create(IDB_BIT
m_imagelistLarge.Create(ID
m_list.SetImageList(&m_ima
m_list.SetImageList(&m_ima
m_list.InsertColumn(0, _T("Name"), LVCFMT_LEFT, 130);
m_list.InsertColumn(1, _T("Address"), LVCFMT_LEFT, 200);
m_style.SetCurSel(3);
return TRUE; // return TRUE unless you set the focus to a control
}
// 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 CVirtualListDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBK
// 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 CVirtualListDlg::OnQueryDr
{
return (HCURSOR) m_hIcon;
}
void CVirtualListDlg::OnButtonA
{
//Add 10 elements to the database
for(int i=0; i<10; i++)
m_database.push_back( CSampleData() );
//Resize the list to add the elements to the list
m_list.SetItemCount( m_database.size() );
UpdateCount();
}
void CVirtualListDlg::OnButtonC
{
//Clear database and list.
m_database.clear();
m_list.SetItemCount(0);
UpdateCount();
}
void CVirtualListDlg::UpdateCou
{
CString temp;
temp.Format(_T("%d items."), m_database.size());
GetDlgItem(IDC_STATIC_COUN
}
void CVirtualListDlg::OnSelchan
{
//Change list view style
DWORD style = 0;
switch( m_style.GetCurSel() )
{
case 0:
style = LVS_ICON;
break;
case 1:
style = LVS_SMALLICON;
break;
case 2:
style = LVS_LIST;
break;
default:
style = LVS_REPORT;
break;
}
//Remove old style, and add new
m_list.ModifyStyle(LVS_TYP
//Turn on/off check box
if(style == LVS_ICON || style == LVS_SMALLICON)
//Off
ListView_SetExtendedListVi
else
//On
ListView_SetExtendedListVi
}
//This function is called when the list needs data. This is the most
//critical function when working with virtual lists.
void CVirtualListDlg::OnGetdisp
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
//Create a pointer to the item
LV_ITEM* pItem= &(pDispInfo)->item;
//Which item number?
int itemid = pItem->iItem;
//Do the list need text information?
if (pItem->mask & LVIF_TEXT)
{
CString text;
//Which column?
if(pItem->iSubItem == 0)
{
//Text is name
text = m_database[itemid].m_name;
}
else if (pItem->iSubItem == 1)
{
//Text is slogan
text = m_database[itemid].m_sloga
}
//Copy the text to the LV_ITEM structure
//Maximum number of characters is in pItem->cchTextMax
lstrcpyn(pItem->pszText, text, pItem->cchTextMax);
}
//Do the list need image information?
if( pItem->mask & LVIF_IMAGE )
{
//Set which image to use
pItem->iImage=m_database[i
//Show check box?
if(IsCheckBoxesVisible())
{
//To enable check box, we have to enable state mask...
pItem->mask |= LVIF_STATE;
pItem->stateMask = LVIS_STATEIMAGEMASK;
if(m_database[itemid].m_ch
{
//Turn check box on..
pItem->state = INDEXTOSTATEIMAGEMASK(2);
}
else
{
//Turn check box off
pItem->state = INDEXTOSTATEIMAGEMASK(1);
}
}
}
*pResult = 0;
}
//This functions is called when the user "writes" in the list box to find an item.
void CVirtualListDlg::OnOdfindi
{
// pNMHDR has information about the item we should find
// In pResult we should save which item that should be selected
NMLVFINDITEM* pFindInfo = (NMLVFINDITEM*)pNMHDR;
/* pFindInfo->iStart is from which item we should search.
We search to bottom, and then restart at top and will stop
at pFindInfo->iStart, unless we find an item that match
*/
// Set the default return value to -1
// That means we didn't find any match.
*pResult = -1;
//Is search NOT based on string?
if( (pFindInfo->lvfi.flags & LVFI_STRING) == 0 )
{
//This will probably never happend...
return;
}
/*
Let's look on a sample list;
Name
Anders
* Anna
Annika
Bob
Emma
Emmanuel
Anna is selected.
If "A" is written, Annika should be selected.
If "AND" is written, Anders should be selected.
If "ANNK" is written, the selection should stay on Anna.
If "E" is written, Emma should be selected.
*/
//This is the string we search for
CString searchstr = pFindInfo->lvfi.psz;
// TRACE(_T("Find: %s\n"), searchstr);
int startPos = pFindInfo->iStart;
//Is startPos outside the list (happens if last item is selected)
if(startPos >= m_list.GetItemCount())
startPos = 0;
int currentPos=startPos;
//Let's search...
do
{
//Do this word begins with all characters in searchstr?
if( _tcsnicmp(m_database[curre
{
//Select this item and stop search.
*pResult = currentPos;
break;
}
//Go to next item
currentPos++;
//Need to restart at top?
if(currentPos >= m_list.GetItemCount())
currentPos = 0;
//Stop if back to start
}while(currentPos != startPos);
}
//This is called to give you a chance to catch data. Useless in most cases :-)
void CVirtualListDlg::OnOdcache
{
NMLVCACHEHINT* pCacheHint = (NMLVCACHEHINT*)pNMHDR;
/* TRACE( _T("Chache item %d to item %d\n"),
pCacheHint->iFrom,
pCacheHint->iTo );*/
//... cache the data pCacheHint->iFrom to pCacheHint->iTo ...
*pResult = 0;
}
void CVirtualListDlg::ToggleChe
{
//Change check box
m_database[item].m_checked
//And redraw
m_list.RedrawItems(item, item);
}
//This is called when user clicks on the list.
//If you had check box you have to write code to make them possible to toggle.
void CVirtualListDlg::OnClickLi
{
NMLISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
LVHITTESTINFO hitinfo;
//Copy click point
hitinfo.pt = pNMListView->ptAction;
//Make the hit test...
int item = m_list.HitTest(&hitinfo);
if(item != -1)
{
//We hit one item... did we hit state image (check box)?
//This test only works if we are in list or report mode.
if( (hitinfo.flags & LVHT_ONITEMSTATEICON) != 0)
{
ToggleCheckBox(item);
}
}
*pResult = 0;
}
//This is called when a key i pressed down
void CVirtualListDlg::OnKeydown
{
LV_KEYDOWN* pLVKeyDown = (LV_KEYDOWN*)pNMHDR;
//If user press space, toggle flag on selected item
if( pLVKeyDown->wVKey == VK_SPACE )
{
//Check if check boxes are visible
if( IsCheckBoxesVisible() )
{
//Toggle if some item is selected
if(m_list.GetSelectionMark
ToggleCheckBox( m_list.GetSelectionMark() );
}
}
*pResult = 0;
}
BOOL CVirtualListDlg::IsCheckBo
{
DWORD style = m_list.GetStyle();
if( ((style & LVS_TYPEMASK) == LVS_LIST) ||
((style & LVS_TYPEMASK) == LVS_REPORT) )
return TRUE;
return FALSE;
}
ASKER
Hi Amit,
Is there any luck?
Thanks
devender
Is there any luck?
Thanks
devender
Have you referred this how its implemented ..
http://www.codeproject.com/listctrl/virtuallist.asp
Your code seems to be same as above.. Tried to change above for 24 bit images ?
-MAHESH
http://www.codeproject.com/listctrl/virtuallist.asp
Your code seems to be same as above.. Tried to change above for 24 bit images ?
-MAHESH
ASKER
This code snippet is from the link above, but even it does not work for 24Bit Bitmaps. I am using this code for testing. you can check it for by changing the defult bitmap to 24bit Bitmap, and you can see the difference. the icon will be shown in grey scale.
devender
devender
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
its works great.
Thanks a lot amit.
Thanks
Devender
Thanks a lot amit.
Thanks
Devender
Amit