【问题标题】:How to refresh the part below the items of istview/treeview?如何刷新listview/treeview项目下方的部分?
【发布时间】:2021-03-25 06:55:46
【问题描述】:

我在做什么

问题的倾向可能不清楚。我会做更多的描述。

当您尝试重绘WC_TREEVIEW 控件时,您可能需要注意它的父窗口消息WM_NOTIFY

可能是这样编码的:

case WM_NOTIFY: {
    UINT ctrl_id = wParam;
    LPNMHDR pnmh = (LPNMHDR)lParam;
    HWND ctrl_hwnd = pnmh->hwndFrom;
    char class_name[256] = "";
    LRESULT result;
            
    GetClassName(ctrl_hwnd,class_name,sizeof(class_name));
    if(strstr(class_name,WC_TREEVIEW)) {
        LPNMTREEVIEW item = (LPNMTREEVIEW)pnmh;

        if(item->hdr.code == NM_CUSTOMDRAW) {
            //...Do your item drawing
            return result;
        }
    }
    //....
} break;

参数NMTREEVIEW 包含更新特定项目区域所需的所有必要信息。 我的第一个问题是结构成员NMTVCUSTOMDRAW::nmcd::dwDrawStage 的含义。 MSDN说了很多,我没有理想。 我的编码是这样的,如果不对请纠正我。谢谢。


//My drawing of treeview item.
{
    LPNMTVCUSTOMDRAW cust_draw = (LPNMTVCUSTOMDRAW)lParam;
    RECT rect;
    HDC hdc;
    TVHITTESTINFO tv_hit;
    TVITEM tv_item;
    HTREEITEM item;
    char item_text[1024] = "";
    int step_level=cust_draw->iLevel;
    
    hdc = cust_draw->nmcd.hdc;
    CopyRect(&rect,&(cust_draw->nmcd.rc));
    tv_hit.pt = {(rect.left+rect.right)/2,(rect.top+rect.bottom)/2};
    
    if(cust_draw->nmcd.dwDrawStage==CDDS_PREPAINT) {
        return CDRF_NOTIFYITEMDRAW;
    }
    else if(cust_draw->nmcd.dwDrawStage == CDDS_ITEMPREPAINT) {
        item = TreeView_HitTest(hwnd,&tv_hit);
        if(item) {
            tv_item.mask = TVIF_TEXT|TVIF_STATE|TVIF_CHILDREN;
            tv_item.hItem = item;
            tv_item.pszText = item_text;
            tv_item.cchTextMax = sizeof(item_text);
            TreeView_GetItem(hwnd,&tv_item);
            MyTreeItemDrawing(hwnd,hdc,rect,step_level,&tv_item);
        } 
        return CDRF_SKIPDEFAULT;              
    }
    return CDRF_SKIPDEFAULT;
}

我的问题是什么

所有这些都已完成。然后,当您调整支架窗口大小时,您会发现一些变细。 我使树视图控件根据其容器窗口的大小自动调整大小。 现在如果我直接阻止WM_ERASEBKGND返回非零,它会以某种方式减少闪烁。

case WM_ERASEBKGND: return 1;
break;

但是,如果树状视图​​项目没有占据整个客户区,则未被树状视图项目占据的其余部分将无法正确刷新。 那是我的问题。Treeview 刷新它的背景和项目导致闪烁。我应该怎么做才能解决这个问题?

现在,当我重绘 WC_LISTVIEW 控件时,这对我来说是一个常见问题。它还提供WM_DRAWITEM 来重写项目。 同样的闪烁问题。

【问题讨论】:

  • 很抱歉,我无法构建项目并根据您的描述重现问题,您能否在没有私人信息的情况下显示a minimal, reproducible sample
  • @SongZhu-MSFT 加油,你又来了。这是一个链接link,你是中国人吧?我对git做了一些描述。希望能在更正式的地方进行一些讨论。
  • 我根据你的代码建了项目,但是当窗口调整大小时,没有闪烁。但是有些图没有被擦除,如果我在WM_ERASEBKGND返回0,一切正常。你能详细描述一下你的问题吗?
  • 我不想使用默认的擦除背景方法。它有一个问题,当你包裹了很多层时,我的意思是树视图控件有父窗口 A,A 有父窗口 B 等等。如果使用默认的擦除背景程序(返回零),就会出现闪烁。
  • 也许你可以添加一些截图或gif来描述当前的现象和你期望的效果。

标签: windows winforms winapi


【解决方案1】:

窗口样式 WS_CLIPCHILDREN 可以工作。 容器窗口应该应用这种样式以避免控制区域的双重刷新。这样就可以保持WM_ERASEBKGND,并且没有闪烁。

【讨论】:

    猜你喜欢
    • 2012-09-09
    • 1970-01-01
    • 2019-04-24
    • 2012-09-21
    • 2019-10-28
    • 2011-08-11
    • 2014-02-14
    • 1970-01-01
    • 2017-06-02
    相关资源
    最近更新 更多