【轉】MFC介面更新實現方法

來源:互聯網
上載者:User

標籤:

原文網址:http://www.cnblogs.com/skywatcher/p/3572311.html

1.更新視窗

即採用UpdateWindow()函數立即發送WM_PAINT訊息更新整個視窗。

void CEditTestDlg::OnBnClickedBtnSysUpdate(){    CString csTmp;    int i = 0;    while (i < 100)    {        Sleep(20);        i += 1;        csTmp.Format(_T("%d"),i);        m_value = csTmp;//無法更新只顯示結果        //m_editNum.SetWindowText(csTmp);//無法更新也不顯示結果        UpdateData(FALSE);        UpdateWindow();//能更新但再次操作會卡死        //Invalidate(FALSE);//無法更新只顯示結果        //RedrawWindow(NULL,NULL,RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE);//RDW_INVALIDATE和Invalidate()效果一樣,RDW_ERASE導致閃爍    }}

但是這會導致介面假死,更新過程中無法對視窗進行任何操作。控制項的Control變數有時候無法更新Invalidate()一般都在多文檔對話方塊裡使用,RedrawWindow()是前兩個都會去調用的函數,方式更多。詳情見:MFC重繪函數

2. 定時器實現

在需要更新的位置調用SetTimer()啟動定時器,在定時器響應函數OnTimer()裡面來處理更新,可以同時啟用多個定時器更新多個位置。

啟動定時器:

void CEditTestDlg::OnBnClickedBtnTimerUpdate(){    this->SetTimer(1,1,NULL);    this->SetTimer(2,1,NULL);}

定時器內部處理:

void CEditTestDlg::OnTimer(UINT_PTR nIDEvent){    switch (nIDEvent)    {    case 1:        if (tmp >= 100)        {            this->KillTimer(1);            MessageBox(_T("定時器1停止!"), NULL, NULL);            return;        }        Sleep(20);        tmp += 1;        m_value.Format(_T("%d"),tmp);        UpdateData(FALSE);        break;    case 2:        if (tmp1 >= 200)        {            this->KillTimer(2);            MessageBox(_T("定時器2停止!"), NULL, NULL);            return;        }        Sleep(20);        tmp1 += 1;        m_value2.Format(_T("%d"),tmp1);        UpdateData(FALSE);    default:        break;    }    CDialog::OnTimer(nIDEvent);}

通過定時器介面不會假死,實現也簡單明了。

3. 線程更新

建立一個新的線程來更新介面,建立線程:

void CEditTestDlg::OnBnClickedBtnThreadUpdate(){    CWinThread* pThread;    pThread = AfxBeginThread(UpdateThread,this);}

線程內部實現:

static UINT UpdateThread(LPVOID lpParam){    CEditTestDlg *dlg = (CEditTestDlg*) lpParam;    int i = 0;    while (i < 200)    {        Sleep(20);        i += 1;        dlg->m_value2.Format(_T("%d"), i);        //dlg->UpdateData(FALSE);//release下可行        dlg->m_editCtl.SetWindowText(dlg->m_value2);//使用control變數        //dlg->GetDlgItem(IDC_EDIT2)->SetWindowText(dlg->m_value2);    }    return 0;}

在這裡,最好不要用UpdateData(FALSE)來顯示到介面,在Debug下回奔潰,而Release模式下沒有任何問題,具體見:線程調用UpdateData函數出錯

4. 線程中發送自訂訊息更新

線上程中給視窗發送自訂的更新介面的訊息,讓訊息加入系統訊息佇列達到更新介面的目的。自訂訊息可參照:MFC添加自訂訊息

void CEditTestDlg::OnBnClickedBtnMsgUpdate(){    CWinThread* pThread;    pThread = AfxBeginThread(SendMsgThread,this);}
static UINT SendMsgThread(LPVOID lpParam){    CEditTestDlg *dlg = (CEditTestDlg*) lpParam;    int i = 0;    while (i < 100)    {        Sleep(20);        i += 1;        dlg->m_value2.Format(_T("%d"), i);        //PostMessage(dlg->m_hWnd,WM_UPDATEDATA,FALSE,NULL);        //SendMessage(dlg->m_hWnd,WM_UPDATEDATA,FALSE,NULL);        SendMessageTimeout(dlg->m_hWnd, WM_UPDATEDATA, FALSE,NULL, SMTO_BLOCK, 1000, NULL);    }    return 0;}

發送訊息的時候PostMessage(),SendMessage()SendMessageTimeout()都可以實現,具體區別見:SendMessage和PostMessage區別

5. 裝置繪製更新

直接在介面中不停的繪製變化的部分,這種方法也會造成假死。

void CEditTestDlg::OnBnClickedBtnDrawUpdate(){    CString csTmp;    int i = 0;    CDC* pDC = this->GetDC();    while (i < 100)    {        Sleep(20);        i += 1;        csTmp.Format(_T("%d"),i);        pDC->TextOut(20, 100, csTmp);    }    ReleaseDC(pDC);}

6. STATIC控制項更新

給STATIC控制項賦值更新,同樣會造成假死現象。(值得一提的是以前在VC6.0中可以對EIDT控制項使用同樣的方法更新而現在去測試卻不行,希望有經驗的人給予指導。)

void CEditTestDlg::OnBnClickedBtnStaticUpdate(){    CString csTmp;    int i = 0;    while (i < 100)    {        Sleep(20);        i += 1;        csTmp.Format(_T("%d"),i);        m_csStaticNum = csTmp;//能更新但再次操作會卡死        //m_staticCtlNum.SetWindowText(csTmp);//不更新也不顯示結果        UpdateData(FALSE);    }}

7. 發送系統訊息更新

直接給系統訊息迴圈發送WM_PAINT訊息來更新介面,但是同樣會出現假死情況,所以可以建立一個函數DoEvent()實現:在有系統訊息,如拖動點擊等訊息時,暫停處理我們發送的訊息而優先去處理系統訊息。

void CEditTestDlg::OnBnClickedBtnMsg(){    CString csTmp;    int i = 0;    while (i < 100)    {        Sleep(20);        i += 1;        csTmp.Format(_T("%d"),i);        m_value = csTmp;//能更新但再次操作會卡死        //m_editNum.SetWindowText(csTmp);//無法更新也不顯示結果        UpdateData(FALSE);        GetDlgItem(IDC_EDIT1)->SendMessage(WM_PAINT);//能更新但再次操作會卡死        DoEvents();//轉出處理系統訊息    }}
//有系統訊息時暫停處理系統訊息void DoEvents(){    MSG msg; //定義一個MSG類型的變數    while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) //擷取訊息並把該訊息從訊息佇列中移除(防止重複響應)。    {        TranslateMessage(&msg);//翻譯訊息 在合適的機會產生char訊息        DispatchMessage(&msg); //將訊息移交給過程函數    }}

但是出現的問題是,我們在拖動對話方塊的時候,介面停止了更新。

 

所以比較而言,線程發送訊息和定時器效果相對較好,介面不會假死,在進行拖動等操作的時候也不會出現停止等待的現象。

【轉】MFC介面更新實現方法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.