VC中对话框上数据的动态实时更新技术总结

在写一个算法的时候,希望能够看到计算过程中数据的实时变化,本以为很简单,就拖了一个文本框用来显示循环次数,没想到事与愿违,文本框中的数据并不是动态的变化,而是在计算完成后才一次冒出来,如下例如示,这个小小的问题难了我一整天,现在终于解决,并总结了数据实时显示的一些方法。

一个示例:

for (int i=0;i<10000000;i++)
{
m_curPos=i;
itoa(m_curPos,temp,10);
m_edit.SetWindowText(temp);

}

在上例中,整个循环结束后,程序才将控制权交给窗口,窗口控件才能刷新。解决方法有以下几种:

1.使用定时器:

先设定定时器:this->SetTimer ( 1, 0.1, NULL ) ;然后在对话框中添加OnTimer消息,这样文本框中的数据就可以动态变化了。

void CTestDlg::OnButton1() 
{
this->SetTimer ( 1, 0.1, NULL ) ;
}

void CTestDlg::OnTimer(UINT nIDEvent) 
{
m_curPos++;
char temp[20];
itoa(m_curPos,temp,10);
  m_edit.SetWindowText(temp);
UpdateData(false);
CDialog::OnTimer(nIDEvent);
}

2.使用多线程

void CTestDlg::OnButton3() //¶àÏ̷߳½Ê½
{
CWinThread*   pThread; 
pThread=AfxBeginThread(ThreadProc,this);//¸Ã²ÎÊý¿ÉÓÃÀ´ÏòÉÏÃ溯Êý´«µÝ
}

static UINT ThreadProc(LPVOID lpParam)//²ÎÊýlpParamÓÃÀ´´«µÝ£¬¿ÉÁé»îÔËÓà
{

CTestDlg *dlg=(CTestDlg *)lpParam;
char temp[30];
while (dlg->m_curPos<100000)
{

dlg->m_curPos=dlg->m_curPos+1;
itoa(dlg->m_curPos,temp,10);
dlg->m_edit.SetWindowText(temp);
}
return   0; 
}
但是,有时候这两种方法并不能达到我们的要求,方法1必须将计算过程写在OnTimer函数中,若将m_curPos写在OnTimer函数外部变化,仍不能动态更新,而有时候计算过程不能写在OnTimer函数中,而且文本框中数据的变化时间间隔是事先设定好的,与计算并不是同步的,有违实时性。方法2类似,必须将变量的计算过程写在ThreadProc中,与法1的区别是可与计算过程同步更新。


3.用设备管理器DC来更新文本

这次不用文本框来显示数据,而是直接在对话框界面上绘制,可达到目的。

void CTestDlg::OnButton2() //DC·½Ê½
{
char temp[20];
CDC* dc=this->GetDC();
for (int i=0;i<1000000;i++)
{
m_curPos=i;
itoa(m_curPos,temp,10);
dc->TextOut(20,20,CString(temp));
UpdateData(false);
}
}

4.用Static控件来显示

void CTestDlg::OnButton4() 
{
// TODO: Add your control notification handler code here
char temp[20];
CDC* dc=this->GetDC();
for (int i=0;i<10000000;i++)
{
m_curPos=i;
itoa(m_curPos,temp,10);
m_staticValue=CString(temp);
m_staticControl.SetWindowText(temp);
UpdateData(false);
}
}

不知为什么Edit控件如此不能实时更新,而Static控件却可以。但此法与法3也是有缺陷的:计算过程中,如果程序焦点变化,如处理其它事情,数据将停止变化,甚至整个程序出现假死状态,一片空白,但实际仍在运行,就是不能动态刷新了。

5.使用DoEvent()或者使用SendMessage强制向窗口发送刷新消息

void CTestDlg::OnButton4() 
{
// TODO: Add your control notification handler code here
char temp[20];
CDC* dc=this->GetDC();
for (int i=0;i<10000000;i++)
{
m_curPos=i;
itoa(m_curPos,temp,10);
m_edit.SetWindowText(temp);

m_editValue=m_curPos;

UpdateData(false);

GetDlgItem(IDC_EDIT2)->SendMessage(WM_PAINT);
// DoEvent();  //暂时转出去处理一下系统消息

}
}

void DoEvent()
{
MSG msg;
while (PeekMessage(&msg, (HWND)NULL, 0, 0, PM_REMOVE) )//ÅжÏÊÇ·ñÓÐÏûÏ¢
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}

使用SendMessage方法和法3.4存在相同的问题,即焦点变化时,出现假死状态,经检验,使用DoEvent方法是最完美的办法。


总结:

此问题实际上是实时绘制和刷新的问题,在做实时数据采集显示,科学计算过程显示时会遇到,有时还需要绘制实时的图形,这时,就要求计算过程与显示同步更新,以上方法可在小程序中使用,若在大型实时系统中,可能最终还是会用多线程技术,虽然法2也用了多线程,但解决并不完美,望高手指正。

你可能感兴趣的:(开发语言,vc++)