DOBON.NET DOBON.NETプログラミング掲示板過去ログ

TreeView文字のForeColor変更

環境/言語:[WinXp C# .NET1.1]
分類:[.NET]

TreeViewのノードの文字のForeColorは標準で変更できるように
なってますが、選択されたとき必ず決まった色になるようです。
これをカスタムドローで変更したいですが、
どなたかヒント頂けないでしょうか?
よろしくお願いします。
興味があったので調べてみました。
 NM_CUSTOMDRAW 通知メッセージを処理することで文字色の変更ができるようです。
NMTVCUSTOMDRAW で Google 検索すれば日本語サイトのサンプルも ( C++ ですけど ) 見つかりますので
色々試してみては如何でしょう。



#以下蛇足
> どなたかヒント頂けないでしょうか?
とのことだったので上記だけで十分でしょうけど、序でですのでこちらで動作確認したコードを
下記しておきます。
 選択したノードの文字色を黄色、背景色を黒色にするという内容です。フォーム ( Form1 ) 上に
ツリービューコントロール ( treeView1 ) を配置してあるという前提で記述してますので、
必要に応じて書き換えてください。
#見ての通りコメントは一切振っておりませんので、もし参考にする場合でも各パラメータの意味等は
#お調べになってくださいね。
#こちらの管理人さまが発行されてるメルマガ『.NETプログラミング研究』の 35 号も
#一部参考になるかと思います。
# http://dobon.net/vb/melma/dotnet35.txt


//using System.Runtime.InteropServices;

    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.TreeView treeView1;

//        〜 中略 〜

        private const int  WM_NOTIFY            = 0x004E;

        private const uint NM_FIRST             = (0U - 0U);
        private const uint NM_CUSTOMDRAW        = unchecked(NM_FIRST - 12U);

        private const int  CDDS_PREPAINT        = 0x00000001;
        private const int  CDDS_ITEM            = 0x00010000;
        private const int  CDDS_ITEMPREPAINT    = (CDDS_ITEM | CDDS_PREPAINT);

        private const int  CDRF_SKIPDEFAULT     = 0x00000004;
        private const int  CDRF_NOTIFYITEMDRAW  = 0x00000020;

        private const int  CDIS_SELECTED        = 0x0001;

        private struct NMHDR
        {
            public IntPtr   hwndFrom;
            public uint     idFrom;
            public uint     code;
        };

        private struct NMCUSTOMDRAW
        {
            public NMHDR    hdr;
            public uint     dwDrawStage;
            public IntPtr   hdc;
            public RECT     rc;
            public uint     dwItemSpec;
            public uint     uItemState;
            public IntPtr   lItemlParam;
        };

        private struct NMTVCUSTOMDRAW
        {
            public NMCUSTOMDRAW nmcd;
            public uint         clrText;
            public uint         clrTextBk;
            public int          iLevel;
        };

        private struct RECT 
        {
            public int  left;
            public int  top;
            public int  right;
            public int  bottom;
        };

        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            if (m.Msg == WM_NOTIFY)
            {
                NMTVCUSTOMDRAW nmtvcd =
                    (NMTVCUSTOMDRAW)Marshal.PtrToStructure(m.LParam, typeof(NMTVCUSTOMDRAW));
                if ((nmtvcd.nmcd.hdr.hwndFrom == this.treeView1.Handle) &&
                    (nmtvcd.nmcd.hdr.code == NM_CUSTOMDRAW))
                {
                    switch (nmtvcd.nmcd.dwDrawStage)
                    {
                        case CDDS_PREPAINT:
                            m.Result = new IntPtr(CDRF_NOTIFYITEMDRAW);
                            return;
                        case CDDS_ITEMPREPAINT:
                            bool selected = ((nmtvcd.nmcd.uItemState & CDIS_SELECTED) != 0);

                            if (!selected)
                                break;

                            nmtvcd.clrText = (uint)ColorTranslator.ToWin32(Color.Yellow);
                            nmtvcd.clrTextBk = (uint)ColorTranslator.ToWin32(Color.Black);
                            Marshal.StructureToPtr(nmtvcd, m.LParam, false);
                            m.Result = new IntPtr(CDRF_SKIPDEFAULT);
                            break;
                    }
                }
            }
            base.WndProc(ref m);
        }
    }
すいません、すいません、すいません
ありがとうございます。

返信遅れました。諦めて掲示版まめに見てませんしたので。。。すいません
さっきサンプルを確認させて頂きました。わずか一分で確認できました。
まさに希望通りの動作です。
大変わかりやすいサンプルです。

ありがとうございました。
すいません
大変あつかましいですが、
もしこの現象に覚えがありましたら、
ご教授頂きたいと思います。

提示していただいたサンプルは全然問題ありませんが、
ところが私のいま作成中のアプリのフォームのWndProcで
WM_NOTIFYメッセージが届かない現象が発生しています。
これはどんなときかご存知でしょうか?

すぐにわかるようなことでしたらよろしくお願いします。
私のアプリにのみ発生する現象(というか私のミス)の可能性が大ですので、
ほかの方が調べようがありませんので、そのときはこの質問は忘れてください。
度々すいません。

かなり初歩的なミスでした。
私のアプリでは対象ツリービューの親がフォームではありませんでした。
対象ツリービューの親であるパネルに提示していただいたコードを書いた
ところうまく動作しました。
凡ミスで申し訳ありませんでいた。

ありがとうございました。
■No10455に返信(Mr.Kさんの記事)
> 度々すいません。
>
> かなり初歩的なミスでした。
> 私のアプリでは対象ツリービューの親がフォームではありませんでした。
> 対象ツリービューの親であるパネルに提示していただいたコードを書いた
> ところうまく動作しました。
> 凡ミスで申し訳ありませんでいた。
>
> ありがとうございました。
>
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板