すべてのアイテムとすべての列を削除および再添加するときに、win32ダイアログでlistViewが点滅します
質問
C ++で記述されたListViewコントロール(レポートモード)を使用したプレーンWin32ダイアログを検討してください。特定のイベントでは、すべてのアイテムとすべての列が削除され、新しい列とアイテムが作成されます。基本的に、コンテンツが変更されると、列はコンテンツに基づいて自動的に生成されます。
古いアイテム/列が削除され、新しいアイテムが追加されると、ListViewは地獄のようにちらつきます。私が試してみました WM_SETREDRAW
と LockWindowUpdate()
視覚的な経験に変更はありません。
拡張リストビュースタイルも設定しました LVS_EX_DOUBLEBUFFER
そして、それはまったく役に立ちませんでした。
親ダイアログにはあります WS_CLIPCHILDREN
セットする。
できるだけ小さなフリッカーでこれを機能させる方法はありますか?私は2つのリストビューを使用することを考えています。視認性を交互に、非表示のものをバックバッファーとして使用しますが、これは過剰に聞こえます。簡単な方法がなければなりません。
解決
デフォルトのリストコントロールペイントにはかなり欠陥があります。しかし、独自のダブルバッファリングテクニックを実装する簡単なトリックがあります。
CMyListCtrl::OnPaint()
{
CRect rcClient;
GetClientRect(rcClient);
CPaintDC dc(this);
CDC dcMem;
dcMem.CreateCompatibleDC(&dc);
CBitmap bmMem;
bmMem.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
CBitmap* pbmOld = dcMem.SelectObject(&bmMem);
dcMem.FillSolidRect(rcClient, ::GetSysColor(COLOR_WINDOW));
this->DefWindowProc(WM_PAINT, (WPARAM)dcMem.m_hDC, (LPARAM)0);
dc.BitBlt(0,0,rcClient.Width(), rcClient.Height(), &dcMem, 0, 0, SRCCOPY);
dcMem.SelectObject(pbmOld);
CHeaderCtrl* pCtrl = this->GetHeaderCtrl();
if (::IsWindow(pCtrl->GetSafeHWnd())
{
CRect aHeaderRect;
pCtrl->GetClientRect(&aHeaderRect);
pCtrl->RedrawWindow(&aHeaderRect);
}
}
これにより、ビットマップが作成され、デフォルトのウィンドウ手順を呼び出して、リストコントロールをビットマップにペイントし、ビットマップの内容をペイントDCに描きます。
また、wm_erasebkgndのハンドラーを追加する必要があります。
BOOL CMyListCtrl::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
これにより、コントロールが再描画の前に常に背景を消去するのを止めます。ビットマップにメンバー変数を追加し、ウィンドウのサイズが変更されたときにのみ(再)作成すると、オンペイントをさらに最適化できます(常にビットマップを作成することは、ウィンドウのサイズに応じてコストがかかる場合があります)。
これは非常にうまく機能するはずです。
他のヒント
多くのことを試した後、何よりも humbagumba
の提案私は非常に単純な結論に達しました。 LockWindowUpdate
この種の状況ではみんなの友達です。どうして初めて私のために機能しなかったのかわかりませんが、カスタムペインティングがあらゆる状況で配信できなかった後、私は試しました LockWindowUpdate
もう一度、それはうまくいきました!
基本的に、すべての作業をリストビューでラップするだけです LockWindowUpdate(hWnd)
と LockWindowUpdate(NULL)
そして物事は美しく機能します。スクロールバーフリッカーさえありません。
巣を作らないようにしてください LockWindowUpdate
一度にロックできるウィンドウは1つだけです。