Re: CListCtrl, hide and edit

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



Looks like n**2 bubble sort. Works OK for small n, but for large n, it is a killer. I
tend to just use qsort because it is n*log(n)

I once had an app which required sorting a doubly-linked list. The problem was that old
data files were unsorted. So what I did was for any version of the file < k (the version
k was the one that now required the list be maintained in ascending order, for realtime
performance), I would run across the list once; if it was in order, I left it alone.

If it was not in order, I allocated a vector of count-of-list-elements pointers, put a
pointer to every list element in it, qsorted the array, then ran through the array,
linking up the elements in sorted order. This whole operation took under 5 seconds on an
80286 (read: small memory). The problem was that for very large arrays, we discovered in
beta testing, when I did the malloc(n * sizeof(void *)), I got back NULL because there
wasn't enough space to allocate the side vector. In that case, I popped up a status
display saying "Updating older format file to new format, please be patient, this may take
several minutes" and proceeded to do a bubble sort, which could take up to three minutes.
Of course, once we wrote the file back out in the new format, we knew it was in order and
didn't have to go through this again.

But it really pointed out how n**2 and n*log2(n) differ in performance.
joe

On Mon, 5 May 2008 13:03:38 -0700, "Tom Serface" <tom.nospam@xxxxxxxxxxxxx> wrote:

I typically sort the items in my memory list (the one the list control is
calling on to get it's value line by line). Of course the memory list can
be just about anything, but for me it's typically a vector of CObList of
objects so sorting is usually based off of one of the items in the object.
For example, I typically have a list of items that I just call a routine on
like:

bool CDialogWithList::CompareAndSwapString1(int pos, bool bAscending)
{
CMyObjectInfo *temp;
int posFirst = pos;
int posNext = pos + 1;

if(!bAscending) {
if (((CMyObjectInfo *)GetAt(posFirst))->m_csString1 <
((CMyObjectInfo *)GetAt(posNext))->m_csString1) {
temp = (CMyObjectInfo *)GetAt(posFirst);
SetAt(posFirst, GetAt(posNext));
SetAt(posNext, temp);
return TRUE;
}
}
else if (((CMyObjectInfo *)GetAt(posFirst))->m_csString1 >
((CMyObjectInfo *)GetAt(posNext))->m_csString1) {
temp = (CMyObjectInfo *)GetAt(posFirst);
SetAt(posFirst, GetAt(posNext));
SetAt(posNext, temp);
return TRUE;
}
return FALSE;
}

bool CDataFileArray::CompareAndSwapDate(int pos, bool bAscending)
{
CMyObjectInfo *temp;
int posFirst = pos;
int posNext = pos + 1;
if(!bAscending) {
if (((CMyObjectInfo *)GetAt(posFirst))->m_cDate <
((CMyObjectInfo *)GetAt(posNext))->m_cDate) {
temp = (CMyObjectInfo *)GetAt(posFirst);
SetAt(posFirst, GetAt(posNext));
SetAt(posNext, temp);
return TRUE;
}
}
else if (((CMyObjectInfo *)GetAt(posFirst))->m_cDate >
((CMyObjectInfo *)GetAt(posNext))->m_cDate) {
temp = (CMyObjectInfo *)GetAt(posFirst);
SetAt(posFirst, GetAt(posNext));
SetAt(posNext, temp);
return TRUE;
}
return FALSE;
}

Then I call a routine to Sort the object list like:

void CMyDialogWithList::Sort(MY_DATA_SORT_ITEMS nSort, bool bAscending)
{
bool bNotDone = TRUE;
int pos = 0;

while (bNotDone) {
bNotDone = FALSE;
switch(nSort) {
case MY_DATA_SORT_NONE:
break;
case MY_DATA_SORT_STRING1:
for(pos = 0;pos < GetUpperBound();pos++)
bNotDone |= CompareAndSwapString1(pos, bAscending);
break;
case MY_DATA_SORT_STRING2:
for(pos = 0;pos < GetUpperBound();pos++)
bNotDone |= CompareAndSwapString2(pos, bAscending);
break;
case MY_DATA_SORT_DATE:
for(pos = 0;pos < GetUpperBound();pos++)
bNotDone |= CompareAndSwapDate(pos, bAscending);
break;
default:
break;
};
}
}

So I don't use the sort mechanism in the list control at all. When the
column wants to sort I just sort the list then refresh the current screen
and only the items on the screen are drawn. I also move it back to the top
of the list when someone sorts one of the columns. I think is sort of
expected behavior. This is may not be the most efficient method for doing
sorting, but it works well and keeps the object list in an order that I can
write out and read back in the same order as the user last sorted.

Also, you can edit sub-items, but you have create your own edit control or
trick it into think it is colums 0. For example:

http://www.codeguru.com/cpp/controls/listview/editingitemsandsubitem/article.php/c4175/

It's not that difficult once you get it implemented.

Tom

"Joseph M. Newcomer" <newcomer@xxxxxxxxxxxx> wrote in message
news:cllu14ti1a6i5oebn448d47l9rpbga6gfs@xxxxxxxxxx
See below..

program displays the first item in each location. I can use the iItem
number
instead to solve that and it looks correct. Sorting gives an ASSERT now
but
that depends on lParam too so it's not surprising. However, how do I solve
that because I can't get at the iItem number in the compare function.
****
Tom Serface is our virtual-CListCtrl guru, perhaps he can answer this.
I've not used
virtual controls because I typically have a small number of items to
store, and there are
only a few cases where I *should* have used one, but because it was not a
"product
deliverable" but a personal hobby project, I didn't bother.
****

Also, how do I deal with the number of items in the list control? I could
imagine I just set the size of the list to the total number of items I
should be displaying. It should be fast to do that - the control just
allocates or deallocates memory. Is that correct?
****
For a virtual control, there is no allocation at all, which is why you get
the
performance.
***

Lastly, is it possible to edit a list control subitem in place? If not,
what
is the purpose of EditLabel()? Oh wait. I set Edit Labels. Now I can get
an
in place edit of the first column. How can I do the other columns?
****
Due to fundamental failures of design, a CListCtrl only allows the editing
of the 0th
elment, making it nearly useless for anything that has sophisiticated
constraints (for
example, I'd like the 0th element to be the index, but now I have to get
into manipulating
the column order to make the one-and-only-editable-field be the logical
column 0 while
displaying some other column in the leftmost position, a real pain). I
think there are
some articles in www.codeproject.com on creating a CListCtrl subclass in
which any column
can be edited, and I would consider looking there first.
joe
****
Joseph M. Newcomer [MVP]
email: newcomer@xxxxxxxxxxxx
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
.



Relevant Pages

  • Re: CListCtrl, hide and edit
    ... I typically sort the items in my memory list (the one the list control is calling on to get it's value line by line). ... bool CDialogWithList::CompareAndSwapString1(int pos, bool bAscending) ... CMyObjectInfo *temp; ...
    (microsoft.public.vc.mfc)
  • Re: CListCtrl, hide and edit
    ... in that they do not preserve the order items that have identical sort keys. ... it sounds more like you want a custom grid control than a custom ... bool CDialogWithList::CompareAndSwapString1(int pos, bool bAscending) ... CMyObjectInfo *temp; ...
    (microsoft.public.vc.mfc)
  • Re: CListCtrl, hide and edit
    ... display a boolean value and also to allow that value to be editted. ... control next to a list control, ... bool CDialogWithList::CompareAndSwapString1(int pos, bool bAscending) ... CMyObjectInfo *temp; ...
    (microsoft.public.vc.mfc)
  • Re: CListCtrl, hide and edit
    ... bool CDialogWithList::CompareAndSwapString1(int pos, bool bAscending) ... CMyObjectInfo *temp; ... bool bNotDone = TRUE; ... So I don't use the sort mechanism in the list control at all. ...
    (microsoft.public.vc.mfc)
  • Re: CListCtrl, hide and edit
    ... I do not believe qsort is a stable sort; where I care about order under equality, I will, ... it sounds more like you want a custom grid control than a custom ... bool CDialogWithList::CompareAndSwapString1(int pos, bool bAscending) ... CMyObjectInfo *temp; ...
    (microsoft.public.vc.mfc)