【问题标题】:Get Column Order (MFC)获取列顺序 (MFC)
【发布时间】:2013-08-22 14:19:36
【问题描述】:

我正在尝试获取 MFC CListCtrl 中列的顺序。最初,我尝试在 HDN_ENDDRAG 通知的消息处理程序中调用 GetColumnOrderArray(),但这总是返回旧的(拖放前)列顺序。因此,根据this SO 帖子评论中的建议,我尝试同时处理HDN_BEGINDRAGHDN_ENDDRAG,并使用phdr->pitem->iOrder 获取新旧列订单。但是在两个处理程序中,pitem 对我来说始终为 NULL。不知道为什么。

SOOO 我尝试使用存储在消息中的列索引 (phdr->iItem) 直接与 CHeaderCtrl 对话并自己获取列顺序,但是我的标题控件填充的结构中的字段都是无效的;我仍然无法获得列顺序。

我的列表控件是否存在某种更深层次的问题?还是我只是错误地处理了消息?

HDN_BEGINDRAG消息处理程序:

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消息处理程序:

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;
}

【问题讨论】:

    标签: visual-c++ mfc clistctrl


    【解决方案1】:

    虽然这是一个老问题,但我刚刚在查看 CListCtrl 列拖动时遇到了它,并认为我会对其进行一些更新,以防其他人使用它。

    OP提到,

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

    这将是因为您尚未初始化 columnStruct 足以告诉 GetItem 您有兴趣检索哪些数据。您需要使用各种标志初始化 columnStruct.mask,例如 HDI_WIDTH | HDI_ORDER,如果你使用 HDI_TEXT,那么给 columnStruct.pszText 一个缓冲区和 columnStruct.cchTextMax 缓冲区的大小。

    例如,这是documented in the CHeaderCtrl::GetItem documentation on MSDN

    在掩码元素中设置的任何标志确保 返回时正确填写相应的元素。如果面具 元素设置为零,其他结构元素中的值是 毫无意义。

    【讨论】:

    • 可爱,我只是没有仔细阅读文档-.-
    【解决方案2】:

    这可能是一个有点简单的解决方案,当需要关闭列表控件的父级时,为什么不调用GetColumnOrderArray()

    如果您确实需要立即将列顺序用于其他目的,并且从您引用的 SO 帖子中,看起来HDN_ENDDRAG 调用GetColumnOrderArray() 为时过早,请尝试将PostMessage 发送给(父级) OnHdnEnddrag() 末尾的列表控件,消息编号在 WM_USER through 0x7FFF 范围内,并在该消息的处理程序中调用 GetColumnOrderArray()

    【讨论】:

    • 我已经尝试了您的第一个解决方案,方法是从包含我的列表控件的CListView 的析构函数中调用GetColumnOrderArray(),但此时列表控件已经无效;程序崩溃了:(我会看看我是否可以让你的第二个解决方案工作,但PostMessage() 并没有让你确定何时处理消息,对吗?我不能保证父母会处理HDN_ENDDRAG 处理程序完成后的消息,GetColumnArray() 将返回有效答案?
    • 我确定析构函数为时已晚,这就是为什么我提到“当需要关闭列表控件的父级时”,所以这将在关闭过程开始之前;您使用什么样的父类来承载 ListControl? PostMessage 将在处理完所有其他队列消息后才处理该消息,值得一试
    • 好的,我试试看。父母是CListView。我试图从CListView 的析构函数中调用GetColumnOrderArray(),而不是CListCtrl()
    • 我最终只是创建了我自己的SaveState() 函数,我在程序的其他地方调用它(为了时间;你的解决方案可能工作得很好,idk)。我不喜欢它,因为它不是在消息通知之类的自动调用函数中完成的,但它可以工作:/ 感谢您的时间!
    • 我很高兴输入是有帮助的[我们通常在视图即将关闭时而不是在实际更改本身(如拖放)期间保存应用程序中的视图设置,即这样您就可以对列进行多次重新排序,并且设置仅在关闭时保存一次]
    猜你喜欢
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    • 1970-01-01
    • 2012-09-19
    • 2013-06-08
    • 2011-04-17
    相关资源
    最近更新 更多