Здравствуйте!
Есть WidowsForm. На форме присутствуют
Panel1 и
Button1 .
Функционал формы:
- Если мышкой нажать на изображение, то на него рисуется сверху прямоугольник - фрагмент изображения.
- Курсорными клавишами можно перемещать фрагмент.
- Колесом мыши менять zoom изображения.
C#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
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 равно нулю.
1.
2.
3.
4.
5.
6.
7.
8.
9.
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. Нужно сделать так, если фрагмент находится за пределы видимости - бегунок автоматически перемещался в соответствующую сторону, чтобы фрагмент был виден целиком. Подскажите, как это можно сделать?