CListCtrl 特定の行を更新するには?

[戻る]
駄犬 [E-Mail] 2002/04/01(月) 17:35:44
お世話になります。

CListCtrl派生クラス(DrawItemをオーバーライドしてオーナー描
写を行っています)のコントロールを貼り付け、このコントロール
の表示を周期的に更新しようと考えています。
試しに親ダイアログから周期的にInvalidateしてみたところ、更新
されることはされるのですが、ちらつきがかなり目立ちます。そこ
で特定の行だけ更新させようとUpdateなるメンバ関数を使ってみた
のですが、今度はまったく更新されません。(DrawItemが叩かれる
ことを期待したのですが。。。)
デバッガでUpdateを追いかけると、LVM_UPDATEをSendMessageして
いるだけでした。

そこで質問です。
・リストコントロールの特定の行を更新するにはどうしたらよいの
でしょうか。
当方MFC(というよりWindowsアプリの)経験が浅く、よい手法がま
ったく浮かびません。



開発環境
Win2K VC++6.0 MFC ダイアログベース
リストコントロールのGetCountPerPage()値は41、列数は13です。


以上よろしくおねがいします。

駄犬 [E-Mail] 2002/04/01(月) 19:58:03
半歩前進しました。

DrawItemをコピーしてDrawLine関数を作ってみました。
これで希望のタイミングで行毎の更新ができるようにはなったので
すが、なぜかDrawLineで表示するとフォントサイズが2周りほど
大きくなってしまいます。
pDCの求め方に問題があるのでしょうか?


void CXXXListCtrl::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
    CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC);
    // 再描画するItemの座標を取得
    CRect rcItem(lpDrawItemStruct->rcItem);
    // アイテムのID
    int nItem = lpDrawItemStruct->itemID;

    DrawColumn(pDC, rcItem, nItem); // 描画処理
}

void CXXXListCtrl::DrawLine(int nItem)
{
    CDC* pDC = GetDC();
    // 再描画するItemの座標を取得
    CRect rcItem;
    GetItemRect(nItem, &rcItem, LVIR_BOUNDS);

    DrawColumn(pDC, rcItem, nItem); // 描画処理
}

void CXXXListCtrl::DrawColumn(CDC* pDC, CRect rcItem, int nItem)
{
    〜カラムごとの描画処理〜
}

dairygoods 2002/04/02(火) 09:58:24
> ・リストコントロールの特定の行を更新するにはどうしたらよいの
> でしょうか
Invalidate()には、RECTを引数に取るバージョンがあります。
そこに、更新したい領域を指定してみてください。

> なぜかDrawLineで表示するとフォントサイズが2周りほど
> 大きくなってしまいます。
> pDCの求め方に問題があるのでしょうか?

DrawItemが呼ばれたときは、既にDCが描画用に初期化されていますが、
GetDC()で取得したDCは未初期化状態です。
描画に使うフォント等を設定する必要があります。

駄犬 [E-Mail] 2002/04/02(火) 11:45:15
[[解決]]
dairygoodsさんありがとうございます。

> Invalidate()には、RECTを引数に取るバージョンがあります。
> そこに、更新したい領域を指定してみてください。

ありました!!
CWnd::InvalidateRect
早速試してみたのですが、ちらつきは思ったほどは減らせなかったです。(TT
SetRedrawと組み合わせるなどして色々試したのですが。。。
「周期的に更新」という仕様では避けられないのでしょうかね。
まあしかし今回はこれで解決ということで。
別のアプローチからの解決方法などなどご教授いただけると幸いです。

> GetDC()で取得したDCは未初期化状態です。
> 描画に使うフォント等を設定する必要があります。

なるほどなるほど。
これはDCについてきちんと勉強せないかんですね〜。
どのみち避けては通れませんからね。

いや今回は大変勉強になりました。
本当にありがとうございます。

dairygoods 2002/04/02(火) 12:55:13
> 早速試してみたのですが、ちらつきは思ったほどは減らせなかったです。(TT
結局同じ場所を二度以上描画するとちらついてしまいますね。

描画のちらつきを無くしたいということであれば、
以下の手法について調べてみてください。

その1)クリッピング(CDCの*Clip*関数など)
その2)ダブルバッファリング

駄犬 [E-Mail] 2002/04/02(火) 16:33:09
すみません、ちらつきが残ったのは私のミスでした。
m_XXXListCtrl.Update(nItem) の消し忘れです。
一番始めの投稿にて「UpdateでDrawItemは起動されない」旨報告し
ましたが、どうやら誤認だったようです。再確認したところ「Upda
teで、指定したアイテムだけでなく表示しているすべてのアイテム
に対してDrawItemが起動される」といったところのようです。
Updateを消し、正しくInvalidateRectしたところ、十分満足の行く
レベルまでちらつきを抑えることができました。

重ねて御礼申し上げます。

# 後学のためDrawLineにあれこれ手を加えて勉強中です。
# 現時点でフォントは設定できたました。
# あとは消えちゃうグリッドラインをなんとかせねば。;-)

> 描画のちらつきを無くしたいということであれば、以下の手法について
> 調べてみてください。

ありがとうございます。
いい機会ですのでDCと併せて勉強したいと思います。
今回は大変お世話になりました。

古いスレッドには追加発言できません。