5

パネルに 20 個のピクチャボックスを動的に追加しました。マウス ホイールを使用したときにパネルがスクロールするのを確認したいと思います。これを実装するために、パネル コントロールで autoscroll を true に設定しようとしました。これがコードです。i As Integer = 1 から 20 の場合:

        Dim b As New PictureBox()
        b.Image = Nothing
        b.BorderStyle = BorderStyle.FixedSingle
        b.Text = i.ToString()
        b.Size = New Size(60, 40)
        b.Location = New Point(0, (i * b.Height) - b.Height)
        b.Parent = Panel1
        Panel1.Controls.Add(b)
    Next

ボタンコントロールでも同じことをしましたが、うまくいきました。i As Integer = 1 から 100 の場合:

        Dim b As New Button()

        b.Text = i.ToString()
        b.Size = New Size(60, 40)
        b.Location = New Point(0, (i * b.Height) - b.Height)
        b.Parent = Panel1
        Panel1.Controls.Add(b)
    Next

「ボタン」コントロールでは機能しますが、「ピクチャボックス」または「ラベル」コントロールでは機能しませんか? 「マウスホイール」を使用してスクロール効果を実装するにはどうすればよいですか?

4

2 に答える 2

6

パネルまたはパネル内のコントロールにフォーカスがある場合、パネルはマウスホイールでスクロールします。あなたが遭遇している問題は、クリックしても PictureBox もパネルもフォーカスを受けないことです。パネルを呼び出すselect()と、マウス ホイールが再び機能し始めることがわかります。

考えられる解決策の 1 つは、Control.MouseEnter イベントを処理して、マウス カーソルが入るたびにパネルを選択することです。

void panel1_MouseEnter(object sender, EventArgs e)
{
    panel1.select();
}
于 2009-12-02T00:47:57.933 に答える
3

「cwick」は非常に正しいです。Windowsは、フォーカスのあるウィンドウにWM_MOUSWHEEL通知を送信します。フォーカスを取得できるため、パネルにボタンを配置すると機能します。次に発生するのは、Windowsがメッセージを受け取るための親コントロールを探し続けることです。ボタンはそれを気にしません、それは親がパネルであり、それは喜んでスクロールしてメッセージを消費します。

子コントロールのフォーカスを取得する機能を使用してドクターする以外に(子コントロールをオーバーライドしてSetStyle(ControlStyles.Selectable)を呼び出す必要があります)、このメッセージの処理方法を変更することを検討できます。多くの商用アプリ(ブラウザー、Officeアプリ)は、ウィンドウが少ないため、この問題は発生していないようです。WFアプリには通常、コントロールごとに1つずつ、たくさんあります。メッセージがフォーカスされたコントロールに送信される前に、メッセージを早期に処理することによってこれを行います。IMessageFilterインターフェースはこれを可能にします。このサンプルコードは、フォーカスのあるコントロールではなく、マウスの下でコントロールをスクロールします。

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsApplication1 {
  public partial class Form1 : Form, IMessageFilter {
    public Form1() {
      InitializeComponent();
      Application.AddMessageFilter(this);
    }

    public bool PreFilterMessage(ref Message m) {
      if (m.Msg == 0x20a) {
        // WM_MOUSEWHEEL, find the control at screen position m.LParam
        Point pos = new Point(m.LParam.ToInt32());
        IntPtr hWnd = WindowFromPoint(pos);
        if (hWnd != IntPtr.Zero && hWnd != m.HWnd && Control.FromHandle(hWnd) != null) {
          SendMessage(hWnd, m.Msg, m.WParam, m.LParam);
          return true;
        }
      }
      return false;
    }

    // P/Invoke declarations
    [DllImport("user32.dll")]
    private static extern IntPtr WindowFromPoint(Point pt);
    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);
  }
}

このコードは、アプリのどのウィンドウでもアクティブであることに注意してください。必ず試して、ユーザーを混乱させすぎないことを確認してください。

于 2009-12-02T01:42:34.257 に答える