I'm trying to figure out how to supply my own custom sort method to items and strings in a TListBox
.
My list box stores a custom object in its Object
property, and I need to use that in the custom sort.
I'm basing the below code on this post (Delphi): Is it possible to sort a TListBox using a custom sort comparator?
My custom sort function looks like this
int __fastcall SortListByValue (TStringList* sl, int item1, int item2)
{
IniKey* k1 = (IniKey*) sl->Objects[item1];
IniKey* k2 = (IniKey*) sl->Objects[item2];
return k1->mValue < k2->mValue;
}
The key values are strings. Currently they can be "-", "Yes", "No" and "Pass".
And the code where it is called is like this:
void __fastcall TMainForm::sortByValueAExecute(TObject *Sender)
{
Log(lInfo) << "Sorting list based on Values";
TStringList* sl = new TStringList();
sl->Assign(imagesLB->Items);
sl->CustomSort(SortListByValue);
imagesLB->Items->Assign(sl);
}
The above code does "something" to the list, but its not sorted.
The resulting list starts with "-" items, and all "Yes" items are consecutive. "No" and "Pass" and "-" items are then scrambled.
Any clues?
Your sort function is expected to return a value that is < 0
, 0
, or > 0
, depending on the desired order of the two input parameters. But you are not doing that correctly. You are returning either 0
or 1
, but never < 0
, because you are returning the (implicitly converted) result of a boolean expression, which can only be false
or true
.
You need to change this line:
return k1->mValue < k2->mValue;
To this instead:
if (k1->mValue < k2->mValue) return -1;
else if (k1->mValue > k2->mValue) return 1;
else return 0;
Alternatively, use the RTL's AnsiCompareStr()
or CompareStr()
function instead:
return AnsiCompareStr(k1->mValue, k2->mValue);
return CompareStr(k1->mValue, k2->mValue);