Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / WinForms, .Net Framework Новый топик    Ответить
 Вопрос про скроллинг  [new]
ferzmikk
Member

Откуда:
Сообщений: 2213
Здравствуйте!

Есть WidowsForm. На форме присутствуют Panel1 и Button1.

Функционал формы:
- Если мышкой нажать на изображение, то на него рисуется сверху прямоугольник - фрагмент изображения.
- Курсорными клавишами можно перемещать фрагмент.
- Колесом мыши менять zoom изображения.
+C#
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace TestZoomImage
{
    public partial class Form1 : Form
    {
        Image image; //Загруженное изображение
        Image imageZoom; //Изображение после Zoom                   
        Int32 WidthPicture = 6;  //Ширина фрагмента
        Int32 HeightPicture = 6; //Высота фрагмента        
        Int32? PictureBox_X = null; //Последняя координата X фрагмента
        Int32? PictureBox_Y = null; //Последняя координата Y фрагмента
        double zoom = 1.0; //Коэффициент zoom
        double Stride = 0.05; //Шаг для zoom
        Int32? Scroll_X = null; //Позиция бегунка по горизонтали
        Int32? Scroll_Y = null; //Позиция бегунка по вертикали
        PictureBox pictureBox1;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.FormBorderStyle = FormBorderStyle.FixedDialog;           
            pictureBox1 = new PictureBox();
            pictureBox1.Name = "pictureBox1";
            pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
            panel1.AutoScroll = true;
            panel1.Controls.Add(pictureBox1);            
            pictureBox1.MouseDown += new MouseEventHandler(pictureBox1_MouseDown);
            pictureBox1.MouseWheel += new MouseEventHandler(pictureBox1_MouseWheel);
            image = Image.FromFile(@"C:\Users\Acer\Desktop\Image1.png");            
            pictureBox1.Image = image;
            pictureBox1.Width = image.Width;
            pictureBox1.Height = image.Height;
            imageZoom = image;
            pictureBox1.Focus();
        }

        private void pictureBox1_MouseWheel(object sender, MouseEventArgs e)
        {
            if (pictureBox1.Image != null)
            {
                zoom = zoom * (1 + Stride * Math.Sign(e.Delta));
                pictureBox1.Width = Convert.ToInt32(image.Width * zoom);
                pictureBox1.Height = Convert.ToInt32(image.Height * zoom);
                ((HandledMouseEventArgs)e).Handled = true;
                Bitmap bmp = new Bitmap(image,
                                        Convert.ToInt32(image.Width * zoom),
                                        Convert.ToInt32(image.Height * zoom));
                Graphics g = Graphics.FromImage(bmp);
                imageZoom = bmp;
                pictureBox1.Image = bmp;
                pictureBox1.Focus();
            }
        }        

        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {            

            if (e.X - WidthPicture / 2 >= 0 &&                //Чтобы не выходили за край PictureBox
                e.Y - HeightPicture / 2 >= 0 &&               //с учетом ширины и высоты фрагмента
                e.X + WidthPicture / 2 < pictureBox1.Width && //
                e.Y + HeightPicture / 2 < pictureBox1.Height) //
            {
                PictureBox_X = e.X;
                PictureBox_Y = e.Y;

                Procedure2();
                pictureBox1.Focus();
            }
        }        

        //Движение фрагмента курсорными кнопками
        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (!(PictureBox_X == null || PictureBox_Y == null))
            {
                switch (keyData)
                {
                    case Keys.Right:
                        if (PictureBox_X <= pictureBox1.Image.Width - WidthPicture)
                        {
                            PictureBox_X = PictureBox_X + 1;
                            Procedure1();
                            Procedure2();
                        }
                        return true;

                    case Keys.Left:
                        if (PictureBox_X > WidthPicture / 2)
                        {
                            PictureBox_X = PictureBox_X - 1;
                            Procedure1();
                            Procedure2();
                        }
                        return true;

                    case Keys.Up:
                        if (PictureBox_Y > HeightPicture / 2)
                        {
                            PictureBox_Y = PictureBox_Y - 1;
                            Procedure1();
                            Procedure2();
                        }
                        return true;

                    case Keys.Down:
                        if (PictureBox_Y <= pictureBox1.Image.Height - HeightPicture)
                        {
                            PictureBox_Y = PictureBox_Y + 1;
                            Procedure1();
                            Procedure2();
                        }
                        return true;
                }
            }
            return base.ProcessDialogKey(keyData);
        }

        //Проверяет выходит ли фрагмент за пределы видимости
        //Если да - сдвигает бегунок в соответствующую сторону, чтобы фрагмент был полностью виден
        private void Procedure1()
        {
            
        }

        //Процедура, которая вставляет прямоугольник на изображение.
        private void Procedure2()
        {
            //Получаем прямоугольник
            Rectangle cloneRect = new Rectangle((int)PictureBox_X - WidthPicture / 2,
                                                (int)PictureBox_Y - HeightPicture / 2,
                                                 WidthPicture,
                                                 HeightPicture);
            Bitmap myBitmap = new Bitmap(imageZoom);
            PixelFormat format = myBitmap.PixelFormat;
            Bitmap newBitmapForForm = new Bitmap(imageZoom);
            using (Graphics g = Graphics.FromImage(newBitmapForForm))
            {
                g.DrawRectangle(new Pen(Color.Black, 1), cloneRect);
                g.Dispose();
            }
            pictureBox1.Image = newBitmapForForm;
        }        

        private void button1_Click(object sender, EventArgs e)
        {
            //Какая то процедура

            pictureBox1.Focus(); //Если это убрать, то бегунок не теряет свою позицию, но не будет работать zoom

            panel1.HorizontalScroll.Value = (int)Scroll_X;
            panel1.VerticalScroll.Value = (int)Scroll_Y;
        }

        //Получаем новые значения скроллинга после изменения
        private void panel1_Scroll(object sender, ScrollEventArgs e)
        {
            if (e.ScrollOrientation == ScrollOrientation.HorizontalScroll)
            {
                Scroll_X = e.OldValue;
            }
            else
            {
                Scroll_Y = e.OldValue; // Здесь почему то e.OldValue равен нулю
            }            
        }
        
    }
}
Здесь возникают вопросы:

1. Но если прокрутить бегунок (и горизонтально, и вертикально), нажать мышкой и потом нажать на button, то вертикальный бегунок фактически занял исходную позицию, но изображение по вертикали на месте и почему то значение e.OldValue равно нулю.
        private void button1_Click(object sender, EventArgs e)
        {
            //Какая то процедура

            pictureBox1.Focus(); //Если это убрать, то бегунок не теряет свою позицию, но не будет работать zoom

            panel1.HorizontalScroll.Value = (int)Scroll_X;
            panel1.VerticalScroll.Value = (int)Scroll_Y;
        }
Почему так? Как правильно написать? Тут еще дополнительно надо учитывать, чтобы значение 'Value' лежало в диапазоне от 'minimum' до 'maximum'.

2. Нужно сделать так, если фрагмент находится за пределы видимости - бегунок автоматически перемещался в соответствующую сторону, чтобы фрагмент был виден целиком. Подскажите, как это можно сделать?
1 мар 21, 17:09    [22287988]     Ответить | Цитировать Сообщить модератору
Все форумы / WinForms, .Net Framework Ответить