lost_in_the_source
lost_in_the_source

Reputation: 11237

ListView sorting by wrong column

In this winapi program, I am sorting all the items based on the "Date" column. However, it is sorting by the "Description" column instead of the "Date" column. This is how my listview looks

Here is the code in WM_NOTIFY:

static char szText[10];
NM_LISTVIEW *pNm = (NM_LISTVIEW *)lParam;

switch (((LPNMHDR)lParam)->code) {
    case LVN_COLUMNCLICK:
        if (pNm->iSubItem == 2)
            if (ListView_SortItems(pNm->hdr.hwndFrom, CompareFunc, 
                               (LPARAM) (pNm->iSubItem)) == FALSE)
                MessageBox(hwnd, "FALSE", "", MB_OK);
        break;
 /* other WM_NOTIFY code */
}

ListView_SortItems returns TRUE, strangely. Here is the CompareFunc function:

int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
    if (lParamSort == 2) {
        date d1, d2;              // app-defined "date" class
        char b1[32], b2[32];

        sscanf((char *) lParam1, "%s %d %d", b1, &d1.day, &d1.yr);
        sscanf((char *) lParam2, "%s %d %d", b2, &d2.day, &d2.yr);

        d1.month = monthtoi(b1);    // converts month as string to number
        d2.month = monthtoi(b2);

        if (d1 > d2)                // overloading the ">" and "<" operators
            return 1;
        else if (d1 < d2)
            return -1;
        return 0;
    }
}

I tried checking iSubItem against 3 rather than 2 (1-based vs 0-based), but that didn't work either. What am I doing wrong?

Edit:

int monthtoi(char *s)
{
    int i;

    for (i = 0; i < 12; ++i) {
        // MONTHS is a global array of char *, containing the months
        if (strcmp(MONTHS[i], s) == 0)
            return i;
    }
    return -1;
}
bool date::operator>(const date &x)
{
    switch (this->cmp(x)) { // cmp is a private member function
    case 0:
    case -1:
        return false;
    case 1:
        return true;
    }
    return false;
}
bool date::operator<(const date &x)
{
    switch (this->cmp(x)) {
    case 0:
    case 1:
        return false;
    case -1:
        return true;
    }
    return false;
}
int date::cmp(const date &x)
{
    if (this->yr > x.yr)
        return 1;
    else if (this->yr < x.yr)
        return -1;

    if (this->yr == x.yr) {
        if (this->month > x.month)
            return 1;
        else if (this->month < x.month)
            return -1;
        else if (this->day > x.day)
            return 1;
        else if (this->day < x.day)
            return -1;
        else
            return 0;
    }
    return 0;
}

Upvotes: 2

Views: 530

Answers (1)

uesp
uesp

Reputation: 6204

The input lParam1 and lParam2 are not the string of the sub-item but as the documentation says they are the data associated with the item:

The lParam1 parameter is the 32-bit value associated with the first item being compared; and the lParam2 parameter is the value associated with the second item. These are the values that were specified in the lParam member of the items' LVITEM structure when they were inserted into the list.

You can find a complete ListView sorting example here but the basics of it are as follows:

          // Custom type storing the item's information, or a link to it
struct myitemdata_t 
{
    char* pFood;
    char* pDescription;
    date  Date;
    ...
};

     // When adding items to a listview set the item data
m_ctlListView.InsertItem(i, "food");
m_ctlListView.SetItemText(i, 1, "Saturday shopping");
...
     // Set the item data for the list item
m_ctlListView.SetItemData(i, (LPARAM) GetItemData(i));

    // Your sort function should look like
int CALLBACK SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
    myitemdata_t* pData1 = (myitemdata_t *)lParam1;
    myitemdata_t* pData2 = (myitemdata_t *)lParam2;
    ...

Upvotes: 2

Related Questions