zoukankan      html  css  js  c++  java
  • 控件内容更新 之 DrawText UpdateData SetWindowText

    以一个显示用户通话时长的界面为例,要在一个static控件上绘制“通话时长:XX:XX:XX”

    关于绘制,可以使用获得到控件的句柄和CDC,通过 DrawText 绘制,也可以通过API函数UpdateData 或 SetWindowText 进行更新。

    关于计时,可以通过线程来计时也可以通过利用计时器来计时。

    下面,按照绘制方式的不同来进行比较,看哪个最方便啦~

     

    方法一: DrawText + 线程计时

    这无疑是最笨的一种方法啦...

    代码:

    //变量

    CDC* pDCStatic;//static控件的CDC

    BOOL bIintState;//是否初始化完毕(对WM_SIZE的处理必须是在初始化完毕后,否则出错)

    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数据交换机制之中的,是控件和数据的双向通道。

  • 相关阅读:
    Licode—基于webrtc的SFU/MCU实现
    从入门到进阶|如何基于WebRTC搭建一个视频会议
    Web前端的WebRTC攻略(一)基础介绍
    WebRTC入门与提高1:WebRTC基础入门
    RTCStartupDemo:一款极其简单的 WebRTC 入门项目
    WebRTC 开发实践:如何实现 SFU 服务器
    maven~生成spotbug文档
    spotbugs~lombok生成的Date属性引起的EI_EXPOSE_REP问题
    es~通过ElasticsearchTemplate进行聚合~Nested嵌套聚合
    es~通过ElasticsearchTemplate进行聚合~嵌套聚合
  • 原文地址:https://www.cnblogs.com/jack-jia-moonew/p/4299764.html
Copyright © 2011-2022 走看看