Question

I'm trying to get the order of the columns in an MFC CListCtrl. Initially I tried calling GetColumnOrderArray() in a message handler for the HDN_ENDDRAG notification, but that always returned the old (pre-drag and drop) column order. So, based on the advice in this SO post's comment, I tried handling both the HDN_BEGINDRAG and the HDN_ENDDRAG and grabbing the old and new column orders with phdr->pitem->iOrder. But pitem is always NULL for me in the both handlers. No idea why.

SOOO I tried using the column index stored in the message (phdr->iItem) to talk directly to the CHeaderCtrl and grab the column order myself, but the fields in the structure populated by my header control were all invalid; I still couldn't get the column order.

Is there some sort of deeper problem with my list control? Or am I just handling messages incorrectly?

HDN_BEGINDRAG message handler:

BOOL CDFAManListView::OnHdnBegindrag(UINT, NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);

    phdr->iItem; // this contains a valid column index

    HDITEM columnStruct;

    List->GetHeaderCtrl()->GetItem(phdr->iItem, &columnStruct); // but this call just fills columnStruct with junk values

    if (phdr->pitem) // pitem is always null
    {
        initialPosition = phdr->pitem->iOrder;
    }

    *pResult = 0;
    return TRUE;
}

HDN_ENDDRAG message handler:

void CDFAManListView::OnHdnEnddrag(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);

    HDITEM columnStruct;

    List->GetHeaderCtrl()->GetItem(phdr->iItem, &columnStruct); // still just fills columnStruct with junk

    List->GetColumnOrderArray(signalColumnOrder); // gets **old** column order

    *pResult = 0;
}
Was it helpful?

Solution

While this is an old question, I came across it just now while looking into CListCtrl column dragging and thought I'd update it a bit in case it's of use to somebody else.

The OP mentioned that,

HDITEM columnStruct;

List->GetHeaderCtrl()->GetItem(phdr->iItem, &columnStruct); // but this call just fills columnStruct with junk values

This will because you haven't initialised columnStruct enough to tell GetItem what data you're interested in retrieving. You need to initialise columnStruct.mask with various flags such as HDI_WIDTH | HDI_ORDER, and if you use HDI_TEXT then give columnStruct.pszText a buffer and columnStruct.cchTextMax the size of the buffer.

This is documented in the CHeaderCtrl::GetItem documentation on MSDN for example.

Any flags set in the mask element ensure that values in the corresponding elements are properly filled in upon return. If the mask element is set to zero, values in the other structure elements are meaningless.

OTHER TIPS

This may be a bit of simplistic solution, why not call GetColumnOrderArray() when the parent of the list control needs to be closed?

If you do need the column order for some other purpose right away and from the SO post you quoted, it looks like HDN_ENDDRAG is too early to call GetColumnOrderArray(), try a PostMessage to the (parent of) the list control at the end of OnHdnEnddrag() with the message number in the range WM_USER through 0x7FFF and call GetColumnOrderArray() in the handler of that message.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top