Top / .NET備忘録 / 04.最難関!ComboBox / 04.Scroll イベント

Scroll イベントは、リストボックスをサブクラス化して WM_VSCROLL メッセージを捕まえます。

まずはイベントの定義

    public event EventHandler Scroll;
 
    protected virtual void OnScroll(EventArgs e)
    {
        if (Scroll != null) Scroll(this, e);
    }

サブクラス化については、NativeWindow クラスを使用します。
NativeWindow を継承した ListBoxWindow クラスを作成し、リストボックスのウインドウハンドルをアサインすると、サブクラス化が簡単にできます。

    const int WM_VSCROLL = 0x0115;
 
    private class ListBoxWindow : NativeWindow
    {
        VBComboBox m_Owner;
 
        public ListBoxWindow(VBComboBox owner)
        {
            m_Owner = owner;
            this.AssignHandle(owner.ListBoxHandle);
        }
 
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_VSCROLL:
                    base.WndProc(ref m);
                    m_Owner.OnScroll(EventArgs.Empty);
                    break;
 
                default:
                    base.WndProc(ref m);
                    break;
            }
        }
    }

ListBoxWindow クラスを作成、解放する処理を作成します。
EditBox もサブクラス化する予定なので、名前を 〜 ChildWindows としておきます。

    private ListBoxWindow m_ListBoxWindow = null;
 
    private void AssignChildWindows()
    {
        if (ListBoxHandle != IntPtr.Zero)
        {
            m_ListBoxWindow = new ListBoxWindow(this);
        }
    }
 
    private void ReleaseChildWindows()
    {
        if (m_ListBoxWindow != null)
        {
            m_ListBoxWindow.ReleaseHandle();
            m_ListBoxWindow = null;
        }
    }

あとは、これをどの処理に組み込むか、なのですが、.Net のソースを見ると、OnHandleCreated で作成して WM_NCDESTROY メッセージで解放しているようです。

OnHandleCreated の最後に AssignChildWindows() を追加します。

    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
 
        HandleRef hr = new HandleRef(this, this.Handle);
        ComboBoxInfo ci = new ComboBoxInfo();
 
        if (GetComboBoxInfo(hr, ci))
        {
            m_EditBoxHandle = ci.EditBoxHandle;
            m_ListBoxBoxHandle = ci.ListBoxHandle;
        }
        else
        {
            m_EditBoxHandle = IntPtr.Zero;
            m_ListBoxBoxHandle = IntPtr.Zero;
        }
 
        AssignChildWindows();
    }

VBComboBox クラスの WndProc の分岐を追加します。

    const int
    WM_NCDESTROY = 0x0082;
 
    // 子ウインドウをリリース
    case WM_NCDESTROY:
        base.WndProc(ref m);
        ReleaseChildWindows();
        break;



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   最終更新のRSS
Last-modified: 2013-03-05 (火) 23:02:55 (1625d)