2

修飾キー (Shift または Control) を押した状態でクリックすると、WndProc にマウスアップ通知が表示されません。修飾キーなしでそれらが表示され、修飾キーでマウスダウン通知が表示されます。

作成していないコンポーネントでユーザー アクションを追跡しようとしているので、Windows フォームの NativeWindow ラッパー (コンポーネントをラップ) を使用して、WndProc() メソッドから Windows メッセージを取得しています。

受け取った通知を追跡しようとしましたが、表示される唯一の手がかりは WM_CAPTURECHANGED です。WM_LBUTTONDOWN メッセージを受信したときに SetCapture を呼び出してみましたが、役に立ちません。

修飾子なし (ペイント、タイマー、および NCHITTEST メッセージをスキップ):

WM_PARENTNOTIFY
WM_MOUSEACTIVATE
WM_MOUSEACTIVATE
WM_SETCURSOR
WM_LBUTTONDOWN
WM_SETCURSOR
WM_MOUSEMOVE
WM_SETCURSOR
WM_LBUTTONUP

修飾子あり (ペイント、タイマー、および NCHITTEST メッセージをスキップ):

WM_KEYDOWN
WM_PARENTNOTIFY
WM_MOUSEACTIVATE
WM_MOUSEACTIVATE
WM_SETCURSOR
WM_LBUTTONDOWN
WM_SETCURSOR (repeats)
WM_KEYDOWN (repeats)
WM_KEYUP

マウス ボタンを長押しすると、通常は WM_LBUTTONUP 通知を受け取ることができますが、応答性を高めることができるはずです..

編集:マウスボタンを離す前に、目的のコンポーネントの外側でコントロールクリックしてカーソルをそこに移動しようとしましたが、WM_LBUTTONUP通知が表示されるため、マウスダウン時にコンポーネントがマウスをキャプチャしているように見えます. 別のウィンドウがマウスをキャプチャしたときにその通知を受け取る方法はありますか?

ありがとう。

4

5 に答える 5

2

多くの場合、(ネイティブ) Windows コントロールでマウスをクリックすると、「ドラッグ」操作を管理するためにある種のモーダル トラッキング ループに入ります。モーダル ループの期間中、メッセージはメッセージ キューから直接抽出されて処理されます。マウス アップ通知はモーダル ループの終了条件の 1 つになるため、通常はディスパッチされずに消費されます。

デスクトップのどこかをクリックし、マウスをウィンドウの上に移動して放すと、クリックが表示されますか? これは、ある種のモーダル コードがマウス ダウン メッセージでトリガーされていることを示しています。


この問題を回避できる可能性のある 4 つの方法を考えることができます。

  • コントロールがサポートするドラッグ操作の種類を調べて、それを無効にします。ビルトインの WindowProc が、モーダル ドラッグが許可されていないことを認識していれば、モーダル ループに入らないことを願っています。
  • WindowProc がモーダル ドラッグを検出しないようにします。つまり、WM_LBUTTONDOWN メッセージをインターセプトして、チェーン内の次の Windowproc に渡さないでください。
  • SetWindowsHookEx を使用してメッセージ フックをインストールします。

これらのソリューションはすべて非常に Windows API です。管理された環境でそれらがどのように変換されるかわかりません。

于 2010-05-26T05:33:36.550 に答える
0

修飾キーとナビゲーション キーは、デフォルトで OS の内部使用のために予約されています。デフォルトのキーボード ハンドラはそれらを解釈し、必要に応じてそれらに基づいて適切なメッセージを生成します。コントロールがそれらに直接作用したい場合、メッセージを処理する必要があり、必要に応じて、やなどWM_GETDLGCODEの適切なフラグを含む結果が得られるため、キーは通常のメッセージとしてメッセージ キューに配信されます (たとえば、メッセージが生成されます)。 )。DLGC_WANT...DLGC_WANTALLKEYSDLGC_WANTARROWSDLGC_WANTALLKEYSWM_KEYDOWN/UP

于 2010-05-26T20:48:46.580 に答える
0

コンポーネントがマウス メッセージをキャプチャする場合、WM_LBUTTONUP メッセージはラッパーをバイパスしてコンポーネントに直接送信される可能性があります。

于 2010-05-25T21:59:34.983 に答える
0

Application.AddMessageFilterを使用して、ハンドラーをネイティブ メッセージ ポンプに追加します。このようなもの:

[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
private class ZoomGestureHandler : IMessageFilter
{
    private const UInt32 WM_MOUSEWHEEL = 0x20A;
    private const UInt32 MK_CONTROL = 0x08;

    private readonly ImageListView _target;

    public ZoomGestureHandler(ImageListView target)
    {
        _target = target;
    }

    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg != WM_MOUSEWHEEL)
        {
            // Not a mouse wheel message
            return false;
        }

        int wheelDelta = HiWord(m.WParam.ToInt32());
        int keyState = LoWord(m.WParam.ToInt32());

        // Mouse wheel scrolled while the Control key was down
        if ((wheelDelta != 0) && (MK_CONTROL == keyState))
        {
            // Hit test the mouse location
            int xPos = LoWord(m.LParam.ToInt32());
            int yPos = HiWord(m.LParam.ToInt32());

            Point controlLocation = _target.Parent.PointToScreen(_target.Location);
            if ((xPos >= controlLocation.X) && (xPos < (controlLocation.X + _target.Width))
                && (yPos >= controlLocation.Y) && (yPos < (controlLocation.Y + _target.Height)))
            {
                // Determine whether to zoom in or out
                if (wheelDelta > 0)
                {
                    _target.ViewModel.TryZoomIn();
                }
                if (wheelDelta < 0)
                {
                    _target.ViewModel.TryZoomOut();
                }
            }
        }
        return false;
    }

    private static int HiWord(int number)
    {
        if ((number & 0x80000000) == 0x80000000)
            return (number >> 16);
        return (number >> 16) & 0xffff;
    }

    private static int LoWord(int number)
    {
        return number & 0xffff;
    }
}

そのサンプルは特定の目標に固有のものではありませんが、それに合わせて変更できます。たまたま最近書いたものです。

于 2010-05-26T22:02:12.400 に答える
0

WM_LBUTTONUP メッセージを受け取ったら、ハンドラー内で WPARAM キーを確認する必要があります。

http://msdn.microsoft.com/en-us/library/ms645608%28VS.85%29.aspx

于 2010-05-25T18:44:06.533 に答える