【问题标题】:Mousewheel scroll in panel with dynamically added picturebox controls?带有动态添加的图片框控件的面板中的鼠标滚轮滚动?
【发布时间】:2010-12-22 05:47:42
【问题描述】:

我已将 20 个图片框动态添加到面板中,并希望在使用鼠标滚轮时看到面板滚动。为了实现这一点,我尝试在面板控件上将自动滚动设置为 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 作为整数 = 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

它适用于“按钮”控件,但不适用于“图片框”或“标签”控件? 如何使用“鼠标滚轮”实现滚动效果?

【问题讨论】:

    标签: vb.net winforms scroll panel picturebox


    【解决方案1】:

    当面板或其中的控件具有焦点时,面板会随鼠标滚轮滚动。您遇到的问题是,当您单击 PictureBox 和面板时,它都没有获得焦点。如果你在面板上调用select(),你会看到鼠标滚轮又开始工作了。

    一种可能的解决方案是在鼠标光标进入面板时通过处理 Control.MouseEnter 事件来选择面板:

    void panel1_MouseEnter(object sender, EventArgs e)
    {
        panel1.select();
    }
    

    【讨论】:

      【解决方案2】:

      "cwick" 非常正确,Windows 将 WM_MOUSWHEEL 通知发布到具有焦点的窗口。当您在面板中放置一个按钮时它会起作用,因为它可以获得焦点。接下来发生的事情是 Windows 一直在寻找父控件来接收消息。 Button 不会关心它,它的 Parent 是面板,它会愉快地滚动并使用消息。

      除了修改子控件获取焦点的能力(您必须覆盖它们并调用 SetStyle(ControlStyles.Selectable)),您可以考虑更改处理此消息的方式。许多商业应用程序(浏览器、Office 应用程序)似乎没有这个问题,因为它们只有几个窗口。 WF 应用程序通常有很多,每个控件一个。通过在消息被发送到焦点控件之前及早处理消息来做到这一点。 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);
        }
      }
      

      请注意,此代码对您应用中的 any 窗口有效。确保您尝试并验证它不会让用户感到太多困惑。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-25
        • 1970-01-01
        • 1970-01-01
        • 2010-12-08
        • 2014-02-11
        相关资源
        最近更新 更多