繁体   English   中英

无法收到ListView的所有NM_CUSTOMDRAW dwDrawStage

[英]Unable to receive all NM_CUSTOMDRAW dwDrawStage for a ListView

我有一个带有MDI框架窗口的Win32应用程序(无mfc)。

MDI主框架窗口将具有MDICLIENT窗口。 但是在我的应用程序中,主框架窗口还有另一个tabctrl子窗口,它在主框架的底部显示一些listview Wnd:

//create the tab first, as a child of main MDI frame with 800px width and 300px height, at point (0, 600) of main frame window.
HWND hWndTabCtrl = CreateWindow(WC_TABCONTROL, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_VISIBLE | TCS_BOTTOM, 0, 600, 800, 300, hWndMainFrame, NULL, hInstance, NULL);

//add one tab item for test:
TCITEM item;
item.mask = TCIF_TEXT;
item.pszText = L"Test List View";
TabCtrl_InsertItem(hWndTabCtrl , 0, &item);

//And then create a listview, this list view is a child window of tab ctrl (hWndTabCtrl)
HWND hWndListView = CreateWindow(WC_LISTVIEW, L"", WS_CHILD | WS_BORDER | LVS_REPORT | LVS_SHOWSELALWAYS | WS_VISIBLE, 0, 0,800, 280, hWndTabCtrl , NULL, hInstance, NULL);

//Now insert two columns:
LVCOLUMN column;
column.mask = LVCF_WIDTH | LVCF_TEXT;
column.cx = 200;
column.pszText = L"Column 0";
ListView_InsertColumn(hWndListView , 0, &column); //column for sub item 0
column.pszText = L"Column 1";
ListView_InsertColumn(hWndListView , 1, &column); //column for sub item 1

现在,我想更改子项目1的文本颜色。

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message){
        case WM_NOTIFY:
            if (((LPNMHDR)lParam)->hwndFrom == hWndListView && ((LPNMHDR)lParam)->code == NM_CUSTOMDRAW){

                LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW)lParam;

                switch (lplvcd->nmcd.dwDrawStage){
                    case CDDS_PREPAINT:
                        //I can receive this value 
                        return CDRF_NOTIFYITEMDRAW;
                        break;
                    case CDDS_ITEMPREPAINT:
                        //I cann't receive this value:
                        return CDRF_NOTIFYSUBITEMDRAW;
                        break;
                    case CDDS_SUBITEM | CDDS_ITEMPREPAINT:
                        //I cann't receive this value:
                        lplvcd->clrText = RGB(255,0, 0);
                        return CDRF_NEWFONT;
                        break;
                }
                return CDRF_DODEFAULT;
            }
            break;
        case ...
            ...
            break;
    default:
    return DefFrameProc(hWnd, hWndMainFrame, message, wParam, lParam);

    }
}

在WM_NOTIFY代码块的情况下,我只能接收一次lplvcd-> nmcd.dwDrawStage,其值为CDDS_PREPAINT。 我相信这是因为返回值CDRF_NOTIFYITEMDRAW未返回正确的“父级”。

是TabCtrl的问题还是MDI窗口的问题?

尽管文档中有说明,但返回值实际上是位掩码,因此您可以一次返回多个值。 同样, dwDrawingStage也是位掩码,因此您应该在寻找感兴趣的特定位。

尝试更多类似这样的方法:

LPNMHDR pnmhdr = (LPNMHDR) lParam;
if ((pnmhdr->hwndFrom == hWndListView) && (pnmhdr->code == NM_CUSTOMDRAW))
{
    LPNMLVCUSTOMDRAW lplvcd = (LPNMLVCUSTOMDRAW) lParam;

    if (lplvcd->nmcd.dwDrawStage & CDDS_ITEM)
    {
        if (lplvcd->nmcd.dwDrawStage & CDDS_ITEMPREPAINT)
        {
            if (lplvcd->nmcd.dwDrawStage & CDDS_SUBITEM)
            {
                lplvcd->clrText = RGB(255,0, 0);
                ...
                return CDRF_DODEFAULT | CDRF_NEWFONT;
            }
            else
            {
                ...
                return CDRF_DODEFAULT | CDRF_NOTIFYSUBITEMDRAW;
            }
        }
        ...
    }
    else
    {
        switch (lplvcd->nmcd.dwDrawStage)
        {
            case CDDS_PREPAINT:
            {
                ...
                return CDRF_NOTIFYITEMDRAW | CDRF_NOTIFYSUBITEMDRAW;
            }
            ...
        }
    }
    return CDRF_DODEFAULT;
}

我有一个类似的问题(对话框中的ListView),但有一个共同因素:没有MFC。 结果相同:接收CDDS_PREPAINT,但不接收CDDS_ITEMPREPAINT或其组合(CDDS_SUBITEM | CDDS_PREPAINT和CDDS_ITEM | CDDS_SUBITEM | CDDS_PREPAINT)。 经过3天的挖掘,我在https://www.codeproject.com/Articles/2890/Using-ListView-control-under-Win-API中找到了答案。

在我的DialogProc中,我将NM_CUSTOMDRAW的结果返回给WM_NOTIFY,如下所示:

    case WM_NOTIFY:
        NMHDR* pHdr = (NMHDR*) lParam;
        if (pHdr->idFrom == IDC_LIST_RESULTS  &&  pHdr->code == NM_CUSTOMDRAW)
        {
            return HandleCustomDraw((NMLVCUSTOMDRAW*)pHdr);
        }
        break;

但是正确的行为是将结果发送给所有者:

    case WM_NOTIFY:
        NMHDR* pHdr = (NMHDR*) lParam;
        if (pHdr->idFrom == IDC_LIST_RESULTS  &&  pHdr->code == NM_CUSTOMDRAW)
        {
            SetWindowLong(hDlg, DWL_MSGRESULT, (LONG)HandleCustomDraw((NMLVCUSTOMDRAW*)pHdr));
            return TRUE;
        }
        break;

希望能帮助到你!

编辑:当然,现在我在另一个stackoverflow问题中已经找到了相同的答案:-) 虚拟列表视图未获取CDDS_ITEMPREPAINT c ++

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM