2009-12-02 18 views
5

He agregado dinámicamente 20 cuadros de imagen a un panel y me gustaría ver el desplazamiento del panel cuando uso la rueda del mouse. Para implementar esto, he intentado configurar el desplazamiento automático en verdadero en el control del panel. Aquí está el código. Para i As Integer = 1 a 20:Rollo de rueda del mouse en el panel con controles picturebox agregados dinámicamente

 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 

me hizo lo mismo con el botón de control y funciona muy bien. Para i As Integer = 1 a 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 

Funciona para control "botón", pero no para los controles de "etiqueta" "PictureBox" o? ¿Cómo puedo implementar el efecto de desplazamiento usando 'mousewheel'?

Respuesta

6

El panel se desplaza con la rueda del mouse cuando tiene un foco o un control dentro. El problema al que se está enfrentando es que ni el PictureBox ni el panel reciben el foco al hacer clic en él. Si llama al select() en el panel, verá que la rueda del mouse comienza a funcionar nuevamente.

Una posible solución sería la de seleccionar el panel cada vez que el cursor del ratón entra en ella, por el manejo del evento Control.MouseEnter:

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

"Cwick" tiene toda la razón, los mensajes de Windows WM_MOUSWHEEL la notificación a la ventana eso tiene el foco. Funciona cuando pones un botón en el panel porque puede enfocar. Lo siguiente que sucede es que Windows sigue buscando un control Parent para tomar el mensaje. Al botón no le importará, es el panel principal y se desplazará felizmente y consumirá el mensaje.

Aparte de utilizar la capacidad de los controles secundarios para enfocar (tendrá que anularlos y llamar a SetStyle (ControlStyles.Selectable)), podría considerar cambiar la forma en que se maneja este mensaje. Muchas aplicaciones comerciales aparentemente no tienen este problema (navegadores, aplicaciones de Office) porque tienen solo unas pocas ventanas. Las aplicaciones WF generalmente tienen mucho, una para cada control. Hazlo procesando el mensaje temprano, antes de enviarlo al control enfocado. La interfaz IMessageFilter lo permite. Este código de ejemplo se desplaza el control bajo el ratón en lugar del control que tiene el foco:

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); 
    } 
} 

Mira que este código está activo para cualquier ventana en su aplicación. Asegúrate de probarlo y verifica que no confunda demasiado al usuario.

Cuestiones relacionadas