V. interesting article, thanks. The sample is CDialog-specific though; has anyone tried creating a self-contained "CVirtualListControl"-class? BTW For VS.NET 2003 you need to comment out the line: const int LVS_EX_LABELTIP = 0x00004000; ...in CDlgTest::OnInitDialog() -- it already exists as a define.
ReplyIf You fill the pItem->pszText by lstrcpy You get an error. This is becouse the system allocates memory for the text, and if You copy a long string ( in my case 800 char long ), the buffer overruns. Instead of writing 'lstrcpy(pItem->pszText, m_strText)' write 'pItem->pszText = m_strText.GetBuffer( 0 )'
i solved problom!! thank you!!!
Reply...not to mention that the originally allocated memory becomes orphaned and is now a leak.
ReplyHe had it right though. I'm not sure who frees this memory, but I believe the application does on exit? In that case you have to be careful with your example or you'll free it twice.
ReplyAfter searching through a few MFC texts and searching online. You were the only good resource I could find to explain virtual list controls. You did a good job at keeping things simple and I thank you very much.
ReplyOriginally posted by: Alan Sim
I have used the SetCallBackMask(hWnd, LVIS_SELECTED|LVIS_STATEIMAGEMASK|LVIS_OVERLAYMASK) method to have the checkboxes in the virtual list ctrl, but the checkboxes does not seem to response (change state) to mouse click. It also does not send LVN_ITEMCHANGED. Any advise will be greatly appreciated.
ReplyOriginally posted by: PoperoH
database product:
by default i opened the cedatabase the sort property on the description. This part is working just perfect, but now i have a problem: i need to show on the listview just the product of a specified classification sorted by description. how to do it??
follow the code:
case LVN_GETDISPINFO:
// function that read the cedatabase and put the data into a struct called product
if (pLVdi->item.mask & LVIF_IMAGE)
i have a listview with LVS_OWNERDATA and on the LVN_GETDISPINFO i get the record from a cedatabase using the item number of the listview to retrieve the data from the database.
1 - code
2 - description - sorted ascending
3 - classification - sorted ascending
pLVdi = (NMLVDISPINFO *)lParam;
GetItemProduct (pLVdi->item.iItem, &Product);
pLVdi->item.iImage = 0;
if (pLVdi->item.mask & LVIF_PARAM)
pLVdi->item.lParam = 0;
if (pLVdi->item.mask & LVIF_STATE)
pLVdi->item.state = 0;
if (pLVdi->item.mask & LVIF_TEXT) {
switch (pLVdi->item.iSubItem) {
case 0:
wsprintf(auxi, TEXT("%s"), Product.Description);
_tcscpy (pLVdi->item.pszText, auxi);
break;
case 1:
wsprintf(auxi, TEXT("%s"), Product.Classification);
_tcscpy (pLVdi->item.pszText, auxi);
break;
case 2:
wsprintf(auxi, TEXT("%i"), Product.Code);
_tcscpy (pLVdi->item.pszText, auxi);
break;
}
Originally posted by: Keri
I've implemented virtual listctrls in my app, but couldn't figure out the Scroll to letter - thanks for the LVN_ODFINDITEM explanation, and Phil Hartmann's improvement was appreciated too!
ReplyOriginally posted by: VikasKB
Hi, Thanks for the article. But I am facing a different problem. I need to display morethan 10000 images in a ListView. I have created a Database for speeding up the process of rendering each time. But the whole process takes nearly a minute !! How can I speed up the whole process of putting thumbnail in Virtual ListView ?
I am currently using
CImageList::Replace()
CListCtrl::InsertItem(). Any workaround to use Virtual List Ctrl?
Thanks
Vikas
Reply
Originally posted by: Yue Guang Ling
how to set the flag?
in my program,the code of setting value cant be excuted!
help!
Originally posted by: Phil Hartmann
void <classname>::OnOdFindItem(NMHDR* pNMHDR, LRESULT* pResult)
if(fndItem.flags & LVFI_STRING)
// Search from 0 to start.
*pResult = -1; // Default action.
This is how to handle it properly, like how explorer and other programs do it
{
NMLVFINDITEM* pFindInfo = (NMLVFINDITEM*)pNMHDR;
LVFINDINFO fndItem = pFindInfo->lvfi;
{
int nLength = strlen(fndItem.psz);
// Search to end.
for(int i = pFindInfo->iStart; i < <yourArray.Size()>; i++ )
{
if(_strnicmp(fndItem.psz, <yourArray[i]>,nLength) == 0)
{
*pResult = i;
return;
}
}
for( i = 0; i < pFindInfo->iStart; i++ )
{
if(_strnicmp(fndItem.psz, <yourArray[i]>, nLength) == 0)
{
*pResult = i;
return;
}
}
}
}
Originally posted by: Peter Brightman
I think that virtual lists are fine because you don't have
to load all the data into the control and so waste lot's of
memory. With owner draw mode, you'll render the data to screen just when the appropriate lines appear in the visible
part of the control's client area. The only thing we need to do is to add all the entries and give each a handle that is the key to the data. I have done this some years ago with a list control and it worked fine. The key was a record number to a record entry in a DB.
The thing about sorting is that you really have to remove all entries in the control and add them in the order you wish them to appear. Because the entries hold just handles/keys and not values, so the sorting is really a complete removal and new insert of all entries.
I'd like to ask the community if there is any example or if someone can give hints in how to use virtual lists along with data retrieved from a SQL DB. Is it ok to retrieve a record for each fired event of the control by using the primary key? Usually one would want to retrieve a result set with more than one entry but like this, one would only use the event for the first line in the control and ignore the other events, because the first event would retrieve n records that would hold all other entries that have to displayed too in the control. Then the 2nd to the last event just would be the cursor into the result set. I highly appreciate any hints or links regarding this topic.
Peter Brightman
Reply