|
Hello,
How about sorting, when style set to Icon. Is it supported by standart CListCtrl? Or there will be no other way, but to implement it's handling myself?
Any ideas?
Thank you.
Rimantas
|
|
|
|
|
I use the sort method of CListCtrl,but the following code
is not work,Why?
static int CALLBACK MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
CListCtrl* pListCtrl = (CListCtrl*) lParamSort;
CString strItem1 = pListCtrl->GetItemText(lParam1, 0);
CString strItem2 = pListCtrl->GetItemText(lParam2, 0);
return strcmp(strItem2, strItem1);
}
void SortItems()
{
extern CListCtrl* pmyListCtrl;
pmyListCtrl->SortItems(MyCompareProc, (LPARAM) pmyListCtrl);
}
Thanks in advance!
Best Regards!
|
|
|
|
|
first, the second parameter of "SortItems" must be DWORD type, but in your code, the second parameter is "LPARAM" type.
second, check if the "pmyListCtrl" points to the right CListCtrl object. it's possible that "pmyListCtrl" is null.
only my opinion, it can be wrong...
|
|
|
|
|
you have to use SetItemData() to set the sort index first.
|
|
|
|
|
In order for floating point sorting to be done properly, a couple of simple changes need to be made. (Great coding, btw!):
Before:
bool IsNumber( LPCTSTR pszText )
{
ASSERT_VALID_STRING( pszText );
register int i, length = lstrlen( pszText );
for( i = 0; i < length; i++ )
if( !_istdigit( pszText[ i ] ) )
return false;
return true;
}
After:
bool IsNumber( LPCTSTR pszText )
{
ASSERT_VALID_STRING( pszText );
register int i, length = lstrlen( pszText );
for( i = 0; i < length; i++ )
if( !_istdigit( pszText[ i ] ) && (pszText[ i ] != _T( '.' )) )
return false;
return true;
}
and Before:
int NumberCompare( LPCTSTR pszNumber1, LPCTSTR pszNumber2 )
{
ASSERT_VALID_STRING( pszNumber1 );
ASSERT_VALID_STRING( pszNumber2 );
const int iNumber1 = atoi( pszNumber1 );
const int iNumber2 = atoi( pszNumber2 );
if( iNumber1 < iNumber2 )
return -1;
if( iNumber1 > iNumber2 )
return 1;
return 0;
}
After:
int NumberCompare( LPCTSTR pszNumber1, LPCTSTR pszNumber2 )
{
ASSERT_VALID_STRING( pszNumber1 );
ASSERT_VALID_STRING( pszNumber2 );
const float iNumber1 = atof( pszNumber1 );
const float iNumber2 = atof( pszNumber2 );
if( iNumber1 < iNumber2 )
return -1;
if( iNumber1 > iNumber2 )
return 1;
return 0;
}
|
|
|
|
|
I want to use this contorl in a SDI project, but when I creat this control in the view, the program got an "unknown software exception(0x800000003)". I use create function in the OnInitialUpdate(), and the code like this:
...
m_list = new CSortListCtrl;
if (!m_list) return;
CRect rect;
GetClientRect(rect);
m_list->Create(WS_CHILD|WS_VISIBLE|WS_BORDER|LVS_REPORT,rect, this, 100);
...
Can someone help me? Is there any SDI or MDI demo about this control?
|
|
|
|
|
I have the same problem too.
I need some advice.
help us.
|
|
|
|
|
I didn't see any responses to your request on the SDI example for the sort list control. Did you ever get it figured out? I'm trying to do the same thing.
Mike Ellertson
|
|
|
|
|
First place the listctrl onto a dialog, and then put the dialog into a view.
______________
Anything, I Can.
|
|
|
|
|
|
Hi,
In View, I am unable to successfully create an instance of CSortListCtrl.
The statement CSortListCtrl m_ListCtrl; or CSortListCtrl = new m_ListCtrl; returns a NULL for m_ListCtrl. So am not able to reference any of its functions in View. I wish someone could show me how!!
mad:
Pete
|
|
|
|
|
Some folks had been complaining about how horrendous the header control looked in Win XP w/ Visual Styles. I believe I have fixed this issue. I changed the function SetSortArrow in SortHeaderCtrl.cpp to the following:
<br />
void CSortHeaderCtrl::SetSortArrow(const int iSortColumn, const BOOL bSortAscending)<br />
{<br />
DWORD dwHigh, dwLow;<br />
<br />
GetCommonControlVersion(dwHigh, dwLow);<br />
<br />
if (dwHigh < 6)<br />
{<br />
HD_ITEM hditem;<br />
<br />
hditem.mask = HDI_FORMAT;<br />
VERIFY(GetItem(iSortColumn, &hditem));<br />
hditem.fmt |= HDF_OWNERDRAW;<br />
VERIFY(SetItem(iSortColumn, &hditem));<br />
<br />
Invalidate();<br />
}<br />
else<br />
{<br />
HD_ITEM hditem;<br />
<br />
hditem.mask = HDI_FORMAT;<br />
VERIFY(GetItem(iSortColumn, &hditem));<br />
<br />
if (bSortAscending)<br />
{<br />
hditem.fmt &= ~HDF_SORTDOWN;<br />
hditem.fmt |= HDF_SORTUP;<br />
}<br />
else<br />
{<br />
hditem.fmt &= ~HDF_SORTUP;<br />
hditem.fmt |= HDF_SORTDOWN;<br />
}<br />
<br />
VERIFY(SetItem(iSortColumn, &hditem));<br />
<br />
if ((m_iSortColumn > -1) && (m_iSortColumn != iSortColumn))<br />
{<br />
hditem.mask = HDI_FORMAT;<br />
VERIFY(GetItem(m_iSortColumn, &hditem));<br />
<br />
hditem.fmt &= ~HDF_SORTUP;<br />
hditem.fmt &= ~HDF_SORTDOWN;<br />
VERIFY(SetItem(m_iSortColumn, &hditem));<br />
}<br />
}<br />
<br />
m_iSortColumn = iSortColumn;<br />
m_bSortAscending = bSortAscending;<br />
}<br />
and my little function to get the common control version is also in this class (although it doesn't need to be).
<br />
bool CSortHeaderCtrl::GetCommonControlVersion(DWORD &dwHigh, DWORD &dwLow)<br />
{<br />
bool bRet = false;<br />
<br />
HMODULE hMod = LoadLibrary("COMCTL32.DLL");<br />
<br />
if (hMod != NULL)<br />
{<br />
DLLGETVERSIONPROC pDllGetVersion;<br />
pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hMod, "DllGetVersion");<br />
<br />
if (pDllGetVersion)<br />
{<br />
DLLVERSIONINFO dvi;<br />
HRESULT hr;<br />
<br />
ZeroMemory(&dvi, sizeof(dvi));<br />
dvi.cbSize = sizeof(dvi);<br />
<br />
hr = (*pDllGetVersion)(&dvi);<br />
<br />
if (SUCCEEDED(hr))<br />
{<br />
memcpy(&dwHigh, &dvi.dwMajorVersion, sizeof(DWORD));<br />
memcpy(&dwLow, &dvi.dwMinorVersion, sizeof(DWORD));<br />
}<br />
}<br />
<br />
FreeLibrary(hMod);<br />
}<br />
else<br />
{<br />
bRet = false;<br />
}<br />
<br />
return bRet;<br />
}<br />
Hope this helps.
Give me one more medicated peaceful moment
|
|
|
|
|
Thanks for the fix. It works for me with VS6SP5, but I am using an old version of the SDK.
So I added:
#ifndef HDF_SORTUP
#define HDF_SORTUP 0x0400
#endif
#ifndef HDF_SORTDOWN
#define HDF_SORTDOWN 0x0200
#endif
|
|
|
|
|
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
|
|
|
|
|