TrackBarのカスタムドロー

TrackBarの棒部分の色を変えたかったので、カスタムドローに挑戦してみる。
まずシンプルにトラックの背景色だけを変えてみる。

で、できたのがこれです。

namespace TrackBarTest {
    public class CustomTrackBar : TrackBar {
        [StructLayout(LayoutKind.Sequential)]
        protected struct NMHDR {
            public IntPtr hwndFrom;
            public uint idFrom;
            public uint code;
        }

        [StructLayout(LayoutKind.Sequential)]
        protected struct RECT {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }

        [StructLayout(LayoutKind.Sequential)]
        protected struct NMCUSTOMDRAW {
            public NMHDR hdr;
            public uint dwDrawStage;
            public IntPtr hdc;
            public RECT rc;
            public uint dwItemSpec;
            public uint uItemState;
            public IntPtr lItemlParam;
        }

        protected const uint WM_REFLECT = 0x2000;
        protected const uint WM_NOTIFY = 0x004E;

        protected const uint NM_CUSTOMDRAW = 4294967284; //(uint)-12

        protected const uint CDRF_DODEFAULT = 0x00000000;
        protected const uint CDRF_NEWFONT = 0x00000002;
        protected const uint CDRF_SKIPDEFAULT = 0x00000004;
        protected const uint CDRF_NOTIFYPOSTPAINT = 0x00000010;
        protected const uint CDRF_NOTIFYITEMDRAW = 0x00000020;
        protected const uint CDRF_NOTIFYSUBITEMDRAW = 0x00000020;
        protected const uint CDRF_NOTIFYPOSTERASE = 0x00000040;

        protected const uint CDDS_PREPAINT = 0x00000001;
        protected const uint CDDS_POSTPAINT = 0x00000002;
        protected const uint CDDS_PREERASE = 0x00000003;
        protected const uint CDDS_POSTERASE = 0x00000004;

        protected const uint CDDS_ITEM = 0x00010000;
        protected const uint CDDS_ITEMPREPAINT = (CDDS_ITEM | CDDS_PREPAINT);
        protected const uint CDDS_ITEMPOSTPAINT = (CDDS_ITEM | CDDS_POSTPAINT);
        protected const uint CDDS_ITEMPREERASE = (CDDS_ITEM | CDDS_PREERASE);
        protected const uint CDDS_ITEMPOSTERASE = (CDDS_ITEM | CDDS_POSTERASE);

        protected const uint TBCD_TICS = 0x0001;
        protected const uint TBCD_THUMB = 0x0002;
        protected const uint TBCD_CHANNEL = 0x0003;

        protected const uint CDIS_SELECTED = 0x0001;
        protected const uint CDIS_GRAYED = 0x0002;
        protected const uint CDIS_DISABLED = 0x0004;
        protected const uint CDIS_CHECKED = 0x0008;
        protected const uint CDIS_FOCUS = 0x0010;
        protected const uint CDIS_DEFAULT = 0x0020;
        protected const uint CDIS_HOT = 0x0040;
        protected const uint CDIS_MARKED = 0x0080;
        protected const uint CDIS_INDETERMINATE = 0x0100;

        protected override void WndProc(ref Message m) {
            base.WndProc(ref m);

            if (m.Msg == (WM_REFLECT + WM_NOTIFY)) {
                NMHDR nmhdr = (NMHDR)m.GetLParam(typeof(NMHDR));

                if (nmhdr.code == NM_CUSTOMDRAW) {
                    NMCUSTOMDRAW nmcd = (NMCUSTOMDRAW)m.GetLParam(typeof(NMCUSTOMDRAW));

                    if (nmcd.dwDrawStage == CDDS_PREPAINT) {
                        m.Result = (IntPtr)(CDRF_DODEFAULT | CDRF_NOTIFYITEMDRAW);
                    } else if (nmcd.dwDrawStage == CDDS_ITEMPREPAINT) {
                        m.Result = (IntPtr)(CDRF_DODEFAULT | CDRF_NOTIFYPOSTPAINT);
                    } else if (nmcd.dwDrawStage == CDDS_ITEMPOSTPAINT && nmcd.dwItemSpec == TBCD_CHANNEL) {
                        using (Graphics g = this.CreateGraphics()) {
                            g.FillRectangle(Brushes.Red, nmcd.rc.left + 1, nmcd.rc.top + 1, nmcd.rc.right - nmcd.rc.left - 2, nmcd.rc.bottom - nmcd.rc.top - 2);
                        }
                        m.Result = (IntPtr)CDRF_SKIPDEFAULT;
                    }
                }
            }
        }
    }
}

が、トラックをクリックしないと色が変わらない…
フォーカスを別のコントロールに写すと色が消える…


C++のサンプルはたくさんあったけど、C#のは無かったのはそもそも出来ないからなのだろうか。


一日悩んだけどどうにもならんかった。
もう自分でコントロール作ろう…