|
Thanks!I think it helps a lot ^^
|
|
|
|
|
Excellent control! But when I implemented it on my dialog OnToolTipNotify ain´t called anymore.Does anyone have any idea about this??
|
|
|
|
|
Hi,
I find one bug in my program When I use the SortItems function.
my compare function which pass into the SortItems has the following prototype:
int CALLBACK CompareListViewItems(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
When I do debugging, I find the lParam1 and lParam2 passed into the compare function are always set to 0, and never changed.
Who know what is wrong in my code? how I can fix it?
Thanks a lot!
sandy
|
|
|
|
|
This is a problem in the MSDN documentation.lParam1 and lParam2 are not the index of the items but their 32-bit associated value. another problem is even if we set the 32-bit associated value of each item to be the same as the item's index this example will still not work. This is because the items will shift positions after each call to CompareFunction(...) and the 32-bit associated values will no longer represent the item's index. I found this bug when i tried to use the CSortListCtrl in a form view.
Anyway here are some changes you could make to get it working
void CSortListCtrl::Sort( int iColumn, BOOL bAscending )
{
m_iSortColumn = iColumn;
m_bSortAscending = bAscending;
m_ctlHeader.SetSortArrow( m_iSortColumn, m_bSortAscending );
for (int i=0;i < this->GetItemCount();i++)
{
this->SetItemData(i, (DWORD)i);
}
VERIFY( SortItems( CompareFunction, (LPARAM)( this ) ));
}
Also modify CompareFunction
int CALLBACK CSortListCtrl::CompareFunction( LPARAM lParam1, LPARAM lParam2, LPARAM lParamData )
{
CSortListCtrl* pListCtrl = (CSortListCtrl*) lParamData;
CString szText1 = pListCtrl->GetItemText(lParam1, pListCtrl->m_iSortColumn);
CString szText2 = pListCtrl->GetItemText(lParam2, pListCtrl->m_iSortColumn);
LPCTSTR pszText1 = szText1.GetBuffer(szText1.GetLength());
LPCTSTR pszText2 = szText2.GetBuffer(szText2.GetLength());
ASSERT_VALID_STRING( pszText1 );
ASSERT_VALID_STRING( pszText2 );
if( IsNumber( pszText1 ) )
return pListCtrl->m_bSortAscending ? NumberCompare( pszText1, pszText2 ) : NumberCompare( pszText2, pszText1 );
else if( IsDate( pszText1 ) )
return pListCtrl->m_bSortAscending ? DateCompare( pszText1, pszText2 ) : DateCompare( pszText2, pszText1 );
else
return pListCtrl->m_bSortAscending ? lstrcmp( pszText1, pszText2 ) : lstrcmp( pszText2, pszText1 );
}
|
|
|
|
|
You have to change the IsNumber function to make sure that floating point variables are not treated as text.
Otherwise, it looks good.
A reasonable man adapts himself to the world. An unreasonable one persists, trying to adapt the world to himself. That is why all the progress in the world depends on the unreasonable men.
|
|
|
|
|
Hi,
first i'd like to say "very nice class!".
but now my question:
i've attatched a image lsit to my list by SetImageList( ... );
now i wand to add a list item by calling AddItem:
list->AddItem( _T( "text" ),
_T( "123"),
_T(symbolNumber) );
the problem: only fhe first image of the image list is shown in the list.
How can i add the ability to select which image to be displayed?!?
thx nico ...
|
|
|
|
|
I am using this sorted list control to display a list of files this list is update when any changes are found, I currently remove all data in the list the repopulate the list, but the data is not sorted until the user clicks on the sort button again
Can you force a sort
|
|
|
|
|
I have added this function
void CSortListCtrl::Sort()
{
//m_iSortColumn = iColumn;
//m_bSortAscending = bAscending;
// show the appropriate arrow in the header control.
if(m_iSortColumn!=-1)
{
m_ctlHeader.SetSortArrow( m_iSortColumn, m_bSortAscending );
VERIFY( SortItems( CompareFunction, reinterpret_cast<dword>( this ) ) );
}
}
and call it here when updating
void CScanJobListView::OnUpdateList()
{
// TODO: Add your control notification handler code here
CScanJobListDoc *ptrDoc = GetDocument();
CJobObj JobObject;
ptrDoc->m_JobList.UpdateList();
m_cItemList.DeleteAllItems();
for(int Idx=0;Idx<ptrdoc->m_JobList.GetItemCount();Idx++)
{
if(ptrDoc->m_JobList.GetItem(Idx,JobObject))
{
AddItem(JobObject.GetJobName(),JobObject.GetSection(),JobObject.GetFileTimeStr());
}
}
m_cItemList.Sort();
}
it works for me.....................
|
|
|
|
|
To understand your code, I changed your code like below.
I changed 'AddItem' to 'InsertItem' and 'SetItemText'.
But it generates error when it process 'GetTextArray' in SetItemText();
The return value of GetTextArray() is NULL.
Do you know what is a problem?
-----------------------------------------------
BOOL CSortListCtrlTestDlg::OnInitDialog()
{
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
(void)m_ctlList.SetExtendedStyle( LVS_EX_FULLROWSELECT );
m_ctlList.SetHeadings( _T("Name,120;Date of Birth,90;Score,50") );
m_ctlList.LoadColumnInfo();
//(void)m_ctlList.AddItem( _T("Mark Jackson"), _T("09/08/1974"), _T("100") );
int nIndex = m_ctlList.InsertItem(0,_T("Mark Jackson"));
m_ctlList.SetItemText(nIndex,1,_T("09/08/1974"));
m_ctlList.SetItemText(nIndex,2,_T("100") );
return TRUE; // return TRUE unless you set the focus to a control
}
|
|
|
|
|
I've solved the problem (I hope).
In the CSortListCtrl add the memberfunction:
int CSortListCtrl::InsertItem(int nItem, LPCTSTR lpszItem)
{
const int iIndex = CListCtrl::InsertItem( nItem, lpszItem );
LPTSTR* arrpsz = new LPTSTR[ m_iNumColumns ];
arrpsz[ 0 ] = new TCHAR[ lstrlen( lpszItem ) + 1 ];
(void)lstrcpy( arrpsz[ 0 ], lpszItem );
va_list list;
va_start( list, lpszItem );
for( int iColumn = 1; iColumn < m_iNumColumns; iColumn++ )
{
//lpszItem = va_arg( list, LPCTSTR );
ASSERT_VALID_STRING( lpszItem );
VERIFY( CListCtrl::SetItem( iIndex, iColumn, LVIF_TEXT, lpszItem, 0, 0, 0, 0 ) );
arrpsz[ iColumn ] = new TCHAR[ lstrlen( lpszItem ) + 1 ];
(void)lstrcpy( arrpsz[ iColumn ], lpszItem );
}
va_end( list );
VERIFY( SetTextArray( iIndex, arrpsz ) );
return iIndex;
}
This is only the solution for calling InsertItem with the parameters int nItem and LPCTSTR lpszItem.
Hope this works for you.
If you have suggestions, let me know.
Greetz joEp mEloEn
|
|
|
|
|
thats correct but the code only works correct if you change
<br />
int CSortListCtrl::AddItem( LPCTSTR pszText, ... )<br />
{<br />
const int iIndex = InsertItem( GetItemCount(), pszText );<br />
LPTSTR* arrpsz = new LPTSTR[ m_iNumColumns ];<br />
.....<br />
into
<br />
int CSortListCtrl::AddItem( LPCTSTR pszText, ... )<br />
{<br />
const int iIndex = <font color=#ff0000>CListCtrl::</font>InsertItem( GetItemCount(), pszText );<br />
LPTSTR* arrpsz = new LPTSTR[ m_iNumColumns ];<br />
.....<br />
if not, my app crashed...
cheers,
vtx
|
|
|
|
|
I am interested in using this Sort List control with VC5. The description of the control indicates VC4-6, but I have been having problems with running it under VC5.
I have attempted to modify it to VC5, by doing the following:
1) comment out #include <afxdtctl.h> in stdafx.h
2) Use CStringEx instead of CString in SetHeader, in order
to get proper Find() (VC5 Find does not take two parameters)
3) Revise CSortListCtrl::PreSubclassWindow() to get pointer to CHeaderCtrl (no GetHeaderCtrl() in VC5)
When I run under debug, I get an assertion error:
CHeaderCtrl::GetItemCount() line 414 + 46 bytes
?Serialize@CSortHeaderCtrl@@UAEXAAVCArchive@@@Z + 194 bytes
?LoadColumnInfo@CSortListCtrl@@QAEXXZ + 270 bytes
?OnInitDialog@CSortListCtrlTestDlg@@MAEHXZ + 139 bytes
When I run under Release, control seems to work fine. I am using the demo project.
Any help appreciated. Thanks in advance.
Dick Males
Cincinnati, Ohio, USA
|
|
|
|
|
Really helpful class, good implementation. But...
In current release Windows XP Visual Styles is not supported, more - control works incorrectly if styles is used. I waiting for update
Date comparision and sorting made incorrectly. It's ignores system international settings.
|
|
|
|
|
Yes, it looks very bad on XP w/ Styles. I'm going to have to find another solution, whether it be modify this one or try my own derived CHeaderCtrl that behaves in the XP environment.
Give me one more medicated peaceful moment
|
|
|
|
|
i think it´s nice control, but i have 2 probs:
1) if i select an item, only the first column is colored, not all columne of the selected row
2) i´m using the control in a form view, and if i close my view, open again and exit the application, i get a some meory leaks:
SortListCtrl.cpp(132) : {337} normal block at 0x00303110, 16 bytes long.
Data: <Rezept Nummer 5 > 52 65 7A 65 70 74 20 4E 75 6D 6D 65 72 20 35 00
SortListCtrl.cpp(120) : {336} normal block at 0x00303150, 5 bytes long.
Data: <0005 > 30 30 30 35 00
\SortListCtrl.cpp(119) : {335} normal block at 0x00303190, 8 bytes long.
Data: <P10 10 > 50 31 30 00 10 31 30 00
SortListCtrl.cpp(413) : {334} normal block at 0x003031D0, 8 bytes long.
Data: < 20 > 90 32 30 00 00 00 00 00
SortListCtrl.cpp(132) : {333} normal block at 0x00303210, 16 bytes long.
Data: <Rezept Nummer 4 > 52 65 7A 65 70 74 20 4E 75 6D 6D 65 72 20 34 00
SortListCtrl.cpp(120) : {332} normal block at 0x00303250, 5 bytes long.
Data: <0004 > 30 30 30 34 00
SortListCtrl.cpp(119) : {331} normal block at 0x00303290, 8 bytes long.
Data: <P20 20 > 50 32 30 00 10 32 30 00
SortListCtrl.cpp(413) : {330} normal block at 0x003032D0, 8 bytes long.
Data: < 30 > 90 33 30 00 00 00 00 00
SortListCtrl.cpp(132) : {329} normal block at 0x00303310, 16 bytes long.
Data: <Rezept Nummer 3 > 52 65 7A 65 70 74 20 4E 75 6D 6D 65 72 20 33 00
SortListCtrl.cpp(120) : {328} normal block at 0x00303350, 5 bytes long.
Data: <0003 > 30 30 30 33 00
SortListCtrl.cpp(119) : {327} normal block at 0x00303390, 8 bytes long.
Data: <P30 30 > 50 33 30 00 10 33 30 00
SortListCtrl.cpp(413) : {326} normal block at 0x003033D0, 8 bytes long.
Data: < =0 > F0 3D 30 00 00 00 00 00
SortListCtrl.cpp(132) : {325} normal block at 0x00303410, 16 bytes long.
Data: <Rezept Nummer 2 > 52 65 7A 65 70 74 20 4E 75 6D 6D 65 72 20 32 00
SortListCtrl.cpp(120) : {324} normal block at 0x00303450, 5 bytes long.SortListCtrl.cpp(119) : {323} normal block at 0x00303DF0, 8 bytes long.
Data: <P40 40 > 50 34 30 00 10 34 30 00
Merlin\SortListCtrl.cpp(413) : {322} normal block at 0x00303E30, 8 bytes long.
Data: < 90 > F0 39 30 00 00 00 00 00
SortListCtrl.cpp(132) : {321} normal block at 0x00303E70, 21 bytes long.
Data: <Rezept Nummer 10> 52 65 7A 65 70 74 20 4E 75 6D 6D 65 72 20 31 30
SortListCtrl.cpp(120) : {320} normal block at 0x00303EC0, 5 bytes long.
Data: <0001 > 30 30 30 31 00
SortListCtrl.cpp(119) : {319} normal block at 0x003039F0, 8 bytes long.
Data: < >0 p>0 > C0 3E 30 00 70 3E 30 00
{309} normal block at 0x00303AB0, 57 bytes long.
Data: <C:\DEVELOPEMENT\> 43 3A 5C 44 45 56 45 4C 4F 50 45 4D 45 4E 54 5C
can anyone help me ?
|
|
|
|
|
In response to your first question:
m_cListControl.SetExtendedStyle(LVS_EX_FULLROWSELECT);
Bluute tette!
|
|
|
|
|
This message LVM_SORTITEMSEX is similar to LVM_SORTITEMS, except for the type of information passed to the comparison function. With LVM_SORTITEMSEX, lParam1 is the current index of the first item, and lParam2 is the current index of the second item. You can send an LVM_GETITEMTEXT message to get more information on an item, if needed.
The comparison function must return a negative value if the first item should precede the second, a positive value if the first item should follow the second, or zero if the two items are equivalent.
Note: During the sorting process, the list view contents are unstable. If the callback function sends any messages to the list view control aside from LVM_GETITEM (ListView_GetItem), the results are unpredictable.
Requirements
Version 5.80 and later of Comctl32.dll
|
|
|
|
|
Give me a sample,OK?
Thanks in advance!
Best Regards!
|
|
|
|
|
Agreed, this is a much simplier way...
<code>
#ifndef LVM_SORTITEMSEX
#define LVM_SORTITEMSEX (LVM_FIRST + 81)
#endif
BOOL CListCtrlEx::SortItemsEx(PFNLVCOMPARE pfnCompare, DWORD dwData)
{
ASSERT(::IsWindow(m_hWnd));
ASSERT((GetStyle() & LVS_OWNERDATA)==0);
return (BOOL) ::SendMessage(m_hWnd, LVM_SORTITEMSEX, dwData, (LPARAM)pfnCompare);
}
static int CALLBACK MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
CListCtrlEx* pListCtrl = (CListCtrlEx*) lParamSort;
CString strItem1 = pListCtrl->GetItemText(lParam1, pListCtrl->m_sortColumn);
CString strItem2 = pListCtrl->GetItemText(lParam2, pListCtrl->m_sortColumn);
return strcmp(strItem2, strItem1);
}
void CListCtrlEx::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
m_sortColumn = pNMListView->iSubItem;
SortItemsEx(MyCompareProc, (LPARAM)this);
*pResult = 0;
}
</code>
(oh, and you'll want to add this to your messagemap)
<br />
ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick)<br />
--
AnthonyJ@planetquake.com
www.btinternet.com/~AnthonyJ
|
|
|
|
|
|
I want to be able to specify diferent colors for the items I insert.
How can I do this?
Sebastian
|
|
|
|
|
See this article.
/ravi
"There is always one more bug..."
http://www.ravib.com
ravib@ravib.com
|
|
|
|
|
I may be totally dumb but try to add this code in a proggie :
POSITION p = m_c_listCtrl.GetFirstSelectedItemPosition();
int index = 0;
while(p){
index = m_c_listCtrl.GetNextSelectedItem(p);
m_c_listCtrl.DeleteItem(index);
}
this should delete all selected items...
after debugging and investigation i can't wonder why it only delete half selected items ex: select 6 items it will delete only 3.... isn't ti strange ??
any bug fix ?
thx
|
|
|
|
|
By deleting the items, you are confusing the position stuff. Another way you can do it is...
int nIndex;
while ((nIndex = m_c_listCtrl .GetNextItem (-1, LVNI_SELECTED) >= 0)
{
m_c_listCtrl .DeleteItem (nIndex);
}
Tim Smith
I know what you're thinking punk, you're thinking did he spell check this document? Well, to tell you the truth I kinda forgot myself in all this excitement. But being this here's CodeProject, the most powerful forums in the world and would blow your head clean off, you've got to ask yourself one question, Do I feel lucky? Well do ya punk?
|
|
|
|
|
I wanted to be able to use a loop to insert the fields of a database into the sortable list control without having to use one function with all the strings passed to it at once.
In the article you noted that you could add things the normal CListCtrl way, but when I did that, the sort just plain bombed. So I modified my insertion list to pass in the string aray that CSortListCtrl creates in AddItem.
I added the following member function:
int CSortListCtrl::AddStrList(const int iIndex, LPTSTR *arrpsz )
{
VERIFY( SetTextArray( iIndex, arrpsz ) );
return iIndex;
}
and the following modification to my code in the dialog that contains the CSortListCtrl:
CString item;
for(h = 0; h < recs; h++)
{
//Insert an item for this:
int iIndex = m_ctlList.InsertItem( cols, "" );
LPTSTR* arrpsz = new LPTSTR[ cols ];
//Loop through to set text for this row:
for(int j = 0; j < cols; j++)
{
set->GetFieldValue(j, item);
m_ctlList.SetItem(h, j, LVIF_TEXT, item, 0, 0, 0, NULL);
arrpsz[ j ] = new TCHAR[ lstrlen( item ) + 1 ];
(void)lstrcpy( arrpsz[ j ], item );
}
m_ctlList.AddStrList( iIndex, arrpsz );
//Move to the next record:
set->MoveNext();
}
Hope that helps people
|
|
|
|
|