Circle::Animation();的做法

在CPatternDlg中,宣告了一個圈圈物件
class CPatternDlg : public CDialog
{
    Circle m_Goal;
};
因為想要圈圈做動畫,並且用下面的呼叫方式(漂亮的語法)
void CPatternDlg::readyScreen()
{
//...
    m_Goal.Animation();
}
注意事項:
在此的動畫實作,是另外呼叫一個Thread來跑動畫程式段。


原本的做法

UINT CPatternDlg::vbrGoalThread(LPVOID LParam)
{
//...
    for (int i = 0; i < 100; ++i)
    {        
         PtnDlg->InvalidateRect(pGoal->VbrFun(i, oriR));
         PtnDlg->UpdateWindow();
    }
}
pGoal->VbrFun(i, oriR) 為動畫的數學式子(自已決定)
InvalidateRect();和UpdateWindow();為更新視窗的函數。

使用
void CPatternDlg::readyScreen()
{
//...
    vbrGoalThread((LPVOID)&Info1);
}
在準備畫面時,執行這個函數,就會出現動畫。


難點:
動畫需要更新畫面,所以動畫的每一頁更新步驟會建在CPattern::Animation()
但若做成CPattern::Animation(Circle& ),就違反概念整體性,也不OO了

後來的做法

我們來看看,先將動畫函數建在Circle
class Circle
{
private:
    CWnd* m_pdlgcWnd;
    static void elasticAnimation(LPVOID LParam);  //開新的Thread

public:
    CWnd* gethWnd(){ return m_pdlgcWnd; };
     void setWnd(CWnd* cWnd){ m_pdlgcWnd = cWnd; };

     void Animation(){ elasticAnimation((LPVOID)&m_Info1); };
};
在CPattern::CPattern()完成後,再用另一個函數將CWnd*存進Circle,為了畫面更新控制權。
void CPatternDlg::SomeFunction()
{
//...
    m_Goal.setWnd(GetActiveWindow()); //GetActiveWindow()需等建構式完成才可以抓取
}
最後在Circle裡建Animation(),再將「開新的Thread」函數隱藏起來
void Circle::elasticAnimation(LPVOID LParam)
{
//...
    for (UINT i = 0; i < 100; ++i)
    {
        _pCircle->gethWnd()->InvalidateRect(&_pCircle->DampingVibration(i,  _pCircle->GetRadius()), TRUE);
        _pCircle->gethWnd()->UpdateWindow();
    }
}

沒有留言:

張貼留言

(什麼是留言欄訊息?)