2009-12-02 16 views
5

J'ai ajouté dynamiquement 20 images à un panneau et j'aimerais que le panneau défile lorsque j'utilise la molette de la souris. Pour implémenter cela, j'ai essayé de mettre l'autoscroll à true sur le panneau de contrôle. Voici le code. Pour i As Integer = 1 à 20:La molette de la souris fait défiler le panneau avec des contrôles de la zone d'image ajoutés dynamiquement?

 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 

J'ai fait la même chose avec bouton de contrôle et il fonctionne très bien. Pour 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 

Il fonctionne pour le contrôle "bouton", mais pas pour le "picturebox" ou "contrôles d'étiquettes"? Comment puis-je implémenter l'effet de défilement en utilisant 'mousewheel'?

Répondre

6

Le panneau défile à l'aide de la roulette de la souris lorsque celui-ci ou un contrôle interne est activé. Le problème que vous rencontrez est que ni PictureBox ni le panneau ne reçoit le focus lorsque vous cliquez dessus. Si vous appelez select() sur le panneau, vous verrez que la roulette de la souris recommence à fonctionner.

Une solution possible serait de sélectionner le panneau à chaque fois que le curseur de la souris entre, en manipulant l'événement Control.MouseEnter:

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

« cwick » est tout à fait raison, les messages de Windows la notification de WM_MOUSWHEEL à la fenêtre qui a l'accent. Cela fonctionne quand vous mettez un bouton dans le panneau parce qu'il peut obtenir le foyer. La prochaine chose qui arrive est que Windows ne cesse de chercher un contrôle Parent pour prendre le message. Le bouton ne s'en souciera pas, c'est Parent qui est le panneau et il fera joyeusement défiler et consommer le message.

Outre le fait de pouvoir traiter la fonction de contrôle des enfants (vous devrez les ignorer et appeler SetStyle (ControlStyles.Selectable)), vous pouvez envisager de modifier la façon dont ce message est traité. De nombreuses applications commerciales ne semblent pas avoir ce problème (les navigateurs, les applications Office) car ils n'ont que quelques fenêtres. Les applications WF en ont généralement beaucoup, une pour chaque contrôle. Faites-le en traitant le message plus tôt, avant qu'il ne soit envoyé au contrôle ciblé. L'interface IMessageFilter le permet. Cet exemple de code fait défiler le contrôle sous la souris au lieu du contrôle qui a le focus:

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

Prenez garde que ce code est actif pour une fenêtre dans votre application. Assurez-vous de l'essayer et de vérifier qu'il ne va pas trop perturber l'utilisateur.