0

ShowDialogではなく、visibleプロパティをtrueに設定することで表示されるフォームがあります。これは、ドロップダウンのように動作するためです。

フォームは、を使用してマウスフックをインストールしますSetWindowsHookEx(WH_MOUSE, ...)

ドロップダウンの外側でマウスがクリックされたかどうかを検出し、クリックされた場合は、HookProcメソッドで1を返し、ドロップダウンを閉じます。

HookProc奇妙なことに、ドロップダウンの外側をクリックしてテキストボックスに移動すると、ドロップダウンが閉じた後も、メソッドで処理されていても、テキストボックスはマウスクリックを受け取ります。

見知らぬ人になります...ラベルまたはボタンをクリックすると、ドロップダウンが閉じた後、期待どおりにマウスクリックが表示されません。

何が起こっているのか分かりますか?

ETA 2:

以下の私のコードはすべて無視してかまいません。さらに調査したところ、この動作は、ドロップダウンタイプのフォームを実装する少なくとも1つのフレームワークコントロールで示されていることがわかりました。

複製するには、フォームを作成し、プロパティグリッド、ボタン、テキストボックス、およびラベルを追加します。プロパティグリッドの選択したオブジェクトをフォントに設定します。

フォームを実行し、フォント名を選択します。ドロップダウンリストが表示されます。次に、フォームのテキストボックスをクリックします。テキストボックスのクリックイベントが発生します。ただし、ボタンやラベルについては同じことは起こりません。

どうしたの?

ETA 1:

Visual C#.NETでWindowsフックを設定して何が起こっているのかを示す方法の基本的なコードを次に示します。コンバーターを使用してコードをC#に変換し直しましたが、問題がないことを願っています。よくわかりませんが、に置き換える必要があるかもしれませConsole.WriteLineDebug.WriteLine

2つのフォームを作成Form1しますDropDown

(1)VB.NET

Form1、ボタン、ラベル、テキストボックス、および次のコードを追加します。

Imports System.Runtime.InteropServices

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Console.WriteLine("Button1_Click")
        Dim dd As New DropDown
        dd.Visible = True
        Do While dd.Visible
            Application.DoEvents()
            MsgWaitForMultipleObjectsEx(0, IntPtr.Zero, 250, &HFF, 4)
        Loop
    End Sub

    <DllImport("user32.dll", CharSet:=CharSet.Auto, ExactSpelling:=True)> _
    Public Shared Function MsgWaitForMultipleObjectsEx(ByVal nCount As Integer, ByVal pHandles As IntPtr, ByVal dwMilliseconds As Integer, ByVal dwWakeMask As Integer, ByVal dwFlags As Integer) As Integer
    End Function

    Private Sub Label1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Label1.Click
        Console.WriteLine("Label1_Click")
    End Sub

    Private Sub TextBox1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles TextBox1.Click
        Console.WriteLine("TextBox1_Click")
    End Sub

End Class

ドロップダウンに、次のコードを配置します。

Imports System.Runtime.InteropServices

Public Class DropDown

    Public Delegate Function HookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer

    Private hHook As Integer = 0
    Public Const WH_MOUSE As Integer = 7
    Private MouseHookProcedure As HookProc

    <StructLayout(LayoutKind.Sequential)> _
    Public Class POINT
        Public x As Integer
        Public y As Integer
    End Class

    <StructLayout(LayoutKind.Sequential)> _
    Public Class MouseHookStruct
        Public pt As POINT
        Public hwnd As Integer
        Public wHitTestCode As Integer
        Public dwExtraInfo As Integer
    End Class

    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal lpfn As HookProc, ByVal hInstance As IntPtr, ByVal threadId As Integer) As Integer
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function UnhookWindowsHookEx(ByVal idHook As Integer) As Boolean
    End Function

    <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _
    Public Shared Function CallNextHookEx(ByVal idHook As Integer, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
    End Function

    Protected Overrides Sub OnDeactivate(ByVal e As System.EventArgs)
        MyBase.OnDeactivate(e)
        UnhookWindowsHookEx(hHook)
        hHook = 0
    End Sub

    Public Sub New()
        InitializeComponent()
        MouseHookProcedure = New HookProc(AddressOf MouseHookProc)
        hHook = SetWindowsHookEx(WH_MOUSE, MouseHookProcedure, New IntPtr(0), AppDomain.GetCurrentThreadId())
    End Sub

    Public Function MouseHookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Integer
        Dim MyMouseHookStruct As MouseHookStruct = DirectCast(Marshal.PtrToStructure(lParam, GetType(MouseHookStruct)), MouseHookStruct)
        If nCode < 0 Then
            Return CallNextHookEx(hHook, nCode, wParam, lParam)
        Else
            Select Case CInt(wParam)
                Case &H21, &HA1, &HA4, &H204, &H207, &HA7, &H201
                    Me.Visible = False
                    Return 1
            End Select
            Return CallNextHookEx(hHook, nCode, wParam, lParam)
        End If
    End Function

End Class

(2)C#

Form1に、ボタン、ラベル、テキストボックス、および次のコードを追加します。

using System.Runtime.InteropServices;

public class Form1
{
    public Form1()
    {
        InitializeComponent();
        Button1.Click += Button1_Click;
        Label1.Click += Label1_Click;
        TextBox1.Click += TextBox1_Click;
    }

    private void Button1_Click(System.Object sender, System.EventArgs e)
    {
        Console.WriteLine("Button1_Click");
        DropDown dd = new DropDown();
        dd.Visible = true;
        while (dd.Visible) {
            Application.DoEvents();
            MsgWaitForMultipleObjectsEx(0, IntPtr.Zero, 250, 0xff, 4);
        }
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    public static extern int MsgWaitForMultipleObjectsEx(int nCount, IntPtr pHandles, int dwMilliseconds, int dwWakeMask, int dwFlags);

    private void Label1_Click(object sender, System.EventArgs e)
    {
        Console.WriteLine("Label1_Click");
    }

    private void TextBox1_Click(object sender, System.EventArgs e)
    {
        Console.WriteLine("TextBox1_Click");
    }
}

ドロップダウンに、次のコードを配置します。

using System.Runtime.InteropServices;

public class DropDown
{
    public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

    private int hHook = 0;
    public const int WH_MOUSE = 7;
    private HookProc MouseHookProcedure;

    [StructLayout(LayoutKind.Sequential)]
    public class POINT
    {
        public int x;
        public int y;
    }

    [StructLayout(LayoutKind.Sequential)]
    public class MouseHookStruct
    {
        public POINT pt;
        public int hwnd;
        public int wHitTestCode;
        public int dwExtraInfo;
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    public static extern bool UnhookWindowsHookEx(int idHook);

    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);

    protected override void OnDeactivate(System.EventArgs e)
    {
        base.OnDeactivate(e);
        UnhookWindowsHookEx(hHook);
        hHook = 0;
    }

    public DropDown()
    {
        InitializeComponent();
        MouseHookProcedure = new HookProc(MouseHookProc);
        hHook = SetWindowsHookEx(WH_MOUSE, MouseHookProcedure, new IntPtr(0), AppDomain.GetCurrentThreadId());
    }

    public int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
    {
        MouseHookStruct MyMouseHookStruct = (MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseHookStruct));
        if (nCode < 0) {
            return CallNextHookEx(hHook, nCode, wParam, lParam);
        }
        else {
            switch ((int)wParam) {
                case 0x21:
                case 0xa1:
                case 0xa4:
                case 0x204:
                case 0x207:
                case 0xa7:
                case 0x201:
                    this.Visible = false;
                    return 1;
            }
            return CallNextHookEx(hHook, nCode, wParam, lParam);
        }
    }
}
4

1 に答える 1

1

この問題は、マウスダウンメッセージをフィルタリングするが、マウスアップメッセージはフィルタリングしないために発生します。次のように修正できます。

  Select Case CInt(wParam)
    Case &HA1, &HA4, &HA7, &H201, &H204, &H207
      Me.Capture = True
    Case &HA2, &hA5, &HA8, &H202, &H205, &H208
      Me.Visible = False
  End Select

代わりにIMessageFilterの実装を検討してください。

于 2009-11-15T15:49:10.123 に答える