4

WinForms GroupBoxコントロールはMouseMoveをサポートしていません(または少なくとも一貫性がありません)。その理由がわかりません。

Controlの子孫であるため、MouseMoveイベントがありますが、GroupBoxは明示的にそれを再導入するBrowsable(false)ため、プロパティグリッドには表示されません。FlatStyleがStandardのままである限り、実行時にMouseMoveイベントをフックでき、場合によっては機能します。GroupBoxのFlatStyleがSystemに設定されている場合、MouseMoveイベントはまったく発生しません。

リフレクターは私に手がかりを与えてくれませんでした。GroupBoxコンストラクターは、奇妙なコントロールスタイルを設定していないようです。また、GroupBoxは、MouseMoveをオーバーライドして、baseの呼び出しに失敗するような愚かなことは何もしません。

DelphiグループボックスはOnMouseMoveを適切にサポートしているため、これもWinForms固有の制限のようです。 訂正:Delphiとの比較は無効です。Delphiグループボックスは、実際には標準のBM_GROUPBOXコントロールではありません。このような奇妙なグループボックスの動作を実際に継承することなく、グループボックスのように見えるようにペイントされています。したがって、これはWindowsグループボックスコントロールの制限である可能性がありますが、どこにも文書化されていません。

WinForms GroupBoxがMouseMoveをサポートしないのはなぜですか?

4

4 に答える 4

5

このスレッドによると、標準のWindowsグループボックス(つまり、BS_GROUPBOXスタイルのBUTTONコントロール)は、WM_NCHITTESTに応答してHTTRANSPARENTを返すように見えます。コントロールは透過的であると主張しているため、Windowsは代わりにmouse-moveイベントをその親ウィンドウに送信します。

スレッドは、WM_NCHITTESTを自分で処理してHTCLIENTを返すと、グループボックスがマウス移動イベントを取得することを確認します。彼らはMFCを使用していますが、おそらくWinFormsでも機能します。

はっきりしないのは、WindowsがデフォルトでHTTRANSPARENTを返す理由ですが、少なくとも問題は個別に確認されています。

于 2010-01-01T17:04:45.027 に答える
2

これはReflectorで確認できます。キーのプロパティは、CreateParamsと内部のOwnerDrawプロパティです。FlatStyle = Systemを設定した場合を除き、GroupBoxは通常OwnerDraw=trueで動作します。次に、昔ながらのWindowsグループボックスを取得します。これは、クラス名がBUTTONで、BS_GROUPBOXスタイルビットがオンになっているウィンドウです。

Spy ++を見ると、コントロールがマウスメッセージをまったく受け取らないことがわかります。なぜそうなのかわからないので、SDKドキュメントには記載されていません。これは、すべてのサイクルがカウントされたWindows2.xにまでさかのぼると思います。ただし、MouseMoveイベントが非表示になっている理由は説明されており、システムスタイルが選択されている場合は発生しません。クリックとアップ/ダウンについても同じです。FlatStyleプロパティセッターは、Control.UserMouseコントロールスタイルもオフにすることで、実際にそれを固定します。

とにかく、マウスメッセージが必要な場合は、システムスタイルを避ける必要があります。

于 2009-11-10T20:45:41.190 に答える
1

特定のコントロールの多くのイベントには、VSの[イベント]タブ([プロパティ]の下)からアクセスできないことに気付きました。親フォームのデザイナで、次の場所にあるイベントハンドラを手動で割り当てることができますInitializeComponents()

this.groupBox1.MouseMove += new MouseEventHandler(this.groupBox1_MouseMove);

これにより、次のメソッドがトリガーされます。

private void groupBox1_MouseMove(object sender, MouseEventArgs e)
{
    //doodle the stuff you want to happen after the trigger here
};
于 2018-01-12T11:22:45.870 に答える
0

グループボックスは、その中に他のコントロールを格納する静的コントロールです。正しくレイアウトされている場合、ユーザーインターフェイスを直感的にするために、純粋に物事を「グループ化」するように設計されています。したがって、GroupBoxに代わって使用できるイベントはほとんどありません。

GroupBoxから継承される新しいクラスを作成し、それをサブクラス化して、マウス移動イベントをインターセプトできる場合があります。私が以前に使用した非常に便利なクラスがあり、サブクラス化を実行し、MouseMoveのイベントをトリガーするのは本当に簡単です。

サブクラス化がどのように機能するかを確認するには、ここを見てください...わかりました。VB.NETで記述されていますが、必要に応じてC#に変換するのは非常に簡単です。私が想像するコードは次のようになります。 : 注:私が含めたこのコードは私の頭のてっぺんなので、これにエラーがあるかもしれません...しかし、それがその要点です。

編集:ジョーホワイトのコメントに応えて、私は改訂されたコードを含めました、そしてそれはWM_MOUSEMOVEを送ります...私がVS2008Proの下でこれをどのように再現したかについて以下のステップを見てください。

    パブリッククラスMyGroupBox:System.Windows.Forms.GroupBox
    {{
        プライベートサブクラスsc;
        private const int WM_MOUSEMOVE = 0x200;
        パブリックデリゲートvoidMyMouseMoveEventHandler(object sender、System.EventArgs e);
        パブリックイベントMyMouseMoveEventHandlerMyMouseMove;
        public MyGroupBox()
            : ベース()
        {{
            sc = new SubClass(this.Handle、true);
            sc.SubClassedWndProc + = new SubClass.SubClassWndProcEventHandler(sc_SubClassedWndProc);
        }

        保護されたオーバーライドvoidDispose(bool disposed)
        {{
            if(sc.SubClassed)
            {{
                sc.SubClassedWndProc-= new SubClass.SubClassWndProcEventHandler(sc_SubClassedWndProc);
                sc.SubClassed = false;
            }
            base.Dispose(disposed);
        }
        private void OnMyMouseMove()
        {{
            if(this.MyMouseMove!= null)this.MyMouseMove(this、System.EventArgs.Empty);
        }
        void sc_SubClassedWndProc(refメッセージm)
        {{
            if(m.Msg == WM_MOUSEMOVE)this.OnMyMouseMove();
        }

    }

    #regionサブクラス分類ハンドラークラス
    パブリッククラスサブクラス:System.Windows.Forms.NativeWindow
    {{
        パブリックデリゲート無効
          SubClassWndProcEventHandler(ref System.Windows.Forms.Message m);
        パブリックイベントSubClassWndProcEventHandlerSubClassedWndProc;
        private bool IsSubClassed = false;

        public SubClass(IntPtr Handle、bool _SubClass)
        {{
            base.AssignHandle(Handle);
            this.IsSubClassed = _SubClass;
        }

        public bool SubClassed
        {{
            get {return this.IsSubClassed; }
            set {this.IsSubClassed = value; }
        }

        保護されたオーバーライドvoidWndProc(refメッセージm)
        {{
            if(this.IsSubClassed)
            {{
                OnSubClassedWndProc(ref m);
            }
            base.WndProc(ref m);
        }

        #regionHiWordメッセージクラッカー
        public int HiWord(int Number)
        {{
            return((Number >> 16)&0xffff);
        }
        #endregion

        #regionLoWordメッセージクラッカー
        public int LoWord(int Number)
        {{
            return(Number&0xffff);
        }
        #endregion

        #regionMakeLongメッセージクラッカー
        public int MakeLong(int LoWord、int HiWord)
        {{
            return(HiWord << 16)| (LoWord&0xffff);
        }
        #endregion

        #regionMakeLParamメッセージクラッカー
        public IntPtr MakeLParam(int LoWord、int HiWord)
        {{
            return(IntPtr)((HiWord << 16)|(LoWord&0xffff));
        }
        #endregion

        private void OnSubClassedWndProc(ref Message m)
        {{
            if(SubClassedWndProc!= null)
            {{
                this.SubClassedWndProc(ref m);
            }
        }
    }
    #endregion

  1. 単純な空白のフォームを作成します。
  2. ツールパレットからグループボックスをドラッグしてフォームにドロップします。デフォルト名は次のようになります。groupBox1
  3. フォームのデザイナーコードで、次のようにしてコード参照を変更します。
    System.Windows.Forms.GroupBox groupBox1;
    WindowsApplication.MyGroupBox groupBox1;
  4. メソッド内InitializeComponent()で、GroupBoxのインスタンス化を次のように変更します。
    this.groupBox1 = new WindowsApplication.MyGroupBox();
  5. 保存してコンパイルするだけです。
  6. MyMouseMoveデザイナウィンドウに戻り、グループボックスをクリックして、プロパティツールボックス内でイベントを探し、接続します。
  7. イベントハンドラは次のようになります。
        private void groupBox1_MyMouseMove(object sender、EventArgs e)
        {{
            System.Diagnostics.Debug.WriteLine( "MyMouseMove!");
        }

アプリケーションを実行すると、グループボックス内でマウスを動かすたびに、「MyMouseMove!」という出力が表示されます。

これがあなたにヒントを与えることを願っています、よろしく、トム。

于 2010-01-01T18:06:40.560 に答える