写了一个监听端口程序,发现将每次收到的数据信息显示在屏幕上时,每显示一条就会刷新一下屏幕,导致在压力测试时,由于数据量大,屏幕不停的闪烁.请大家看看,有没有好的显示方式,我的显示部分是如下实现的:
void CMainFrame::InsertMsgView(CListCtrl * pListView, CReceiveMsg * pMsg)
{
CTime time; LV_ITEM lvItem;
lvItem.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_STATE;
lvItem.state=LVIS_FOCUSED|LVIS_SELECTED ;
lvItem.stateMask=LVIS_FOCUSED|LVIS_SELECTED;
lvItem.iImage=pMsg->GetDataFlag();
lvItem.iItem=0;
lvItem.iSubItem=0;
lvItem.pszText="";
pListView->InsertItem(&lvItem);
//接收时间
time=pMsg->GetReceiveTime();
pListView->SetItemText(0,1,time.Format("%Y/%m/%d %H:%M:%S"));
//终端
pListView->SetItemText(0,2,pMsg->GetTerminalID());
//卡号
// pListView->SetItemText(0,3,pMsg->GetCardID());
//流水号
pListView->SetItemText(0,3,pMsg->GetSystrace());
//票据号
pListView->SetItemText(0,4,pMsg->GetTicket());
//交易类型
pListView->SetItemText(0,5,pMsg->GetTxnType());
//交易金额
pListView->SetItemText(0,6,pMsg->GetAmt());
//交易结果
pListView->SetItemText(0,7,pMsg->GetTrans_Result());
//操作员
pListView->SetItemText(0,8,pMsg->GetOperator());
//客户机信息
pListView->SetItemText(0,9,pMsg->GetClientIP());
UINT nPort=pMsg->GetClientPort();
CString strPort;
strPort.Format("%d",nPort);
pListView->SetItemText(0,10,strPort);
//下发时间
time=pMsg->GetSendTime();
pListView->SetItemText(0,11,time.Format("%Y/%m/%d %H:%M:%S"));
//上送数据包
pListView->SetItemText(0,12,pMsg->GetReceiveData()); CDC *pDC=pListView->GetDC();
CPen pen(PS_SOLID,4,RGB(255,0,0));
pDC->SelectObject(&pen);
CRect rcLabel;
pListView->GetItemRect(2,rcLabel,LVIR_LABEL);
// CPoint point(rcLabel.left,rcLabel.bottom);
// pDC->MoveTo(point);
// pDC->LineTo(CPoint(400,300));
return ;
}
void CMainFrame::InsertMsgView(CListCtrl * pListView, CReceiveMsg * pMsg)
{
CTime time; LV_ITEM lvItem;
lvItem.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_STATE;
lvItem.state=LVIS_FOCUSED|LVIS_SELECTED ;
lvItem.stateMask=LVIS_FOCUSED|LVIS_SELECTED;
lvItem.iImage=pMsg->GetDataFlag();
lvItem.iItem=0;
lvItem.iSubItem=0;
lvItem.pszText="";
pListView->InsertItem(&lvItem);
//接收时间
time=pMsg->GetReceiveTime();
pListView->SetItemText(0,1,time.Format("%Y/%m/%d %H:%M:%S"));
//终端
pListView->SetItemText(0,2,pMsg->GetTerminalID());
//卡号
// pListView->SetItemText(0,3,pMsg->GetCardID());
//流水号
pListView->SetItemText(0,3,pMsg->GetSystrace());
//票据号
pListView->SetItemText(0,4,pMsg->GetTicket());
//交易类型
pListView->SetItemText(0,5,pMsg->GetTxnType());
//交易金额
pListView->SetItemText(0,6,pMsg->GetAmt());
//交易结果
pListView->SetItemText(0,7,pMsg->GetTrans_Result());
//操作员
pListView->SetItemText(0,8,pMsg->GetOperator());
//客户机信息
pListView->SetItemText(0,9,pMsg->GetClientIP());
UINT nPort=pMsg->GetClientPort();
CString strPort;
strPort.Format("%d",nPort);
pListView->SetItemText(0,10,strPort);
//下发时间
time=pMsg->GetSendTime();
pListView->SetItemText(0,11,time.Format("%Y/%m/%d %H:%M:%S"));
//上送数据包
pListView->SetItemText(0,12,pMsg->GetReceiveData()); CDC *pDC=pListView->GetDC();
CPen pen(PS_SOLID,4,RGB(255,0,0));
pDC->SelectObject(&pen);
CRect rcLabel;
pListView->GetItemRect(2,rcLabel,LVIR_LABEL);
// CPoint point(rcLabel.left,rcLabel.bottom);
// pDC->MoveTo(point);
// pDC->LineTo(CPoint(400,300));
return ;
}
CPen pen(PS_SOLID,4,RGB(255,0,0));
pDC->SelectObject(&pen);
CRect rcLabel;
pListView->GetItemRect(2,rcLabel,LVIR_LABEL);
你只是取得了一个ITEM的Rect,什么都没做,下面都注释了,是做什么用呢?另外记得ReleaseDC(pDC);
//更新内容
m_list.SetRedraw(TRUE);
m_list.Invalidate();
m_list.UpdateWindow();
请问一下怎么设置使它追加在最后啊, 是在lvItem里设置吗?
把0换成实际的数目即可。
非常谢谢你,我试了改成lvItem.iItem=1, 发现还是没有追加在最后啊,请问你所说的实际的数目是指什么啊?是非零吗?
lvItem.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_STATE;
lvItem.state=LVIS_FOCUSED|LVIS_SELECTED ;
lvItem.stateMask=LVIS_FOCUSED|LVIS_SELECTED;
lvItem.iImage=pMsg->GetDataFlag();
lvItem.iItem= pListView->GetItemCount() + 1;
lvItem.iSubItem=0;
lvItem.pszText="";
pListView->InsertItem(&lvItem);
pListView->SetRedraw(FALSE);
..........//插入数据
pListView->SetRedraw(TRUE);
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//可以消除闪烁,但是会有副作用,可以判断一下,在添加行的时候,return true; //其他时候呢return CListView::OnEraseBkgnd(pDC);
return TRUE;
//return CListView::OnEraseBkgnd(pDC);
}
1,增加一个private BOOL m_IsErase;并且初始化为TRUE//意思是默认擦除背景
2.在插入行的函数最开始,写m_IsErase=FALSE;//要插入行了,我不想擦除背景
3,重载OnEraseBkgndBOOL ClistboxView::OnEraseBkgnd(CDC* pDC)
{
if (m_IsErase)
{
//在需要的时候擦除背景。
return CListView::OnEraseBkgnd(pDC);
}
else
{
//再不需要的时候,比如频繁插入行的时候,本次不擦除,恢复擦除状态
m_IsErase=TRUE;
return TRUE;
}
}
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
if (m_IsErase)
{
//m_IsErase=FALSE;
return CListView::OnEraseBkgnd(pDC);
}
else
{
m_IsErase=TRUE;
GetClientRect(rc);
CListCtrl & ListCtrl=GetListCtrl();
ListCtrl.GetItemRect(0,rc2,LVIR_BOUNDS );
//擦除背景的时候,把listview中行所在区域排除,只擦除之外的区域
pDC->FillSolidRect(rc2.right,rc2.top,rc.Width()-rc2.Width(),rc.Height(),RGB(255,255,255));
return TRUE;
}
}
long litemcount=ListCtrl.GetItemCount();
CRect rc,rc2,rcLast;
GetClientRect(rc);
if (m_IsErase&&litemcount==0)
{
TRACE("OnEraseBkgnd: default\n");
//当listview被清空的时候,需要填充整个区域
pDC->FillRect(rc,&CBrush(RGB(255,255,255)));
//CListView::OnEraseBkgnd(pDC);
return TRUE;
}
else
{
m_IsErase=TRUE;
if (litemcount>0)
{
TRACE("OnEraseBkgnd: rgn%d\n",m_IsErase);
//得到第一个ITEM的rect
VERIFY(ListCtrl.GetItemRect(0,rc2,LVIR_BOUNDS ));
//得到最后一个ITEM的rect
VERIFY(ListCtrl.GetItemRect(ListCtrl.GetItemCount()-1,rcLast,LVIR_BOUNDS ));
CRgn rgnA, rgnB;
//从client rect创建RGN,该区域需要去掉headctrl所占区域
VERIFY(rgnA.CreateRectRgn( rc2.left-2,rc2.top-2,rc.right,rc.bottom ));
//如果最后一条记录的右下角坐标,已经超出了client rect那么只需要创建当前视图中包含ITEM,RGN
//如果最后一条记录没有超出视图的区域,那么仅仅创建当前视图中现有ITEM所在RGN
if (rcLast.bottom>rc.bottom)
{
VERIFY(rgnB.CreateRectRgn(rc2.left,rc2.top,rc2.right,rc.bottom));
}
else
{
VERIFY(rgnB.CreateRectRgn(rc2.left,rc2.top,rc2.right,rcLast.bottom));
}
//用client rgn区域与视图中item所占区域相减,得到需要擦除的区域
int nCombineResult = rgnA.CombineRgn( &rgnA, &rgnB, RGN_DIFF);
// pDC->FillSolidRect(rc2.right,rc2.top,rc.Width()-rc2.Width(),rc2.Height(),RGB(255,0,255));
//用白色填充,也可以先取得现在的背景色,再填充
pDC->FillRgn(&rgnA,&CBrush(RGB(255,255,255)));
rgnA.DeleteObject();
rgnB.DeleteObject();
return TRUE;
}
}