CListCtrl的问题啊,大神门,带我飞啊 MFC,CListCtrl 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 一开始发错了板块,在C++板块开的贴,那里是100分,如果各位大神能解决,只要在那个贴回复,就给分http://bbs.csdn.net/topics/390950247 哎,这个现在可以不用重绘了,使用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: // 背景灰状态数组 多谢了,热心的大侠,小弟刚毕业,从0开始接触MFC,老大把这工程给我的时候就是要我改背景颜色,调列表的顺序,改着改着问题就来了,但一个个都解决了,就这个问题是真不知道咋办,在网上也没找到解决的办法,就只能在这发帖求助下了,你的方法对于我来说不太实用,相当于重新开始编这个工程,牵扯面太大了。不过还是很感谢,因为起码知道还有CMFCListCtrl这个类我就想让大侠们分析一下,看可能是哪出了问题。对于这个工程,自绘的函数啥的我真的都没改过,真只改了修改颜色的地方,哎,都是以前的代码,偏偏在我这出了问题,不过出问题也好,能学到东西,但是得在能解决的前提下,大侠们,救命啊 滚动就是ListCtrl自带的啊,超过页面显示就会出来,都没碰过那些代码 没有...列宽到时设置了,因为有的数据太长,所以会动态更据数据的长度设置列宽。还设置了字体,可以增大或减小,那个行高会更具字体大小变化.......其实那个发送重绘消息的函数为啥要这么写,我也一直不太懂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句++,-- 的代码注释掉后,发现没出现那个错误了,现在在测试,不知道这次自己蒙的对不对,不明白为啥会这样 没有...列宽到时设置了,因为有的数据太长,所以会动态更据数据的长度设置列宽。还设置了字体,可以增大或减小,那个行高会更具字体大小变化.......其实那个发送重绘消息的函数为啥要这么写,我也一直不太懂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位。 没有...列宽到时设置了,因为有的数据太长,所以会动态更据数据的长度设置列宽。还设置了字体,可以增大或减小,那个行高会更具字体大小变化.......其实那个发送重绘消息的函数为啥要这么写,我也一直不太懂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位。哦,那问题还是会有,看来不是这里的错 是不是 head 绘制问题 ? 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);} "是不是 head 绘制问题 ?"listctrl 中的 head 是另一个 控件,不是listctrl 自绘的 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); } 使用成员函数试试 // 第0行可见 EnsureVisible(0,false); 这个我知道,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 三色交替;} 多谢大侠指点啊,这个函数让我对另外一个问题有了思路....................我昨天捣鼓一天的软件做测试,终于发现了引发这个错误的诱因,只是诱因,具体在代码里哪出问题还不知道................这个页面的属性可以设置为 有边框 和 无边框,在打开新页面时(只能是新页面,进行了其他操作的都不行),我将第一行滚动到不可见,在从当前属性切换到另一属性(从 有边框->无边框 或者 相反,取决于打开时页的初始属性),就会出现那个错误了,往上滚动到最顶端时,第一行就会显示不全,有一部分是在可是区域以外的,当点击第一行时,因为显示不全就会发生滚动,使ListCtrl往上滚动了一个行高的位移,所以就会有条缝隙,这缝隙的大小取决于第一行隐藏区域的大小,隐藏的越大,缝隙越小,反之亦然。切换属性时页面的大小不会变,因为边框会占空间,所以从无边框->有边框时ListCtrl显示的数据会变少,反之亦然.....无边框有边框我想就是因为这显示的行数发生了变化,从而使之产生了错误测试:打开一个新页面,初始为有边框,将第一行滚动至不可见切换属性到无边框,此时页面显示的最顶上一行已经是显示不全的了滚动到真正的第一行,行使价=10000,此时第一行也是显示不全的点击第一行,缝隙就出来了 大侠,我使用这个函数,将它放在重绘里,不管第二个参数是FALSE还是TRUE,永远显示在第一行void ClistctrlOptions::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) //重绘函数{ //测试测试 this->EnsureVisible(0,TRUE); ///////////////////////////////////////////// . . .} 大侠,我使用这个函数,将它放在重绘里,不管第二个参数是FALSE还是TRUE,永远显示在第一行void ClistctrlOptions::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) //重绘函数{ //测试测试 this->EnsureVisible(0,TRUE); ///////////////////////////////////////////// . . .}你要判断一下动作,当item=0时执行此函数 应该是的吧,起初自己重绘的时候,会出现自绘的网格与ListCtrl自带的网格错位的现象,那时我也找不到哪错了,所以我用下面那代码将ListCtrl自带的网格属性去掉了ListView_SetExtendedListViewStyle(this->m_hWnd, this->GetStyle() & ~LVS_EX_GRIDLINES);现在我将这属性又加回去了,测试了一下,引发这两个错误的诱因是一样的,都是自绘时Item的位置计算错误,与ListCtrl默认的Item位置不同测试正常情况下,黑色背景时,自绘的Item位置和ListCtrl默认的位置重合在一起(可能看起来不好看,但这都是表象,别见怪)出错后,自绘Item的位置比ListCtrl默认的位置要往上一点,自绘的网格线是很暗的那种,ListCtrl自带的网格线很亮,看数据的位置也能看出来可我也不知道哪个地方的参数出错了呀.............................. 给你说了, listctrl 的 customdraw 只 是 list 部分, 不包括 head。 多谢大侠指点啊,这个函数让我对另外一个问题有了思路....................我昨天捣鼓一天的软件做测试,终于发现了引发这个错误的诱因,只是诱因,具体在代码里哪出问题还不知道................这个页面的属性可以设置为 有边框 和 无边框,在打开新页面时(只能是新页面,进行了其他操作的都不行),我将第一行滚动到不可见,在从当前属性切换到另一属性(从 有边框->无边框 或者 相反,取决于打开时页的初始属性),就会出现那个错误了,往上滚动到最顶端时,第一行就会显示不全,有一部分是在可是区域以外的,当点击第一行时,因为显示不全就会发生滚动,使ListCtrl往上滚动了一个行高的位移,所以就会有条缝隙,这缝隙的大小取决于第一行隐藏区域的大小,隐藏的越大,缝隙越小,反之亦然。切换属性时页面的大小不会变,因为边框会占空间,所以从无边框->有边框时ListCtrl显示的数据会变少,反之亦然.....无边框有边框我想就是因为这显示的行数发生了变化,从而使之产生了错误测试:打开一个新页面,初始为有边框,将第一行滚动至不可见切换属性到无边框,此时页面显示的最顶上一行已经是显示不全的了滚动到真正的第一行,行使价=10000,此时第一行也是显示不全的点击第一行,缝隙就出来了根据我20L介绍的诱因,我在代码的重绘函数,DrawItem函数中,增加代码,这段代码只执行一次,也就是在程序中只有第一次重绘才会执行,后面再进入重绘函数都不执行。这段代码的意思就是,获得ListCtrl位置,再用movewindow移动到这个位置,那个错误就不会发生了。写程序就是这样,有时根本找不到原因,但是避开引发的诱因也能解决问题,但是,这还是没从根源解决,所谓治标不治本,后面还有没有这样的错误,就只能听天由命了结贴 VC6.0中如何确定CString转化为COleDateTime是否正确? 关于ListView添加内容(不要MFC!!) 消息框和窗体显示顺序 有高手做过这样的项目吗? CListCtrl 已经设置为LVS_EX_GRIDLINES格式,在最后添加一行时,如何向下滚动? 如何把输入的文字转化为声音? 调试问题(毕业设计) new与delete使用的问题 电脑怎么做围棋死活题?写出代码加分! 想各位高手请教一个问题? 江湖告急:求一个可以屏蔽其他功能的“超级”弹出框 Socket显示接受数据问题
http://bbs.csdn.net/topics/390950247
// 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:
// 背景灰状态数组
多谢了,热心的大侠,小弟刚毕业,从0开始接触MFC,老大把这工程给我的时候就是要我改背景颜色,调列表的顺序,改着改着问题就来了,但一个个都解决了,就这个问题是真不知道咋办,在网上也没找到解决的办法,就只能在这发帖求助下了,你的方法对于我来说不太实用,相当于重新开始编这个工程,牵扯面太大了。不过还是很感谢,因为起码知道还有CMFCListCtrl这个类我就想让大侠们分析一下,看可能是哪出了问题。对于这个工程,自绘的函数啥的我真的都没改过,真只改了修改颜色的地方,哎,都是以前的代码,偏偏在我这出了问题,不过出问题也好,能学到东西,但是得在能解决的前提下,大侠们,救命啊
{
rect.left++ ; //这四句为啥要改位置呢
rect.right-- ;
rect.top++ ;
rect.bottom-- ;
InvalidateRect( rect, FALSE ); // only update subitem, no need clear bgn.
}我把那4句++,-- 的代码注释掉后,发现没出现那个错误了,现在在测试,不知道这次自己蒙的对不对,不明白为啥会这样
{
rect.left++ ; //这四句为啥要改位置呢
rect.right-- ;
rect.top++ ;
rect.bottom-- ;
InvalidateRect( rect, FALSE ); // only update subitem, no need clear bgn.
}我把那4句++,-- 的代码注释掉后,发现没出现那个错误了,现在在测试,不知道这次自己蒙的对不对,不明白为啥会这样
那4句的意思是想将位置向左向下移动1位。
{
rect.left++ ; //这四句为啥要改位置呢
rect.right-- ;
rect.top++ ;
rect.bottom-- ;
InvalidateRect( rect, FALSE ); // only update subitem, no need clear bgn.
}我把那4句++,-- 的代码注释掉后,发现没出现那个错误了,现在在测试,不知道这次自己蒙的对不对,不明白为啥会这样
那4句的意思是想将位置向左向下移动1位。
哦,那问题还是会有,看来不是这里的错
{
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);
}
listctrl 中的 head 是另一个 控件,不是listctrl 自绘的
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);
}
EnsureVisible(0,false);
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 三色交替;}
多谢大侠指点啊,这个函数让我对另外一个问题有了思路....................我昨天捣鼓一天的软件做测试,终于发现了引发这个错误的诱因,只是诱因,具体在代码里哪出问题还不知道................这个页面的属性可以设置为 有边框 和 无边框,在打开新页面时(只能是新页面,进行了其他操作的都不行),我将第一行滚动到不可见,在从当前属性切换到另一属性(从 有边框->无边框 或者 相反,取决于打开时页的初始属性),就会出现那个错误了,往上滚动到最顶端时,第一行就会显示不全,有一部分是在可是区域以外的,当点击第一行时,因为显示不全就会发生滚动,使ListCtrl往上滚动了一个行高的位移,所以就会有条缝隙,这缝隙的大小取决于第一行隐藏区域的大小,隐藏的越大,缝隙越小,反之亦然。切换属性时页面的大小不会变,因为边框会占空间,所以从无边框->有边框时ListCtrl显示的数据会变少,反之亦然.....无边框
有边框
我想就是因为这显示的行数发生了变化,从而使之产生了错误测试:
打开一个新页面,初始为有边框,将第一行滚动至不可见
切换属性到无边框,此时页面显示的最顶上一行已经是显示不全的了
滚动到真正的第一行,行使价=10000,此时第一行也是显示不全的
点击第一行,缝隙就出来了
大侠,我使用这个函数,将它放在重绘里,不管第二个参数是FALSE还是TRUE,永远显示在第一行
void ClistctrlOptions::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) //重绘函数
{
//测试测试
this->EnsureVisible(0,TRUE);
/////////////////////////////////////////////
.
.
.
}
大侠,我使用这个函数,将它放在重绘里,不管第二个参数是FALSE还是TRUE,永远显示在第一行
void ClistctrlOptions::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) //重绘函数
{
//测试测试
this->EnsureVisible(0,TRUE);
/////////////////////////////////////////////
.
.
.
}
你要判断一下动作,当item=0时执行此函数
应该是的吧,起初自己重绘的时候,会出现自绘的网格与ListCtrl自带的网格错位的现象,那时我也找不到哪错了,所以我用下面那代码将ListCtrl自带的网格属性去掉了ListView_SetExtendedListViewStyle(this->m_hWnd, this->GetStyle() & ~LVS_EX_GRIDLINES);
现在我将这属性又加回去了,测试了一下,引发这两个错误的诱因是一样的,都是自绘时Item的位置计算错误,与ListCtrl默认的Item位置不同测试
正常情况下,黑色背景时,自绘的Item位置和ListCtrl默认的位置重合在一起(可能看起来不好看,但这都是表象,别见怪)
出错后,自绘Item的位置比ListCtrl默认的位置要往上一点,自绘的网格线是很暗的那种,ListCtrl自带的网格线很亮,看数据的位置也能看出来
可我也不知道哪个地方的参数出错了呀..............................
多谢大侠指点啊,这个函数让我对另外一个问题有了思路....................我昨天捣鼓一天的软件做测试,终于发现了引发这个错误的诱因,只是诱因,具体在代码里哪出问题还不知道................这个页面的属性可以设置为 有边框 和 无边框,在打开新页面时(只能是新页面,进行了其他操作的都不行),我将第一行滚动到不可见,在从当前属性切换到另一属性(从 有边框->无边框 或者 相反,取决于打开时页的初始属性),就会出现那个错误了,往上滚动到最顶端时,第一行就会显示不全,有一部分是在可是区域以外的,当点击第一行时,因为显示不全就会发生滚动,使ListCtrl往上滚动了一个行高的位移,所以就会有条缝隙,这缝隙的大小取决于第一行隐藏区域的大小,隐藏的越大,缝隙越小,反之亦然。切换属性时页面的大小不会变,因为边框会占空间,所以从无边框->有边框时ListCtrl显示的数据会变少,反之亦然.....无边框
有边框
我想就是因为这显示的行数发生了变化,从而使之产生了错误测试:
打开一个新页面,初始为有边框,将第一行滚动至不可见
切换属性到无边框,此时页面显示的最顶上一行已经是显示不全的了
滚动到真正的第一行,行使价=10000,此时第一行也是显示不全的
点击第一行,缝隙就出来了根据我20L介绍的诱因,我在代码的重绘函数,DrawItem函数中,增加代码,这段代码只执行一次,也就是在程序中只有第一次重绘才会执行,后面再进入重绘函数都不执行。这段代码的意思就是,获得ListCtrl位置,再用movewindow移动到这个位置,那个错误就不会发生了。写程序就是这样,有时根本找不到原因,但是避开引发的诱因也能解决问题,但是,这还是没从根源解决,所谓治标不治本,后面还有没有这样的错误,就只能听天由命了
结贴