解决方案 »

  1.   

    一开始发错了板块,在C++板块开的贴,那里是100分,如果各位大神能解决,只要在那个贴回复,就给分
    http://bbs.csdn.net/topics/390950247
      

  2.   

    哎,这个现在可以不用重绘了,使用CMFCListCtrl类派生一下就搞定,你只需要管理数据就行了。比如
    // CMyListCtrlclass CMyListCtrl : public CMFCListCtrl
    {
    DECLARE_DYNAMIC(CMyListCtrl)public:
    CMyListCtrl();
    virtual ~CMyListCtrl();protected:
    DECLARE_MESSAGE_MAP() /*通过虚函数可修改表的行、列的颜色和字体*/
    virtual COLORREF OnGetCellBkColor(int nRow, int nColum); // 修改背景色
    virtual COLORREF OnGetCellTextColor(int nRow, int nColum); // 修改文本色
    virtual HFONT OnGetCellFont(int nRow, int nColum, DWORD dwData = 0); // 修改字体
    // 排序处理
    virtual int OnCompareItems(LPARAM lParam1, LPARAM lParam2, int iColumn);
    private:
    // 背景灰状态数组
      

  3.   


    多谢了,热心的大侠,小弟刚毕业,从0开始接触MFC,老大把这工程给我的时候就是要我改背景颜色,调列表的顺序,改着改着问题就来了,但一个个都解决了,就这个问题是真不知道咋办,在网上也没找到解决的办法,就只能在这发帖求助下了,你的方法对于我来说不太实用,相当于重新开始编这个工程,牵扯面太大了。不过还是很感谢,因为起码知道还有CMFCListCtrl这个类我就想让大侠们分析一下,看可能是哪出了问题。对于这个工程,自绘的函数啥的我真的都没改过,真只改了修改颜色的地方,哎,都是以前的代码,偏偏在我这出了问题,不过出问题也好,能学到东西,但是得在能解决的前提下,大侠们,救命啊
      

  4.   

    滚动就是ListCtrl自带的啊,超过页面显示就会出来,都没碰过那些代码
      

  5.   

    没有...列宽到时设置了,因为有的数据太长,所以会动态更据数据的长度设置列宽。还设置了字体,可以增大或减小,那个行高会更具字体大小变化.......其实那个发送重绘消息的函数为啥要这么写,我也一直不太懂if( GetSubItemRect( item, refrectsubitem, LVIR_LABEL, rect )==TRUE )
                        {   
                            rect.left++ ;  //这四句为啥要改位置呢
                            rect.right-- ;
                            rect.top++ ;
                            rect.bottom-- ;
                            InvalidateRect( rect, FALSE );  // only update subitem, no need clear bgn.
                        }我把那4句++,-- 的代码注释掉后,发现没出现那个错误了,现在在测试,不知道这次自己蒙的对不对,不明白为啥会这样
      

  6.   

    没有...列宽到时设置了,因为有的数据太长,所以会动态更据数据的长度设置列宽。还设置了字体,可以增大或减小,那个行高会更具字体大小变化.......其实那个发送重绘消息的函数为啥要这么写,我也一直不太懂if( GetSubItemRect( item, refrectsubitem, LVIR_LABEL, rect )==TRUE )
                        {   
                            rect.left++ ;  //这四句为啥要改位置呢
                            rect.right-- ;
                            rect.top++ ;
                            rect.bottom-- ;
                            InvalidateRect( rect, FALSE );  // only update subitem, no need clear bgn.
                        }我把那4句++,-- 的代码注释掉后,发现没出现那个错误了,现在在测试,不知道这次自己蒙的对不对,不明白为啥会这样
    那4句的意思是想将位置向左向下移动1位。
      

  7.   

    没有...列宽到时设置了,因为有的数据太长,所以会动态更据数据的长度设置列宽。还设置了字体,可以增大或减小,那个行高会更具字体大小变化.......其实那个发送重绘消息的函数为啥要这么写,我也一直不太懂if( GetSubItemRect( item, refrectsubitem, LVIR_LABEL, rect )==TRUE )
                        {   
                            rect.left++ ;  //这四句为啥要改位置呢
                            rect.right-- ;
                            rect.top++ ;
                            rect.bottom-- ;
                            InvalidateRect( rect, FALSE );  // only update subitem, no need clear bgn.
                        }我把那4句++,-- 的代码注释掉后,发现没出现那个错误了,现在在测试,不知道这次自己蒙的对不对,不明白为啥会这样
    那4句的意思是想将位置向左向下移动1位。
    哦,那问题还是会有,看来不是这里的错
      

  8.   

    是不是 head 绘制问题 ?
      

  9.   

    void ClistctrlOptions::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) //设置item大小尺寸
    {
    CDC *pDC = GetDC();
    if(pDC==NULL)
    return;
    CFont *pFont = GetFont();
    CFont *pOldFont = pDC->SelectObject(pFont);
    CSize sz = pDC->GetTextExtent("A0");
    pDC->SelectObject(pOldFont);
    lpMeasureItemStruct->itemHeight = sz.cy ;
    ReleaseDC(pDC);

    CListCtrl::OnMeasureItem(lpMeasureItemStruct->CtlID, lpMeasureItemStruct);
    }
      

  10.   

    "是不是 head 绘制问题 ?"
    listctrl 中的 head 是另一个 控件,不是listctrl 自绘的
      

  11.   

    int nCollumn = GetHeaderCtrl()->GetItemCount();//列数
    for (int i = 0; i < GetHeaderCtrl()->GetItemCount(); i++) 
    { //循环得到文本 
    CRect rcItem; 
    if ( !GetSubItemRect(lpMeasureItemStruct->itemID, i,LVIR_LABEL, rcItem )) 
    continue; 
    szText = GetItemText( lpMeasureItemStruct->itemID, i );
    rcItem.left += 5; rcItem.right -= 1; 
        pDC->DrawText(szText, lstrlen(szText), &rcItem, DT_CENTER|DT_LEFT| DT_VCENTER | DT_NOPREFIX | DT_SINGLELINE);
    }
      

  12.   

    使用成员函数试试 // 第0行可见
    EnsureVisible(0,false);
      

  13.   

    这个我知道,CHeadCtrl是我自己重绘的,代码是我自己写的,这个ListCtrl需要三种底色,本来只有白色一种,我自己重绘另外两种,一种黑色,一种就是上面那三色交替的那种
    void CHeaderCtrlCl::OnPaint()
    {
    int nColorMode = m_plist->m_nColorMode;  //0:白色   1:黑色   2:彩色

    if( nColorMode == 0 )  //白色模式
    {
    CPaintDC dc(this); // device context for painting
    // TODO: 在此处添加消息处理程序代码
    // 不为绘图消息调用 CHeaderCtrl::OnPaint()
    int nItem; 
    nItem = GetItemCount();//得到有几个单元 
    for(int i = 0; i<nItem;i ++) 


    CRect tRect;
    GetItemRect(i,&tRect);//得到Item的尺寸

    CRect nRect(tRect);//拷贝尺寸到新的容器中 
    nRect.left++;//留出分割线的地方 
    //绘制立体背景 
    for(int j = tRect.top;j<=tRect.bottom;j++) 

    nRect.bottom = nRect.top+1; 
    CBrush _brush; 
    //AfxMessageBox("asdasdsada");
    _brush.CreateSolidBrush(RGB(225,225,225));//创建画刷 
    dc.FillRect(&nRect,&_brush); //填充背景 
    _brush.DeleteObject(); //释放画刷 
    nRect.top = nRect.bottom; 


    dc.SetBkMode(TRANSPARENT); //DrawText函数的输出方式为透明的
    CFont nFont ,* nOldFont; 

    dc.SetTextColor(RGB(0,0,0));
    nFont.CreateFont(15,0,0,0,0,FALSE,FALSE,0,0,0,0,0,0,_TEXT("宋体"));//创建字体 
    nOldFont = dc.SelectObject(&nFont);

    UINT nFormat = 1;

    TEXTMETRIC metric;
    dc.GetTextMetrics(&metric);
    int ofst = 0;
    ofst = tRect.Height() - metric.tmHeight;
    tRect.OffsetRect(0,ofst/2);
    dc.DrawText(this->m_HChar[i],&tRect,nFormat);
    dc.SelectObject(nOldFont); 
    nFont.DeleteObject(); //释放字体 

    }
        else if  黑色;
        else  三色交替;}
      

  14.   


    多谢大侠指点啊,这个函数让我对另外一个问题有了思路....................我昨天捣鼓一天的软件做测试,终于发现了引发这个错误的诱因,只是诱因,具体在代码里哪出问题还不知道................这个页面的属性可以设置为  有边框   和 无边框,在打开新页面时(只能是新页面,进行了其他操作的都不行),我将第一行滚动到不可见,在从当前属性切换到另一属性(从 有边框->无边框 或者 相反,取决于打开时页的初始属性),就会出现那个错误了,往上滚动到最顶端时,第一行就会显示不全,有一部分是在可是区域以外的,当点击第一行时,因为显示不全就会发生滚动,使ListCtrl往上滚动了一个行高的位移,所以就会有条缝隙,这缝隙的大小取决于第一行隐藏区域的大小,隐藏的越大,缝隙越小,反之亦然。切换属性时页面的大小不会变,因为边框会占空间,所以从无边框->有边框时ListCtrl显示的数据会变少,反之亦然.....无边框
    有边框
    我想就是因为这显示的行数发生了变化,从而使之产生了错误测试:
    打开一个新页面,初始为有边框,将第一行滚动至不可见
    切换属性到无边框,此时页面显示的最顶上一行已经是显示不全的了
    滚动到真正的第一行,行使价=10000,此时第一行也是显示不全的
    点击第一行,缝隙就出来了
      

  15.   


    大侠,我使用这个函数,将它放在重绘里,不管第二个参数是FALSE还是TRUE,永远显示在第一行
    void ClistctrlOptions::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)  //重绘函数
    {
    //测试测试
    this->EnsureVisible(0,TRUE);
    /////////////////////////////////////////////
            .
            .
            .
    }
      

  16.   


    大侠,我使用这个函数,将它放在重绘里,不管第二个参数是FALSE还是TRUE,永远显示在第一行
    void ClistctrlOptions::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)  //重绘函数
    {
    //测试测试
    this->EnsureVisible(0,TRUE);
    /////////////////////////////////////////////
            .
            .
            .
    }

    你要判断一下动作,当item=0时执行此函数
      

  17.   


    应该是的吧,起初自己重绘的时候,会出现自绘的网格与ListCtrl自带的网格错位的现象,那时我也找不到哪错了,所以我用下面那代码将ListCtrl自带的网格属性去掉了ListView_SetExtendedListViewStyle(this->m_hWnd, this->GetStyle() & ~LVS_EX_GRIDLINES);
    现在我将这属性又加回去了,测试了一下,引发这两个错误的诱因是一样的,都是自绘时Item的位置计算错误,与ListCtrl默认的Item位置不同测试
    正常情况下,黑色背景时,自绘的Item位置和ListCtrl默认的位置重合在一起(可能看起来不好看,但这都是表象,别见怪)
    出错后,自绘Item的位置比ListCtrl默认的位置要往上一点,自绘的网格线是很暗的那种,ListCtrl自带的网格线很亮,看数据的位置也能看出来
    可我也不知道哪个地方的参数出错了呀..............................
      

  18.   

    给你说了, listctrl 的 customdraw 只 是 list 部分, 不包括  head。
      

  19.   


    多谢大侠指点啊,这个函数让我对另外一个问题有了思路....................我昨天捣鼓一天的软件做测试,终于发现了引发这个错误的诱因,只是诱因,具体在代码里哪出问题还不知道................这个页面的属性可以设置为  有边框   和 无边框,在打开新页面时(只能是新页面,进行了其他操作的都不行),我将第一行滚动到不可见,在从当前属性切换到另一属性(从 有边框->无边框 或者 相反,取决于打开时页的初始属性),就会出现那个错误了,往上滚动到最顶端时,第一行就会显示不全,有一部分是在可是区域以外的,当点击第一行时,因为显示不全就会发生滚动,使ListCtrl往上滚动了一个行高的位移,所以就会有条缝隙,这缝隙的大小取决于第一行隐藏区域的大小,隐藏的越大,缝隙越小,反之亦然。切换属性时页面的大小不会变,因为边框会占空间,所以从无边框->有边框时ListCtrl显示的数据会变少,反之亦然.....无边框
    有边框
    我想就是因为这显示的行数发生了变化,从而使之产生了错误测试:
    打开一个新页面,初始为有边框,将第一行滚动至不可见
    切换属性到无边框,此时页面显示的最顶上一行已经是显示不全的了
    滚动到真正的第一行,行使价=10000,此时第一行也是显示不全的
    点击第一行,缝隙就出来了根据我20L介绍的诱因,我在代码的重绘函数,DrawItem函数中,增加代码,这段代码只执行一次,也就是在程序中只有第一次重绘才会执行,后面再进入重绘函数都不执行。这段代码的意思就是,获得ListCtrl位置,再用movewindow移动到这个位置,那个错误就不会发生了。写程序就是这样,有时根本找不到原因,但是避开引发的诱因也能解决问题,但是,这还是没从根源解决,所谓治标不治本,后面还有没有这样的错误,就只能听天由命了
    结贴