Comment faire en sorte qu'un panneau fasse défiler par programme pour exposer son AutoSize picturebox

StackOverflow https://stackoverflow.com/questions/1803191

  •  05-07-2019
  •  | 
  •  

Question

Un bloc d'image est réglé sur la taille automatique afin que l'image l'oblige à atteindre sa taille maximale.

La zone d'image se trouve dans un panneau avec autoScroll = true, de sorte que des barres de défilement apparaissent lorsque l'image est plus grande que le panneau.

Comment puis-je faire défiler le panneau par programmation lorsque l'utilisateur clique sur les traînées sur l'image, repositionnant ainsi l'image.

J'ai essayé d'utiliser l'événement MouseMove, en capturant les dernières positions X et Y de la souris, en calculant le déplacement de la souris et en ajustant les valeurs de défilement vertical et horizontal du panneau.

Cela déplace l'image, mais elle saute partout et défile de manière imprévisible.

Comment puis-je y parvenir?

Voici ce que j'ai dans mes événements de souris ...

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (dragging)
    {
        if (e.Button == MouseButtons.Left)
        {
            // move the image inverse to direction dragged
            int horizontalChange = (e.X - startingX) * -1;  
            int newHorizontalPos = panel1.HorizontalScroll.Value + horizontalChange;

            if (newHorizontalPos < panel1.HorizontalScroll.Minimum)
            {
                newHorizontalPos = panel1.HorizontalScroll.Minimum;
                horizontalChange = 0;
            }

            if (newHorizontalPos > panel1.HorizontalScroll.Maximum)
            {
                newHorizontalPos = panel1.HorizontalScroll.Maximum;
                horizontalChange = 0;
            }

            panel1.HorizontalScroll.Value = newHorizontalPos;

            int verticalChange = (e.Y - startingY);
            // move the image inverse to direction dragged
            int newverticalPos = panel1.VerticalScroll.Value + verticalChange * -1;  

            if (newverticalPos < panel1.VerticalScroll.Minimum)
            {
                newverticalPos = panel1.VerticalScroll.Minimum;
                verticalChange = 0;
            }

            if (newverticalPos > panel1.VerticalScroll.Maximum)
            {
                newverticalPos = panel1.VerticalScroll.Maximum;
                verticalChange = 0;
            }

            panel1.VerticalScroll.Value = newverticalPos;
        }
    }

    startingX = e.X;
    startingY = e.Y;
}

Ma logique est-elle fausse ou ma compréhension de la fonctionnalité de défilement du panneau est-elle fausse?

Était-ce utile?

La solution

Je pense que votre instinct est correct, mais votre erreur est d’essayer de régler les barres de défilement plutôt que de déplacer la PictureBox dans le panneau déroulant.

Vous devez intercepter MouseMove et régler la propriété Location de la PictureBox selon le delta des mouvements de la souris. Les barres de défilement doivent être automatiquement mises à jour pour refléter le nouvel emplacement de l'image.

La mise à jour de votre code ressemblerait à ce qui suit (non testé):

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (dragging)
    {
        if (e.Button == MouseButtons.Left)
        {
            int horizontalChange = (e.X - startingX) * -1;  // move the image inverse to direction dragged

            int verticalChange = (e.Y - startingY);

            pictureBox1.Left += horizontalChange;
            pictureBox1.Top += verticalChange;
        }
    }

    startingX = e.X;
    startingY = e.Y;
}

(De plus, je serais enclin à enregistrer les emplacements de départ de la souris et de PictureBox au début du glisser-déposer et à les mettre à jour par rapport à cette position de départ sur chaque événement MouseMove plutôt que d'apporter des modifications incrémentielles comme le code ci-dessus (et votre code d'origine). La raison en est que s'il y a des valeurs inattendues, quelle qu'en soit la raison, cela ne fera que produire un effet transitoire - le prochain bon événement se corrigera de lui-même.)

Autres conseils

Il saute parce que le fait de faire défiler le panneau va décaler la position de la souris de la quantité de défilement. Vous pouvez obtenir le " réel " position de la souris (par rapport au coin supérieur gauche du panneau) comme suit:

  Point realPos = new Point(e.X + panel1.AutoScrollPosition.X,
    e.Y + panel1.AutoScrollPosition.Y);

en supposant que la propriété "Zone de l'image" est (0, 0). Le meilleur moyen de faire défiler le panneau consiste à définir sa propriété AutoScrollPosition.

Vous pouvez définir le AutoScrollPosition du panneau dans l'événement MouseMove. Testé et fonctionne bien.

panel1.AutoScrollPosition = new Point(-panel1.AutoScrollPosition.X - e.X + startPoint.X, -panel1.AutoScrollPosition.Y - e.Y + startPoint.Y);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top