控件內容更新 之 DrawText UpdateData SetWindowText

以一個顯示用戶通話時長的界面爲例,要在一個static控件上繪製「通話時長:XX:XX:XX」html

關於繪製,可使用得到到控件的句柄和CDC,經過 DrawText 繪製,也能夠經過API函數UpdateData 或 SetWindowText 進行更新。app

關於計時,能夠經過線程來計時也能夠經過利用計時器來計時。less

下面,按照繪製方式的不一樣來進行比較,看哪一個最方便啦~函數

 

方法一: DrawText + 線程計時this

這無疑是最笨的一種方法啦...url

代碼:spa

//變量線程

CDC* pDCStatic;//static控件的CDCcode

BOOL bIintState;//是否初始化完畢(對WM_SIZE的處理必須是在初始化完畢後,不然出錯)orm

BOOL bOnLine;//線程運行控制符

DWORD dwStartTime;//用來記錄通話起始時間  在須要開始計時的地方經過 GetTickCount()得到

HANDLE hUpdateEvent;//用於線程同步的Event
CWinThread* pThreadUpdate;//計時線程句柄


static UINT CALLBACK PaintWindow(LPVOID lParam);//計時線程

void GetTimeSpace(DWORD dwStartTime,CString & szTime);//用來獲得時長的CString形態

 

//對話框初始化函數 

BOOL C****Dlg::OnInitDialog()
{
 CDialog::OnInitDialog();
 
 // TODO: Add extra initialization here
 this->pDCStatic = NULL;

 this->bOnLine = TRUE;

//建立線程同步事件
 this->hUpdateEvent = CreateEvent(NULL, TRUE, FALSE, "UpdateEvent") ;
//建立計時線程
 this->pThreadUpdate=new CWinThread;
 this->pThreadUpdate->m_bAutoDelete=true;
 this->pThreadUpdate=AfxBeginThread(AFX_THREADPROC(PaintWindow),this,THREAD_PRIORITY_NORMAL,0,0,NULL);

//初始化結束置位

 this->bIintState = FALSE;

 return TRUE;  // return TRUE unless you set the focus to a control
               // EXCEPTION: OCX Property Pages should return FALSE
}

 

//窗口WM_SIZE響應函數
void C****Dlg::OnSize(UINT nType, int cx, int cy)
{
 CDialog::OnSize(nType, cx, cy);
 
 // TODO: Add your message handler code here
 if(!this->bIintState)
 {  

  CRect rcOnLine;

//獲取當前窗口的客戶區大小
  GetClientRect(&rcOnLine);

  CWnd*  hStatic = GetDlgItem(IDC_TIME);
  this->pDCStatic = hStatic->GetDC();

//獲得在static上繪字的大小,以便於決定static控件位置和大小

  CSize font = this->pDCStatic->GetTextExtent("你");

//和客戶區同寬,起點在客戶區的1/4處,高位字高的3倍
  this->rcAllText = this->rcOnLine;
  this->rcAllText.top += this->rcOnLine.Height()/4;
  this->rcAllText.bottom = this->rcAllText.top+(font.cy*3);

//挪動static控件

  hStatic->MoveWindow( &this->rcAllText, TRUE ); 
 }
}

 

//計時線程 

UINT C****Dlg::PaintWindow(LPVOID lParam)
{
 C****Dlg * vnol = (C****Dlg*)lParam;

 while(vnol->bOnLine)
 { 
  WaitForSingleObject(vnol->hUpdateEvent,INFINITE);//等待事件被置位,此線程暫停於此
  ::SendMessage(vnol->m_hWnd,WM_PAINT,0,0);//給窗口發送刷新消息
  Sleep(100);//時間間隔爲100ms
 }

 return 1;
}

 

//刷新函數

void C****Dlg::OnPaint()
{
 CPaintDC dc(this); // device context for painting
 
 // TODO: Add your message handler code here
 // Do not call CDialog::OnPaint() for painting messages

//獲得當前時長

 CString strStaticText;

 CString strTimeSpace;

//自定義的函數,用來獲得時長的CString形態

//dwStartTime在須要開始計時的地方得到

 this->GetTimeSpace(this->dwStartTime,strTimeSpace);

 strStaticText = "通話時長:" + strTimeSpace;
 CBrush brush(RGB(255,255,255)); 

//將控件區繪製白色背景
 this->pDCStatic->FillRect(CRect(0,0,this->rcAllText.Width(),this->rcAllText.Height()),&brush);
//在控件上經過DrawText將字顯示到屏幕上

 this->pDCStatic->DrawText(szText,CRect(0,0,this->rcAllText.Width(),this->rcAllText.Height()),DT_CENTER|DT_VCENTER|DT_SINGLELINE);

}

 

//這三種方法共用函數,用來獲得時差的CString形態 

void C****Dlg::GetTimeSpace(DWORD dwStartTime,CString & szTime)
{
 DWORD dwNowTime=0;
 DWORD dwSpace=0;
 char time[10]={0,};

 //獲取當前時間
 dwNowTime = GetTickCount();

 //開始計算時差
 dwSpace = dwNowTime-dwStartTime;

 dwSpace = dwSpace/1000;//轉化爲以秒爲單位
 int sec = dwSpace` ;
 int min = ((dwSpace - sec)/60)`;
 int hour = ((dwSpace - sec)/60)/60;

 sprintf(time,"-:-:-",hour,min,sec);
 szTime.Format("%s",(char*)time);

 return;
}

 

 

方法二:setwindowText + 計時器

這個方法還好吧。思路就是:啓動定時器,每隔一段時間就對控件setwindowText。

在這個方法裏,咱們用兩個控件來進行,一個是staticText控件,一個是Edit控件。

setwindowText:設置控件的顯示信息,是針對單個控件而言滴!

CWnd::SetWindowText

void SetWindowText( LPCTSTR lpszString );

Parameters

lpszString

Points to a CString object or null-terminated string to be used as the new title or control text.

 

與setwindowText相對應的是 GetwindowText。

GetwindowText:獲取控件的當前內容(對於Edit控件,能夠在它的EN_CHANGE處理中獲得當前的顯示)。

CWnd::GetWindowText

int GetWindowText( LPTSTR lpszStringBuf, int nMaxCount ) const;

void GetWindowText( CString& rString ) const;

 

代碼以下:

 //變量

 CString m_staticText;//要顯示在static控件上的字符串

 CString m_EditText;//要顯示在Edit控件上的字符串

 BOOL m_bInitState;//是否處於初始化狀態 (若要重載OnSize 則必須是在初始化結束後,不然報錯)

 DWORD m_dwStartTime;//起始時間 在須要開始計時的地方經過 GetTickCount()得到

 void GetTimeSpace(DWORD dwStartTime,CString & szTime);//用來的到當前時間差字符串的函數

 

//窗口的初始化函數 

BOOL C****Dlg::OnInitDialog()
{
 CDialog::OnInitDialog();

 // Set the icon for this dialog.  The framework does this automatically
 //  when the application's main window is not a dialog
 SetIcon(m_hIcon, TRUE);   // Set big icon
 SetIcon(m_hIcon, FALSE);  // Set small icon
 
 // TODO: Add extra initialization here
 //設置定時器
 SetTimer(1,500,NULL);

 this->m_bInitState = FALSE;

 return TRUE;  // return TRUE  unless you set the focus to a control
}


//計時器響應函數

void CUpdateDateDlg::OnTimer(UINT nIDEvent)
{
 // TODO: Add your message handler code here and/or call default
 switch(nIDEvent)
 {
 case 1:
  //定時器時間到
  {
   //計算出時差str

   CString strTemp;
   this->GetTimeSpace(this->m_dwStartTime,strTemp);
   this->m_staticText = "通話時長:"+strTemp;

   //edit和static顯示的是同樣的

   this->m_EditText = this->m_staticText;
   //獲得控件的句柄
   CWnd* hStatic = GetDlgItem(IDC_MYSTATIC);

   CWnd* hEdit = GetDlgItem(IDC_MYEDIT);

   //把語句顯示到兩個控件上
   hStatic->SetWindowText(this->m_staticText);
   hEdit->SetWindowText(this->m_editText);
  }
  break;
 default:
  CDialog::OnTimer(nIDEvent);
 }
}

 

//Edit控件顯示發生改變時EN_CHANGE的響應函數 

void C****Dlg::OnChangeMyedit()
{

  CString szNowText;
  CWnd* hEdit = GetDlgItem(IDC_MYEDIT);
  hEdit->GetWindowText(szNowText); 
}

 

 

方法三:UpdateData + 定時器

這個方法跟方法二思路是同樣滴,不過區別在於UpdateData的用法啦~

UpdateData刷新的是整個對話框,而不是像SetWindowText那樣是針對控件進行處理。

UpdateData是MFC的API,因此這個方法要基於MFC使用。

使用這個方法,首先要經過ClassWizard創建控件和變量之間的聯繫。當你修改了變量的值,而但願對話框控件更新顯示,就應該在修改變量後調用 UpdateData(FALSE);若是你但願知道用戶在對話框中到底輸入了什麼,就應該在訪問變量前調用UpdateData(TRUE)。

// ClassWizard創建控件和變量之間的聯繫

控件內容更新 <wbr>之 <wbr>DrawText <wbr>UpdateData <wbr>SetWindowText

代碼:

//經過ClassWizard創建控件和變量之間聯繫的代碼反映

.h

 //{{AFX_DATA(CUpdateDateDlg)
 enum { IDD = IDD_UPDATEDATE_DIALOG };
 CString m_staticText;
 CString m_editText;
 //}}AFX_DATA

.cpp

void CUpdateDateDlg::DoDataExchange(CDataExchange* pDX)
{
 CDialog::DoDataExchange(pDX);
 //{{AFX_DATA_MAP(CUpdateDateDlg)
 DDX_Text(pDX, IDC_MYSTATIC, m_staticText);
 DDX_Text(pDX, IDC_MYEDIT, m_editText);
 //}}AFX_DATA_MAP
}

 

//變量 

 BOOL m_bInitState;//是否處於初始化狀態 (若要重載OnSize 則必須是在初始化結束後,不然報錯)

 DWORD m_dwStartTime;//起始時間
 void GetTimeSpace(DWORD dwStartTime,CString & szTime);//用來的到當前時間差字符串的函數

 

//窗口的初始化函數 

BOOL C****Dlg::OnInitDialog()
{
 CDialog::OnInitDialog();

 // Set the icon for this dialog.  The framework does this automatically
 //  when the application's main window is not a dialog
 SetIcon(m_hIcon, TRUE);   // Set big icon
 SetIcon(m_hIcon, FALSE);  // Set small icon
 
 // TODO: Add extra initialization here
 //設置定時器
 SetTimer(1,500,NULL);

 this->m_bInitState = FALSE;

 return TRUE;  // return TRUE  unless you set the focus to a control
}


//計時器的響應函數

void CUpdateDateDlg::OnTimer(UINT nIDEvent)
{
 // TODO: Add your message handler code here and/or call default
 switch(nIDEvent)
 {
 case 1:
  //定時器時間到
  {
   //計算出時差
   this->GetTimeSpace(this->m_dwStartTime,this->m_editText);
   this->m_staticText = this->m_editText;


   this->UpdateData(false);

  }
  break;
 default:
  CDialog::OnTimer(nIDEvent);
 }
}

 

//edit控件顯示內容發生變化時EN_CHANGE的響應函數 

void C****Dlg::OnChangeMyedit()
{

    this->UpdateData(true); 
}

 

 


UpdateData詳解

UpdateData(TRUE):

是將控件的狀態傳給其關聯的變量,固然你要爲控件關聯上變量才行。

用於將屏幕上控件中的數據交換到變量中。
UpdateData(FALSE):

是將控件的關聯變量的值傳給控件並改變控件狀態。

用於將數據在屏幕中對應控件中顯示出來。

注意:

UpdateData刷新的是當前對話框

使用UpdateData()函數時,當前界面上全部綁定了的變量(即經過MFC ClassWizard給控件添加了對應的變量)都會被UpdateData(TRUE)更新成對應控件中的內容;一樣全部綁定了變量的控件中的內容也會 UpdateData(FALSE)更新成對應變量中的內容。

 

 

重要補充

GetWindowText()是獲取控件當前內容,是對單個控件而言;
UpdateData()是做用於整個CWnd的DDX數據交換機制之中的,是控件和數據的雙向通道。

相關文章
相關標籤/搜索