CListBoxのオーナードロー時の枠線について

[戻る]
古田 2017/11/29(水) 13:44:58
サイズ変更や色変更等のため、CListBoxをオーナードローしています。
基本的には、CListBoxの動作を踏襲したいのですが、
枠線の描画で困っている点があるので質問させてください。


void CMyListBox::DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
    CDC dc;
    dc.Attach(lpDIS->hDC);

    if ( lpDIS->itemAction & ODA_FOCUS )
    {
        dc.DrawFocusRect(lpDIS->rcItem);
    }

    dc.Detach();
}

このようにすると、フォーカスを当てるだけで点線枠がついてしまいます。
標準のCListBoxは、フォーカスしただけでは点線枠はつかず
AltキーやTabキーを押すと点線枠が付くようになります。

AltキーやTabキーが押された場合だけ点線枠を付けるには
どうしたら良いでしょうか?
Alt/Tabキーイベントを見てフラグ立てるしか無いでしょうか?

みい 2017/11/29(水) 15:42:26
itemActionではなくitemStateで見ても同じですか?

https://msdn.microsoft.com/ja-jp/library/92fhtw0f.aspx
の説明より
「ItemState メンバーは、コントロールにフォーカスがあるかどうかを判断する場合にチ
ェックします。」

古田 2017/11/30(木) 18:59:25
itemState は駄目ですね。

DrawFocusRect()はフォーカス枠線の描画と削除を兼ねているので
itemState の「フォーカスがある時」だけ行うと
「フォーカスが消えた時」に処理が走らず
枠線が消えなくなってしまいます。


AltキーやTabキーが押された後の
「フォーカス枠線を表示しなければならない」という状態が
フラグか何かで取得できれば良いのですが
今のところ見つからず困っています。

Win標準のCListBoxはそのような動きが出来ているので、
中身はどうやっているんでしょう・・・

みい 2017/12/01(金) 17:12:11
https://msdn.microsoft.com/ja-jp/library/kc9hahtd.aspx

これを見る限りではitemActionとitemState両方見て判断のようですが…。

古田 2017/12/04(月) 10:16:28
http://www.softist.com/programming/draw-combo/draw-combo.htm

私はここを参考に作成していたのですが、
MSDNの内容と異なるようですね。

 // Focus
    if (lpDrawItemStruct->itemAction & ODA_FOCUS) 
        pDC->DrawFocusRect(&lpDrawItemStruct->rcItem);    


MSDNの記述方法でも試してみましたが、
結果は変わりませんでした。
フォーカス時、Alt/Tabキー押す前でも枠が付いてしまいます。

ITO 2017/12/05(火) 09:55:36
>フォーカス時、Alt/Tabキー押す前でも枠が付いてしまいます。
他のウインドウ等が重なったり、他のウインドウの作業をしても、
フォーカスになるkとがあります。
状況によって変わるのでむずかしいですね。

ITO 2017/12/05(火) 09:56:34
修正です。
>フォーカスになるkとがあります。
フォーカスになることがあります。

みい 2017/12/05(火) 13:55:27
MSDNは
   // If this item has the focus, draw a red frame around the
   // item's rect.
   if ((lpDrawItemStruct->itemAction | ODA_FOCUS) &&
      (lpDrawItemStruct->itemState & ODS_FOCUS))
   {
      CBrush br(RGB(255, 0, 0));
      dc.FrameRect(&lpDrawItemStruct->rcItem, &br);
   }
ってなってますけど
   // If this item has the focus, draw a red frame around the
   // item's rect.
   if ((lpDrawItemStruct->itemAction & ODA_FOCUS) &&
      (lpDrawItemStruct->itemState & ODS_FOCUS))
   {
      CBrush br(RGB(255, 0, 0));
      dc.FrameRect(&lpDrawItemStruct->rcItem, &br);
   }
ですよね(^^;)
今ちょっと時間がなくて検証できず、ごめんなさい

みい 2017/12/05(火) 15:26:13
http://lhsp.s206.xrea.com/misc/ownerdraw.html

これをみるとitemStateに追加情報が。
ODS_NOFOCUSRECTあたりではじけないかなあ
(このビットが立っていたら枠を描かない)。

古田 2017/12/06(水) 10:03:40
教えていただいた内容で、期待通りの動作が実装できました。
ありがとうございます!

if ( (lpDIS->itemAction | ODA_FOCUS) &&
     (lpDIS->itemState & ODS_FOCUS) &&
     !(lpDIS->itemState & ODS_NOFOCUSRECT) )
{
    pDC->DrawFocusRect(rcItem);
}


しかし、同じ英語のMSDNでも、DRAWITEMSTRUCTの内容が異なりますね。

https://msdn.microsoft.com/en-us/library/92fhtw0f.aspx
https://msdn.microsoft.com/en-us/library/ms673121.aspx

前者がComboboxと関係ないという訳でも無さそうですし・・・
ちゃんと書いておいて欲しいですね。

古田 2017/12/06(水) 10:22:16
[[解決]]
解決チェック付け忘れました

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