SOLVED - Mausrad ansprechen



  • Hallo.

    Ich programmiere gerade eine abgeleitete Picturebox, in welche ich ein Bitmap laden können möchte um dieses dann über das Mausrad zu zoomen und über die gehaltene, mittlere Maustaste zu verschieben.

    Ich habe vieles noch nicht implementiert, aber schonmal das Ansprechen des Mausrades klappt nicht. Könnt ihr mir sagen, weshalb? Nachfolgend der code:

    public class DynamicPictureBox : System.Windows.Forms.PictureBox
        {
            private double ZoomFactor = 1.0;
            private System.Drawing.Image DisplayedImage = null;
            private System.Windows.Forms.ContextMenuStrip MyContextMenuStrip = null;
    
            public DynamicPictureBox() : base()
            {
                System.Windows.Forms.ToolStripItem ti;
    
                #region Settings
                this.Dock = System.Windows.Forms.DockStyle.Fill;
                this.BackColor = System.Drawing.Color.White;
                this.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
                #endregion
    
                #region Context menu strip
                MyContextMenuStrip = new System.Windows.Forms.ContextMenuStrip();
                ti = MyContextMenuStrip.Items.Add("Load picture");
                ti.Click += new EventHandler((sender, e) => DynamicPictureBoxContextMenuFunctions.loadPicture_Click(sender, e, this));
    
                ti = MyContextMenuStrip.Items.Add("Clear picture");
                ti.Click += new EventHandler((sender, e) => DynamicPictureBoxContextMenuFunctions.clearPicture_Click(sender, e, this));
    
                this.ContextMenuStrip = this.MyContextMenuStrip;
                #endregion
    
                this.MouseDown += new System.Windows.Forms.MouseEventHandler(DynamicPictureBox_MouseDown);
                this.MouseWheel += new System.Windows.Forms.MouseEventHandler(DynamicPictureBox_MouseWheel);//Handler im Konstructor definiert. Wird auch ausgeführt
            }
    
            public void LoadBitMap(string Filename)
            {
                this.DisplayedImage = System.Drawing.Image.FromFile(Filename);
                this.Image = DisplayedImage;    
            }
    
            public void ClearImage() { this.Image = null; this.DisplayedImage = null; }
    
            public System.Drawing.Bitmap GetDisplayedBitmap() { return new System.Drawing.Bitmap(DisplayedImage); }
    
            private void DynamicPictureBox_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
            {
                MouseInteraction.MouseDown(e);
            }
    
            private void DynamicPictureBox_MouseWheel(object sender, System.Windows.Forms.MouseEventArgs e)
            {
                System.Windows.Forms.MessageBox.Show("Mouse wheel moved!");
                MouseInteraction.MouseWheele(e, ref this.ZoomFactor, this);
            }
        }
    
    public static class MouseInteraction
        {
            public static void MouseWheele(System.Windows.Forms.MouseEventArgs e, ref double ZoomFactor, DynamicPictureBox DPB)
            {
                System.Drawing.Size NewSize;
                ZoomFactor *= Math.Exp(0.1 * (double)e.Delta / 120.0);
                System.Windows.Forms.MessageBox.Show("New zoomfactor: " + ZoomFactor.ToString());
                NewSize = DPB.Size;
                NewSize.Height = (int)((double)NewSize.Height * ZoomFactor);
                NewSize.Width = (int)((double)NewSize.Width * ZoomFactor);
    
                DPB.Image = (System.Drawing.Image)new System.Drawing.Bitmap(DPB.GetDisplayedBitmap(), NewSize);
            }
    
            public static void MouseDown(System.Windows.Forms.MouseEventArgs e)
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Left)
                {
                    System.Windows.Forms.MessageBox.Show("Left mouse button clicked!");
                }else if(e.Button == System.Windows.Forms.MouseButtons.Middle)
                {
                    System.Windows.Forms.MessageBox.Show("Central mouse button clicked!");
                }
    
            }
    
            public static void ClickMove(System.Windows.Forms.MouseEventArgs e)
            {
    
            }
        }
    

    Ich würde, nach Zeile 49 im ersten, und Zeile 7 im zweiten Codeabschnitt jetzt erwarten, dass beim Bewegen des Mausrades sich einiges tut. Ist aber nicht der Fall. Bei den Maustasten (linke und mittlere - siehe "MouseDown" - funktioniert es ja auch.

    Vielen Dank für Eure Anregungen.



  • Ok, habe die Lösung. Scheinbar funktioniert das Mausrad nur, wenn das Steuerelement Focused ist.
    Also braucht man noch folgendes:

    public DynamicPictureBox(Main fCentral) : base()
            {
                Central = fCentral;
    
                this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.DynamicPictureBox_MouseWheel);
                this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.DynamicPictureBox_MouseDown);
                this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.DynamicPictureBox_MoveMouseDown);
                this.MouseHover += new EventHandler(this.DynamicPictureBox_MouseHover); //new!!!
            }
    
    private void DynamicPictureBox_MouseHover(object sender, EventArgs e)
            {
                this.Focus();
            }
    

    Und schon funktioniert es 🙂



  • Wenn ich mich jetzt nicht grob irre hat das aber den Nachteil dass ... naja, das Control dann eben immer den Fokus bekommt. D.h. jedes andere Control den Fokus verliert. Was vermutlich nicht unbedingt immer das ist was man möchte.

    Ich vermute aber dass z.B. das Fenster (also die "Form") auch die Mouse-Wheel Events bekommt, so lange irgend ein Control im Fenster den Fokus hat. Bzw. es muss auch noch andere Möglichkeiten geben -- schliesslich gibt es ja Windows-Programme die Mouse-Wheel Drehen immer mitbekommen, auch wenn ihr Fenster nicht den Fokus hat.

    K.A. wie wichtig dir diese Dinge sind, aber wäre es mein Projekt würde ich da vermutlich nochmal ein Bisschen Zeit investieren.

    ps: Die übliche Variante scheint zu sein das über IMessageFilter zu machen, siehe z.B.:

    http://stackoverflow.com/questions/87134/c-sharp-listview-mouse-wheel-scroll-without-focus

    Nur nicht vergessen dass man den Message-Filter beim Schliessen des Fensters/Controls auch wieder entfernen sollte (-> Application.RemoveMessageFilter - wird leider in den Beispielen nirgends gezeigt).



  • Das ist auch nur bei einigen Steuerelementen so. Nutze ich beispielsweise ein SimpleOGLObject (aus dem Tao-Framework), so ist der explizite Fokus gar nicht notwendig.