Top / .NET備忘録 / 04.最難関!ComboBox / 09.Locked(ReadOnly) プロパティ その(3)

最後に、リストの選択を抑止します。

ListBoxWindow クラスに処理を入れていきます。

キーボードとマウスの入力は基本的に無視することにし、許可すべきメッセージは

・WM_KEYDOWN の F4
・ウインドウの範囲外のマウスメッセージ

となります。

まずはマウスとキーボードの入力を無視するところをコーディングします。

ListBoxWindow クラスの WndProc の分岐で

    default:
        if (m_Owner.ReadOnly && IsIgnoreMessage(m)) break;
        base.WndProc(ref m);
        break;

のように書きます。

読み取り専用のときは、IsIgnoreMessage でメッセージをチェックし、戻り値が true ならメッセージを握りつぶします。

IsIgnoreMessage では、

    const int
    WM_KEYFIRST = 0x0100,
    WM_KEYDOWN = 0x0100,
    WM_KEYLAST = 0x0108,
    WM_MOUSEFIRST = 0x0200,
    WM_MOUSELAST = 0x020A,
 
    private bool IsIgnoreMessage(Message m)
    {
        if (m.Msg >= WM_KEYFIRST && m.Msg <= WM_KEYLAST)
        {
            return true;
        }
        if (m.Msg >= WM_MOUSEFIRST && m.Msg <= WM_MOUSELAST)
        {
            return true;
        }
        return false;
    }

とし、マウスとキーボードメッセージのすべてを無視します。

WM_KEYDOWN の F4 を許可します。

    if (m.Msg >= WM_KEYFIRST && m.Msg <= WM_KEYLAST)
    {
        if (m.Msg == WM_KEYDOWN && (Keys)m.WParam == Keys.F4) return false;
        return true;
    }

マウスメッセージは、LPARAM に座標が入ってくるので分解します。

    private static int HIWORD(int n)
    {
        return (n >> 16) & 0xffff;
    }
    private static int HIWORD(IntPtr n)
    {
        return HIWORD(unchecked((int)(long)n));
    }
    private static int LOWORD(int n)
    {
        return n & 0xffff;
    }
    private static int LOWORD(IntPtr n)
    {
        return LOWORD(unchecked((int)(long)n));
    }

このコードは .Net のソースが元ネタ(^_^;)
HIWORD, LOWORD の定義はいっぱいあったのですが、いちばんよさそうなのを選択しました。
これを使って、座標を分解します。

    int x = LOWORD(m.LParam);
    int y = HIWORD(m.LParam);

この座標が、リストウインドウ内になければ、メッセージを許可します。

リストウインドウの範囲を求める API 関数を定義します。

    [DllImport("user32.dll")]
    private static extern bool GetClientRect(HandleRef hwnd, ref Rectangle lpRect); 

これを使って、リストウインドウの範囲を求め、範囲外なら false を返します。

    Rectangle clientRect = new Rectangle();
    if (GetClientRect(new HandleRef(this, this.Handle), ref clientRect))
    {
        int x = LOWORD(m.LParam);
        int y = HIWORD(m.LParam);
        if (!clientRect.Contains(x, y)) return false;
    }

IsIgnoreMessage は、こうなりました。

    private bool IsIgnoreMessage(Message m)
    {
        if (m.Msg >= WM_KEYFIRST && m.Msg <= WM_KEYLAST)
        {
            if (m.Msg == WM_KEYDOWN && (Keys)m.WParam == Keys.F4) return false;
            return true;
        }
        if (m.Msg >= WM_MOUSEFIRST && m.Msg <= WM_MOUSELAST)
        {
            Rectangle clientRect = new Rectangle();
            if (GetClientRect(new HandleRef(this, this.Handle), ref clientRect))
            {
                int x = LOWORD(m.LParam);
                int y = HIWORD(m.LParam);
                if (!clientRect.Contains(x, y)) return false;
            }
            return true;
        }
        return false;
    }



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   最終更新のRSS
Last-modified: 2013-03-15 (金) 12:33:43 (1562d)