一个重载OnPaint(),引起不断触发消息,导致控件不断重画的问题。

mailghost 2004-11-25 01:48:46
在一个窗口中写入字符串时,在另一窗口中的List Control中动态添加项,并把字符串显示出来。
我是在要显示字符的窗口的OnPaint()函数中来做的:
PaintFlag =false;
MyDATASTR *hCurData = pDoc->GetCurrentData();//获得要添加显示的数据
if(hCurData==NULL)
return ;
m_List.DeleteAllItems();//先将ListCtrl控件原有项全部清除
for(int i=0; i<pCurData->Num;i++)//重新循环添加项
{
CString rect;
CString str;
int listcount=m_List.GetItemCount();//
str.Format("%d",listcount);
rect.Format("%d%s%s%",pCurData->BlkItem[i].Num,"currentdata",pCurData->String);
m_List.InsertItem(listcount,str);
m_List.SetItem(listcount,1,LVIF_TEXT,rect,0, LVIS_SELECTED, LVIS_SELECTED, 0);
}
}
现在的问题是当我添加项到一定数目,通常是3-5项时,list control 控件滚动条会不断翻滚,控件显示数据区域也不断翻滚。用spy看到不断重复触发消息,特别是WM_NCPAINT消息多次重复触发,它每次重复触发,又会触发控件自身的翻滚消息。
我知道问题处在OnPaint()时删除和重新添加控件项操作,消息响应处理有问题,但又找不到更好的处理办法。
请问:有什么好方法,能过解决吗?
急切盼望中。。。。。。




...全文
313 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
iamzxx 2004-11-26
  • 打赏
  • 举报
回复
我不知道是什么原因在调用m_List.DeleteAllItems();就会出现这种问题//
但我找到了解决办法,就是在他后面加上 m_List.Updata(0)就行了,请高手指点下引起的
内在原因.
aoosang 2004-11-26
  • 打赏
  • 举报
回复
我知道了,你用的show和hide窗口的方法来回的切换窗口,我说个方法你看可行不?
1 在这个窗口类中定义一个方法,用来实现刷新list如下
void freshlist()
{
m_List.DeleteAllItems();//先将ListCtrl控件原有项全部清除
for(int i=0; i<pCurData->Num;i++)//重新循环添加项
{
CString rect;
CString str;
int listcount=m_List.GetItemCount();//
str.Format("%d",listcount);
rect.Format("%d%s%s%",pCurData->BlkItem[i].Num,"currentdata",pCurData->String);
m_List.InsertItem(listcount,str);
m_List.SetItem(listcount,1,LVIF_TEXT,rect,0, LVIS_SELECTED, LVIS_SELECTED, 0);
}
}

}
2 在显示这个窗口的时候,也就是调用ShowWindow(SW_show)之前,你调用上面的方法,showwindow会自动引发窗口onpaint的。下面的问题就是如果你的窗口不切换时,如何定时的更新(不知道是否需要,如果需要,设置个定时器吧)
3 一个问题和你探讨
我看你是每次添加一个item,你有必要将所有的item都删除然后重新生成吗?个人认为
每次添加直接调用m_List.InsertItem()即可,最多在每次调用m_List.InsertItem()后调用一下
m_List.Invalidate(),让list自己重新绘制就是了,
不知方法是否可行,你试一下吧,也许对你的意思领会的不对
mailghost 2004-11-26
  • 打赏
  • 举报
回复
to: lsgt()
重建ListCtrl ?你这是什么含义?控件动态创建?

lsgt 2004-11-25
  • 打赏
  • 举报
回复
不要这么做。

你可以在数据改变的时候重设ListCtrl.

如果你实在要那么做,那就加一个标志,表示数据有没有变化,如果有变化才重建ListCtrl。在数据改变的时候设置这个标志,重建ListCtrl之后恢复这个标志
mailghost 2004-11-25
  • 打赏
  • 举报
回复
to: lzzqqq(Jonersen,aoosang(智慧的鱼) ,lsgt()
你们说的都是正确的。我在OnPaint()中添加代码的目的在二楼帖子都已说了。因为这个窗口
可能会不时被切换,隐藏后,要显示数据可能改变。而这个隐藏窗口是静态创建的,所以每次重新
显示时,要重新取数据,重新显示。
lsgt 2004-11-25
  • 打赏
  • 举报
回复
InsertItem等之后,ListCtrl显示需要的数据已经保存在ListCtrl中了(Virtual mode除外),重绘的时候不需要删掉重来。只在数据改变的时候重设ListCtrl就好了。
aoosang 2004-11-25
  • 打赏
  • 举报
回复
一般来说如果你对控件操作的话,控件窗体自己都会重绘,所以你根本不用将代码写到onpaint里,这样,你的屏幕闪的太厉害,如果你在list里添加一项时,如果控件没有重绘,你可以调用list.Invalidate();方法,让控件自己重绘,建议将你的这段代码放到OnInitDialog()里,这样每次对话框初始化的时候就能够显示
lzzqqq 2004-11-25
  • 打赏
  • 举报
回复
严重反对放在OnPaint()中!!!
应该在你的输入控件中的PrepareTranslateMessage()中拦截
WM_KEYUP/WM_KEYDOWN/WM_PASTE等消息,然后得到输入数据,再插入CListCtrl
mailghost 2004-11-25
  • 打赏
  • 举报
回复
up
mailghost 2004-11-25
  • 打赏
  • 举报
回复
to: DentistryDoctor(雅克医生<改行做程序员了>) :
我试过将对listctrl的操作写到另一函数中,但是在OnPaint()中调用,还是会不断触发消息。
只是多了点堆栈操作而已。


DentistryDoctor 2004-11-25
  • 打赏
  • 举报
回复
m_List.SetRedraw(FALSE);
...
m_List.SetRedraw(TRUE);
DentistryDoctor 2004-11-25
  • 打赏
  • 举报
回复
这些代码怎么写在OnPaint中了。
mailghost 2004-11-25
  • 打赏
  • 举报
回复
因为这个窗口可能会不断切换,要实时更新控件显示的数据。也就是说当listctrl
所在的窗口隐藏后,重新显示出来时,需要重新显示listctrl中的数据(也许隐藏时,要显示的数据改变了)。
有什么好方法,避免这种消息重发的情况吗?急切盼望中!

lsgt 2004-11-25
  • 打赏
  • 举报
回复
为什么要在OnPaint中做呢.添加完数据立即更新ListCtrl不行吗

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧