duilib CPaintManagerUIのWM_PAINTメッセージ

2774 ワード

この間duilibの描画メカニズムを研究して、しばらく忙しくて、感じはまた多く忘れて、ブログを書いて、記録して、後でソースコードを見ないようにします.直接ブログをめくればいいです.
WM_PAINTは2つの部分に分けられ、第1部分はコントロールレイアウト、第2部分はインタフェース更新である.
コントロールレイアウト
duilibの中の最上位は容器で、容器の中には主に各種のコントロールが含まれており、もちろん容器をネストすることもできます.
最上位のコンテナにレイアウトが必要な場合は、最上位のコンテナの位置、すなわちsetpos関数を更新します.
コンテナのsetpos関数の1つの責任は、サブコントロールの位置を維持し、後でコントロールに近づく準備をすることです.
            if( m_bUpdateNeeded ) 
			{
                m_bUpdateNeeded = false;
                RECT rcClient = { 0 };
                ::GetClientRect(m_hWndPaint, &rcClient);
                if( !::IsRectEmpty(&rcClient) ) 
				{
                    if( m_pRoot->IsUpdateNeeded() ) 
					{
                        m_pRoot->SetPos(rcClient);
                        if( m_hDcOffscreen != NULL ) ::DeleteDC(m_hDcOffscreen);
                        if( m_hDcBackground != NULL ) ::DeleteDC(m_hDcBackground);
                        if( m_hbmpOffscreen != NULL ) ::DeleteObject(m_hbmpOffscreen);
                        if( m_hbmpBackground != NULL ) ::DeleteObject(m_hbmpBackground);
                        m_hDcOffscreen = NULL;
                        m_hDcBackground = NULL;
                        m_hbmpOffscreen = NULL;
                        m_hbmpBackground = NULL;
                    }
                    else 
					{
                        CControlUI* pControl = NULL;
                        while( pControl = m_pRoot->FindControl(__FindControlFromUpdate, NULL, UIFIND_VISIBLE | UIFIND_ME_FIRST) ) 
						{
                            pControl->SetPos( pControl->GetPos() );
                        }
                    }
                    // We'll want to notify the window when it is first initialized
                    // with the correct layout. The window form would take the time
                    // to submit swipes/animations.
                    if( m_bFirstLayout ) 
					{
                        m_bFirstLayout = false;
                        SendNotify(m_pRoot, DUI_MSGTYPE_WINDOWINIT,  0, 0, false);
                    }
                }
            }

インタフェースの更新
レイアウトが完了すると、インタフェースが更新されます.インタフェースの更新メカニズムはレイアウトと同じで、DoPaint関数を使用しています.同じコンテナメンテナンス期間のサブクラスの更新です.
ここではあまり説明しませんが、DoPaint関数のプロトタイプは次のとおりです.
void CContainerUI::DoPaint(HDC hDC, const RECT& rcPaint)

1つ目はダブルバッファハンドル(ダブルバッファがオンの場合)で、後ろに親コントロールの領域があります.
mfcダイアログボックスに詳しい人は、OnPaint関数があることを知っています.私たちの絵はここで行われています.
このDoPaint関数はOnPaint関数と似ていて、いくつかの描画操作ができます.
duilibのコントロールもこのhdcの上に絵を描きます.
MFCの中で、1つのgifコントロールを書いて、次のいくつかのステップに分けます
1.cwndを継承してコントロールを書く
2 settimer関数を使用してタイマを追加
3.タイマーにInvaldateRect関数を追加
4.OnPaint関数で現在のフレームを描画する
mfcでの使用操作を真似て、duilibでアニメーション操作をすることができます.