2013年2月26日 星期二

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();
}
}

沒有留言:

張貼留言