0

スクロールバー付きのユーザー コントロールがあります (スクロールバーは、Panel から継承された含まれているユーザー コントロールとして表示されますが、大きすぎます)。マウスを使用してスクロールする場合はすべて問題ありませんが、マウスホイールでスクロールしようとすると機能しません。

ここでの私の解決策は、のイベントハンドラーで子コントロールにフォーカスを設定することですScroll。これは機能します。さて質問です。これにより、多くの不必要な呼び出しが発生しchildControl.Focus()ますか? これを行うよりきちんとした方法はありますか?

編集:質問が少し不明確だったと思うので、質問を言い換えます:

private void ChildControl_OnScroll(object sender, ScrollEventArgs scrollEventArgs) 
{
    this.childControl.Focus();
}

フォーカスを設定する悪い方法ですか?つまり、スクロールするたびにフォーカスが複数回設定されますか? むしろ、これにより(小さな)パフォーマンスの問題が発生します。

4

3 に答える 3

1

SomeUserControl 内の panel1 のスクロールバー領域がクリックされたときにフォーカスを与える別のアプローチを次に示します。NativeWindow を使用しているため、UserControl のパネルを変更する必要はありません。このようにすると、Focus() は、マウスがスクロールバー領域に移動したときに 1 回だけ呼び出されます。

public partial class SomeUserControl : UserControl
{
    private TrapMouseDownOnScrollArea trapScroll = null;

    public SomeUserControl()
    {
        InitializeComponent();
        this.VisibleChanged += new EventHandler(SomeUserControl_VisibleChanged);
    }

    void SomeUserControl_VisibleChanged(object sender, EventArgs e)
    {
        if (this.Visible && trapScroll == null)
        {
            trapScroll = new TrapMouseDownOnScrollArea(this.panel1);
        }
    }

    private class TrapMouseDownOnScrollArea : NativeWindow
    {
        private Control control = null;
        private const int WM_NCLBUTTONDOWN = 0xA1;

        public TrapMouseDownOnScrollArea(Control ctl)
        {
            if (ctl != null && ctl.IsHandleCreated)
            {
                this.control = ctl;
                this.AssignHandle(ctl.Handle);
            }
        }

        protected override void WndProc(ref Message m)
        {
            switch (m.Msg)
            {
                case WM_NCLBUTTONDOWN:
                    if (this.control != null)
                    {
                        Rectangle screenBounds = control.RectangleToScreen(new Rectangle(0, 0, control.Width, control.Height));
                        if (screenBounds.Contains(Cursor.Position))
                        {
                            control.Focus();
                        }
                    }

                    break;
            }
            base.WndProc(ref m);
        }

    }

}

これはあなたのシナリオではやり過ぎかもしれませんが、低レベルのメッセージをトラップする 1 つの方法を示しています。前に述べたように、Panel から派生させて同じ効果を実現することもできます。IMessageFilter を使用して、アプリケーション レベルでメッセージをトラップすることもできます。

于 2013-05-07T20:04:23.463 に答える
1

MouseWheel イベントは、「バブル」するイベントです。Windows は、マウス カーソルがどこにあるかに関係なく、フォーカスを持つコントロールにそれを送信します。最も典型的な問題は、フォーカスを受け取ることができないコントロールがあることです。たとえば、パネル。

これは、パネルにコントロールを配置すると変わります。これで、コントロールがフォーカスを取得し、MouseWheel メッセージを取得できるようになりました。それは何の役にも立たないので、メッセージはその親に渡されます。これに用途がありますが、パネルは期待どおりにスクロールします。

この回答から、フォーカス可能なパネル コントロールを取得できます。この質問からの一般的な「ブラウザまたはOfficeプログラムのように機能させる」ソリューション

于 2013-05-07T15:47:33.303 に答える