2017年4月26日水曜日

C#のListViewの継承

 ListViewを右クリックした時の挙動をちょっと改造してみた。

 右クリックされた時はまずMouseDownRightButtonイベントを呼ぶ。
 次に、CheckFocusedItemの状態に応じ、falseならContextMenuStripを表示、falseならマウスカーソルが選択中のアイテムの上にあるときだけContextMenuStripを表示する。
 また右クリックはMouseDownRightButtonの呼び出しと、ConextMenuStripを表示することのみに使われ、それ以外の処理は行われない。つまり、右クリックで選択が解除されたりということは行われない。
 かなり端折った実装なので、まぁ、こういうこともできますよー程度に。

 ContextMenuStripのOpenedハンドラのsenderにはContextMenuStripが渡されるが、その中のSourceControlに右クリックされたListViewが渡される。ListViewのFocusedItemに選択中のListViewItemが入っている。

 ListViewItemに応じて使用するContextMenuStripを変更したい場合は、MouseDownRightButtonハンドラの中で各自実装したりという感じになると思う。

 もうちょっと色々作り込みたいところだけど、やる気が続かない。

public class ListViewRightButton : ListView
{
    public bool CheckFocusedItem { get; set; }

    protected override void WndProc(ref Message m)
    {
        const int WM_RBUTTONUP = 0x0205;
        const int WM_RBUTTONDOWN = 0x0204;

        if (m.Msg == WM_RBUTTONUP || m.Msg == WM_RBUTTONDOWN)
        {
            Point Client = PointToClient(Cursor.Position);

            MouseDownRightButton?.Invoke(this, new MouseEventArgs(MouseButtons.Right, 0, Client.X, Client.Y, 0));

            if (!CheckFocusedItem)
            {
                ContextMenuStrip?.Show(this, Client.X, Client.Y);
            }
            else if (FocusedItem != null && FocusedItem.Bounds.Contains(Client))
            {
                ContextMenuStrip?.Show(this, Client.X, Client.Y);
            }
        }
        else
        {
            base.WndProc(ref m);
        }
    }

    public event MouseEventHandler MouseDownRightButton;
}

0 件のコメント:

コメントを投稿