Sorting Columns in Report View
Ken Sutherland -- ken@j-mac.co.jp Wednesday, February 19, 1997 Environment: VC++ 4.2b, Win NT 4.0 (Note: I'm using Japanese versions) I am having trouble sorting columns in Report View. CListView::SortItems is always passing null pointers (zeros) to my compare function, so I can't compare anything. My PreCreateWindow and OnIntialUpdate look like this: BOOL CMyListView::PreCreateWindow(CREATESTRUCT& cs) { cs.style = (cs.style & ~LVS_TYPEMASK) | LVS_REPORT; return CListView::PreCreateWindow(cs); } void CMyListView::OnInitialUpdate() { CListView::OnInitialUpdate(); CListCtrl& cListCtrl = (CListCtrl&) GetListCtrl(); CString cHeading = "This is a test"; cListCtrl.InsertColumn(0, cHeading); int Width = cListCtrl.GetStringWidth(cHeading) + 20; cListCtrl.SetColumnWidth(0, Width); cListCtrl.InsertItem(0, "Row 0"); cListCtrl.InsertItem(1, "Row 1"); cListCtrl.InsertItem(2, "Row 2"); } My CompareFunc looks like this: int CALLBACK CompareFunc(char * pString1, char * pString2, LPARAM lCol) { TRACE("CompareFunc('%s', '%s', %i)\n", pString1, pString2, lCol); return 0; } void CMyListView::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; int ColNum = pNMListView->iSubItem; TRACE("Sorting Column %i\n", ColNum); CListCtrl& cListCtrl = (CListCtrl&) GetListCtrl(); cListCtrl.SortItems((PFNLVCOMPARE)CompareFunc, ColNum); *pResult = 0; } When I click on column 0, I get the following trace output: Sorting Column 0 CompareFunc('(null)', '(null)', 0) CompareFunc('(null)', '(null)', 0) I have been trying to follow "samples\mfc\INTERNET\HTTPSVR\HTTPVIEW.CPP" as closely as possible, but no matter what I try, I always get the null pointers, though the column number is passes correctly. Has anyone experienced this? ------------------------------- Ken Sutherland J-MAC SYSTEM, Inc. ken@j-mac.co.jp ken@ http://www.voicenet.co.jp/~ken
Peter Moss -- pmoss@bbn.com Wednesday, February 19, 1997 A couple of problems with your approach which are completely consistent with the results you indicate: Your API for the CompareFunc is incorrect. The CListCtrl::SortItems doc describes it correctly: int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); The lParam1 and lParam2 parameters specify the item data for the two items being compared. The lParamSort parameter is the same as the dwData value. 2. Note that the LPARAM args lParam1 and lParam2 are the 32-bit data values that you store with each item in your control. In your example, you do not set these values using InsertItem or SetItemData, thus their values are 0 (or NULL) for all items. This explains your problem. Thus, you'll need to use the Data value since that's all you get in your CompareFunc in order to do your sorting. Good luck, Peter _________________________________________________________ To: mfc-l@ Internet cc: Subject: Sorting Columns in Report View Environment: VC++ 4.2b, Win NT 4.0 (Note: I'm using Japanese versions) I am having trouble sorting columns in Report View. CListView::SortItems is always passing null pointers (zeros) to my compare function, so I can't compare anything. My PreCreateWindow and OnIntialUpdate look like this: BOOL CMyListView::PreCreateWindow(CREATESTRUCT& cs) { cs.style = (cs.style & ~LVS_TYPEMASK) | LVS_REPORT; return CListView::PreCreateWindow(cs); } void CMyListView::OnInitialUpdate() { CListView::OnInitialUpdate(); CListCtrl& cListCtrl = (CListCtrl&) GetListCtrl(); CString cHeading = "This is a test"; cListCtrl.InsertColumn(0, cHeading); int Width = cListCtrl.GetStringWidth(cHeading) + 20; cListCtrl.SetColumnWidth(0, Width); cListCtrl.InsertItem(0, "Row 0"); cListCtrl.InsertItem(1, "Row 1"); cListCtrl.InsertItem(2, "Row 2"); } My CompareFunc looks like this: int CALLBACK CompareFunc(char * pString1, char * pString2, LPARAM lCol) { TRACE("CompareFunc('%s', '%s', %i)\n", pString1, pString2, lCol); return 0; } void CMyListView::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; int ColNum = pNMListView->iSubItem; TRACE("Sorting Column %i\n", ColNum); CListCtrl& cListCtrl = (CListCtrl&) GetListCtrl(); cListCtrl.SortItems((PFNLVCOMPARE)CompareFunc, ColNum); *pResult = 0; } When I click on column 0, I get the following trace output: Sorting Column 0 CompareFunc('(null)', '(null)', 0) CompareFunc('(null)', '(null)', 0) I have been trying to follow "samples\mfc\INTERNET\HTTPSVR\HTTPVIEW.CPP" as closely as possible, but no matter what I try, I always get the null pointers, though the column number is passes correctly. Has anyone experienced this? ------------------------------- Ken Sutherland J-MAC SYSTEM, Inc. ken@j-mac.co.jp ken@ http://www.voicenet.co.jp/~ken
Alan Ruland -- alan@hstart.com Wednesday, February 19, 1997 Ken , While most would expect the parameters of CompareFunc to be the item numbers of the two items being compared, they are actually the item datas of those two items. Doc: "The lParam1 and lParam2 parameters specify the item data for the two items being compared." (The way you have it coded, you assumed the parameters were the actual text of the compared column. I think I see where you were confused--- by "item data", the docs are referring to the GetItemData/SetItemData 32 bit value, not the item text.) The standard kludge to get around this is to add item data to all your items, making them all unique values, and provide a mapping to the corresponding item numbers or item text. I would expect other answers to your question to advocate this (there was an artilce in a recent MSJ that used this approach). The problem with this, of course, is when you want to add sorting to a list control that already uses the item data value to store useful information for the items. --Alan ---------- From: owner-mfc-l Sent: Wednesday, February 19, 1997 12:38 PM To: mfc-l Subject: Sorting Columns in Report View Environment: VC++ 4.2b, Win NT 4.0 (Note: I'm using Japanese versions) I am having trouble sorting columns in Report View. CListView::SortItems is always passing null pointers (zeros) to my compare function, so I can't compare anything. My PreCreateWindow and OnIntialUpdate look like this: BOOL CMyListView::PreCreateWindow(CREATESTRUCT& cs) { cs.style = (cs.style & ~LVS_TYPEMASK) | LVS_REPORT; return CListView::PreCreateWindow(cs); } void CMyListView::OnInitialUpdate() { CListView::OnInitialUpdate(); CListCtrl& cListCtrl = (CListCtrl&) GetListCtrl(); CString cHeading = "This is a test"; cListCtrl.InsertColumn(0, cHeading); int Width = cListCtrl.GetStringWidth(cHeading) + 20; cListCtrl.SetColumnWidth(0, Width); cListCtrl.InsertItem(0, "Row 0"); cListCtrl.InsertItem(1, "Row 1"); cListCtrl.InsertItem(2, "Row 2"); } My CompareFunc looks like this: int CALLBACK CompareFunc(char * pString1, char * pString2, LPARAM lCol) { TRACE("CompareFunc('%s', '%s', %i)\n", pString1, pString2, lCol); return 0; } void CMyListView::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; int ColNum = pNMListView->iSubItem; TRACE("Sorting Column %i\n", ColNum); CListCtrl& cListCtrl = (CListCtrl&) GetListCtrl(); cListCtrl.SortItems((PFNLVCOMPARE)CompareFunc, ColNum); *pResult = 0; } When I click on column 0, I get the following trace output: Sorting Column 0 CompareFunc('(null)', '(null)', 0) CompareFunc('(null)', '(null)', 0) I have been trying to follow "samples\mfc\INTERNET\HTTPSVR\HTTPVIEW.CPP" as closely as possible, but no matter what I try, I always get the null pointers, though the column number is passes correctly. Has anyone experienced this? ------------------------------- Ken Sutherland J-MAC SYSTEM, Inc. ken@j-mac.co.jp ken@ http://www.voicenet.co.jp/~ken
ABBINFO -- mail.karatel.fr@majordomo.netcom.com Thursday, February 20, 1997 [Mini-digest: 5 responses] Hi, I think that your problem comes to the parameters of your sorting = function. You declare the 2 first parameters in char * when that the correct = declaration is LPARAM. See this sample : int the OnColumnclick void CDlgReceptionMessages::OnColumnclickListMessagesRecus(NMHDR* = pNMHDR, LRESULT* pResult)=20 ----- My sorting function that is static, the parameter is a pointer of = the instance of the current object m_ListMessRecus.SortItems(CompareObjets,(LPARAM)this); --- Then in the static sorting function, I get the text of the 2 = compared items. lParam1 and lParam2 represent the number of items that are compared, not = the text!!! int CALLBACK CDlgReceptionMessages::CompareObjets(LPARAM lParam1, LPARAM lParam2, LPARAM LParamSort) { int Result=3D0; CDlgReceptionMessages *pPapa; CString Chaine1; CString Chaine2; // Recuparation du pointeur sur l'instance de la classe creee pPapa =3D (CDlgReceptionMessages *) LParamSort; if(lParam1>=3D0 && lParam2>=3D0) { // Recuperation des items Chaine1 =3D (pPapa->m_ListMessRecus).GetItemText((int)lParam1, pPapa->m_ColonneSelect); Chaine2 =3D (pPapa->m_ListMessRecus).GetItemText((int)lParam2, pPapa->m_ColonneSelect); Result =3D Chaine1.Compare(LPCTSTR(Chaine2)); } return Result; } ----- Don't forget that when you insert yours items in the report list = add the number of item for the sorting function because it uses the = lParam of the item : iltem is the number of item inserted obj.mask =3D LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM |LVIF_STATE; obj.iItem =3D iItem; obj.iSubItem =3D 0; obj.stateMask =3D 0; obj.state =3D 0; obj.lParam =3D iItem; strcpy(texte,TypeMess); obj.pszText =3D texte; iActualItem =3D m_ListMessRecus.InsertItem(&obj); ---------- De : Ken Sutherland My CompareFunc looks like this: int CALLBACK CompareFunc(char * pString1, char * pString2, LPARAM lCol) { TRACE("CompareFunc('%s', '%s', %i)\n", pString1, pString2,=20 lCol); return 0; } void CMyListView::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult)=20 { NM_LISTVIEW* pNMListView =3D (NM_LISTVIEW*)pNMHDR; int ColNum =3D pNMListView->iSubItem; TRACE("Sorting Column %i\n", ColNum); CListCtrl& cListCtrl =3D (CListCtrl&) GetListCtrl(); cListCtrl.SortItems((PFNLVCOMPARE)CompareFunc, ColNum); =09 *pResult =3D 0; } When I click on column 0, I get the following trace output: Sorting Column 0 CompareFunc('(null)', '(null)', 0) CompareFunc('(null)', '(null)', 0) I have been trying to follow "samples\mfc\INTERNET\HTTPSVR\HTTPVIEW.CPP" as closely as possible, but no matter what I try, I always get the null pointers, though the column number is passes correctly. Has anyone experienced this? ------------------------------- Ken Sutherland =20 J-MAC SYSTEM, Inc. ken@j-mac.co.jp ken@ http://www.voicenet.co.jp/~ken =20 =20 -----From: coghlans> From: Ken Sutherland [SMTP:ken@j-mac.co.jp] > Sent: Wednesday, February 19, 1997 3:39 AM > I am having trouble sorting columns in Report View. > CListView::SortItems is always passing null pointers (zeros) to my > compare function, so I can't compare anything. Ken.. In order to get the CompareFunc to work, the list must have Data pointer = set up that reflect the actual displayed list data. The function Def = looks like :- int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM = lParamSort); were the LPARAM variables have to be cast to the actual data types. i.e. = int CALLBACK CLogListCtrl::CompareFunc( LPARAM lParam1, LPARAM lParam2, = LPARAM lParamSort ) { ITEMINFO* pItem1 =3D (ITEMINFO*)lParam1; ITEMINFO* pItem2 =3D (ITEMINFO*)lParam2; int iResult =3D 0; // Do the Compare switch( lParamSort & 0x0f) { case 0: if ( pItem1->iLine > pItem2->iLine ) // Date iResult =3D 1; else iResult =3D -1; break; etc.. } etc. } Dont forget that when an item is deleted you will have to delete the = item data pointer as well . i.e. void CLogListCtrl::OnDeleteitem( NMHDR* pNMHDR, LRESULT* pResult )=20 { NM_LISTVIEW* pNMListView =3D (NM_LISTVIEW*)pNMHDR; ASSERT( pNMListView->hdr.code =3D=3D LVN_DELETEITEM ); ITEMINFO* pObject =3D (ITEMINFO*)CListCtrl::GetItemData( = pNMListView->iItem ); ASSERT( pObject ); delete pObject; *pResult =3D 0; } // End CLogListCtrl::OnDeleteitem Check out CListCtrl::InsertItem(...) for details of adding Data objects = to List items.. Simon=20 ----------<- Smurf-IV ->------------- Tel : 0121 200 7713 Fax : +44 (0)121 212 0379 Email smurf-iv@sharelink.com Member of the 'Team of nee CIS' now FOA in CPA ;-) ---------<- Fun To All ->------------ We are what we repeatedly do, Excellence, then, is not an act, but a = habit. Aristotle The one who says it cannot be done, should never interrupt the one who = is doing it. The Roman Rule -----Original Message----- From: Ken Sutherland [SMTP:ken@j-mac.co.jp] Sent: Wednesday, February 19, 1997 3:39 AM To: mfc-l@netcom.com Subject: Sorting Columns in Report View Environment: VC++ 4.2b, Win NT 4.0 (Note: I'm using Japanese versions) I am having trouble sorting columns in Report View. CListView::SortItems is always passing null pointers (zeros) to my compare function, so I can't compare anything. My PreCreateWindow and OnIntialUpdate look like this: BOOL CMyListView::PreCreateWindow(CREATESTRUCT& cs)=20 { cs.style =3D (cs.style & ~LVS_TYPEMASK) | LVS_REPORT; return CListView::PreCreateWindow(cs); } void CMyListView::OnInitialUpdate()=20 { CListView::OnInitialUpdate(); =09 CListCtrl& cListCtrl =3D (CListCtrl&) GetListCtrl(); CString cHeading =3D "This is a test"; cListCtrl.InsertColumn(0, cHeading); int Width =3D cListCtrl.GetStringWidth(cHeading) + 20; cListCtrl.SetColumnWidth(0, Width); cListCtrl.InsertItem(0, "Row 0"); cListCtrl.InsertItem(1, "Row 1"); cListCtrl.InsertItem(2, "Row 2"); } My CompareFunc looks like this: int CALLBACK CompareFunc(char * pString1, char * pString2, LPARAM lCol) { TRACE("CompareFunc('%s', '%s', %i)\n", pString1, pString2,=20 lCol); return 0; } void CMyListView::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult)=20 { NM_LISTVIEW* pNMListView =3D (NM_LISTVIEW*)pNMHDR; int ColNum =3D pNMListView->iSubItem; TRACE("Sorting Column %i\n", ColNum); CListCtrl& cListCtrl =3D (CListCtrl&) GetListCtrl(); cListCtrl.SortItems((PFNLVCOMPARE)CompareFunc, ColNum); =09 *pResult =3D 0; } When I click on column 0, I get the following trace output: Sorting Column 0 CompareFunc('(null)', '(null)', 0) CompareFunc('(null)', '(null)', 0) I have been trying to follow "samples\mfc\INTERNET\HTTPSVR\HTTPVIEW.CPP" as closely as possible, but no matter what I try, I always get the null pointers, though the column number is passes correctly. Has anyone experienced this? ------------------------------- Ken Sutherland =20 J-MAC SYSTEM, Inc. ken@j-mac.co.jp ken@ http://www.voicenet.co.jp/~ken =20 -----From: Simon Young Yes, I have experienced this, but in a slightly different environment. I discovered that exactly the same code in a CListCtrl compare function was passing me null pointers when run under Win32s but functioned correctly on NT 3.51. Another twist was that a CListView with the same code was OK on both platforms but a CListCtrl inserted into a CDialogBar didn't work on WIN32s. In the end I resorted to sorting the data myself using qsort and then relying on the order of insert into the control to display it correctly. This worked OK. Regards Simon To: mfc-l @ netcom.com @ SMTP cc: From: ken @ j-mac.co.jp (Ken Sutherland) @ SMTP Sent: Wed 02/19/97 12:38:45 PM EST Subject: Sorting Columns in Report View Environment: VC++ 4.2b, Win NT 4.0 (Note: I'm using Japanese versions) I am having trouble sorting columns in Report View. CListView::SortItems is always passing null pointers (zeros) to my compare function, so I can't compare anything. My PreCreateWindow and OnIntialUpdate look like this: BOOL CMyListView::PreCreateWindow(CREATESTRUCT& cs) { cs.style = (cs.style & ~LVS_TYPEMASK) | LVS_REPORT; return CListView::PreCreateWindow(cs); } void CMyListView::OnInitialUpdate() { CListView::OnInitialUpdate(); CListCtrl& cListCtrl = (CListCtrl&) GetListCtrl(); CString cHeading = "This is a test"; cListCtrl.InsertColumn(0, cHeading); int Width = cListCtrl.GetStringWidth(cHeading) + 20; cListCtrl.SetColumnWidth(0, Width); cListCtrl.InsertItem(0, "Row 0"); cListCtrl.InsertItem(1, "Row 1"); cListCtrl.InsertItem(2, "Row 2"); } My CompareFunc looks like this: int CALLBACK CompareFunc(char * pString1, char * pString2, LPARAM lCol) { TRACE("CompareFunc('%s', '%s', %i)\n", pString1, pString2, lCol); return 0; } void CMyListView::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; int ColNum = pNMListView->iSubItem; TRACE("Sorting Column %i\n", ColNum); CListCtrl& cListCtrl = (CListCtrl&) GetListCtrl(); cListCtrl.SortItems((PFNLVCOMPARE)CompareFunc, ColNum); *pResult = 0; } When I click on column 0, I get the following trace output: Sorting Column 0 CompareFunc('(null)', '(null)', 0) CompareFunc('(null)', '(null)', 0) I have been trying to follow "samples\mfc\INTERNET\HTTPSVR\HTTPVIEW.CPP" as closely as possible, but no matter what I try, I always get the null pointers, though the column number is passes correctly. Has anyone experienced this? ------------------------------- Ken Sutherland J-MAC SYSTEM, Inc. ken@j-mac.co.jp ken@ http://www.voicenet.co.jp/~ken -----From: "petter.hesselberg" The definition of PFNLVCOMPARE is: typedef int (CALLBACK *PFNLVCOMPARE)(LPARAM, LPARAM, LPARAM); There's nothing here about strings. The fact that you had to typecast your function is an ominous sign. In fact, the two first parameters are NOT strings, but the user-defined lParam values in the LV_ITEM struct. Since you do not set these in your code, they remain 0. If you set the lParam of each item to be the address of the text string you're displaying, your Compare function should work (see the more complex variants of AddItem for how to do this). If you use this approach, make sure those string pointers remain valid. A better approach would be to apply some architectural thinking. All but the most elementary uses of listviews are complex. Consider using lParam as a pointer to an object, and using the listview callback mechanisms for display text, icons, et cetera. Regards, Petter Hesselberg Andersen Consulting ___________________________________________________________________________________________________________________________________________________________________________________________________________________ To: mfc-l @ netcom.com @ internet cc: (bcc: Petter Hesselberg) From: ken @ j-mac.co.jp (Ken Sutherland) @ internet Date: 19-02-97 18:38 Subject: Sorting Columns in Report View ___________________________________________________________________________________________________________________________________________________________________________________________________________________ Environment: VC++ 4.2b, Win NT 4.0 (Note: I'm using Japanese versions) I am having trouble sorting columns in Report View. CListView::SortItems is always passing null pointers (zeros) to my compare function, so I can't compare anything. My PreCreateWindow and OnIntialUpdate look like this: BOOL CMyListView::PreCreateWindow(CREATESTRUCT& cs) { cs.style = (cs.style & ~LVS_TYPEMASK) | LVS_REPORT; return CListView::PreCreateWindow(cs); } void CMyListView::OnInitialUpdate() { CListView::OnInitialUpdate(); CListCtrl& cListCtrl = (CListCtrl&) GetListCtrl(); CString cHeading = "This is a test"; cListCtrl.InsertColumn(0, cHeading); int Width = cListCtrl.GetStringWidth(cHeading) + 20; cListCtrl.SetColumnWidth(0, Width); cListCtrl.InsertItem(0, "Row 0"); cListCtrl.InsertItem(1, "Row 1"); cListCtrl.InsertItem(2, "Row 2"); } My CompareFunc looks like this: int CALLBACK CompareFunc(char * pString1, char * pString2, LPARAM lCol) { TRACE("CompareFunc('%s', '%s', %i)\n", pString1, pString2, lCol); return 0; } void CMyListView::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; int ColNum = pNMListView->iSubItem; TRACE("Sorting Column %i\n", ColNum); CListCtrl& cListCtrl = (CListCtrl&) GetListCtrl(); cListCtrl.SortItems((PFNLVCOMPARE)CompareFunc, ColNum); *pResult = 0; } When I click on column 0, I get the following trace output: Sorting Column 0 CompareFunc('(null)', '(null)', 0) CompareFunc('(null)', '(null)', 0) I have been trying to follow "samples\mfc\INTERNET\HTTPSVR\HTTPVIEW.CPP" as closely as possible, but no matter what I try, I always get the null pointers, though the column number is passes correctly. Has anyone experienced this? ------------------------------- Ken Sutherland J-MAC SYSTEM, Inc. ken@j-mac.co.jp ken@ http://www.voicenet.co.jp/~ken -----From: Kostya Sebov Dear Ken, In mfc-l you wrote: Environment: VC++ 4.2b, Win NT 4.0 (Note: I'm using Japanese versions) I am having trouble sorting columns in Report View. CListView::SortItems is always passing null pointers (zeros) to my compare function, so I can't compare anything. When I click on column 0, I get the following trace output: Sorting Column 0 CompareFunc('(null)', '(null)', 0) CompareFunc('(null)', '(null)', 0) I have been trying to follow "samples\mfc\INTERNET\HTTPSVR\HTTPVIEW.CPP" as closely as possible, but no matter what I try, I always get the null pointers, though the column number is passes correctly. Has anyone experienced this? ------------------------------- Help on CListCtrl::SortItems (in the Visual's Books Online) states: [...] The lParam1 and lParam2 [in the CompareProc] parameters specify the item data for the two items being compared. The lParamSort parameter is the same as the dwData value [ passed to the CListCtrl::SortItems]. So you should "compare" not the strings but the custom data you've previously associated with the listview items. Of course you may set it to the same strings (if you manage them yourself). IMO, the way sorting for the listview items is implemented is hardly obvious and flexible but it well documented and manageable. HTH, Kostya Sebov. ---------------------------------------------------------------------------- Tel: +(38 044) 266-6387 /work/, +(38 044) 513-2591 /home/ mailto: sebov@is.kiev.ua --------------------------------------------------------------------------- Leading programmer Intelligent Systems (Boston-Kiev) voice/fax: +(38 044)266-6195 mailto: company@is.kiev.ua http://www.i-rip.com
Become an MFC-L member | Вернуться в корень Архива |