总的来说,我对编程有点陌生,但我渴望了解更多,我想知道是否有人可以帮助我提出一个想法。
(主要目标)
我想制作一个由 C# Windows 窗体应用程序组成的简单程序,该程序在 PictureBox 中显示预设图像(尺寸为 6000x6000 像素,SizeMode 设置为 Zoom,以便整个图像立即在窗体上可见)。实际上整个表单,在表单底部保留一个空间,我想在其中显示一个允许您放大和缩小图像的轨迹栏;以及 PictureBox 底部的水平滚动条和 PictureBox 右侧的垂直滚动条,用于在缩放地图时滚动地图,我希望能够通过单击来控制这些滚动条并在 PictureBox 上沿相应方向拖动(首选,但不确定是否可能)或使用鼠标上的滚轮(可能更容易,但再次不确定)。
(参考)
[ 这里是我完全按照我的描述完成的表单,使用 SizeMode Zoom 在 PictureBox 中使用 6000x6000 放置支架演示纹理作为示例 - 这已得到处理,问题的下一部分更新如下:]
(附录)
我遇到的唯一问题是代码,因为我在该部门几乎是新手。我一直在努力学习 Visual Studio 的工作流程,但我确实需要一些帮助。
提前非常感谢您可以帮助我的任何事情。
更新:
在对这个主题进行研究并花时间进行一些思考之后,我想出了下面列出的代码;但我的问题是,当我将图像平移太远时,图像会被拉得太远,从而当图像被平移/拉太远到一个角落时会暴露其后面的面板。另外,当我缩小得太远时,图像会变得比图片框小得多。
所以,我的最后一个问题:我将如何修改下面的代码以“锁定”我正在平移和缩放的图像,使其不被允许在其框架之外平移或缩放并暴露其后面的面板?
public partial class ImageZoomMainForm : Form
{
Image img;
Point mouseDown;
int startx = 0;
int starty = 0;
int imgx = 0;
int imgy = 0;
bool mousepressed = false;
float zoom = 1;
public ImageZoomMainForm()
{
InitializeComponent();
string imagefilename = @"..\..\ViewPort_MAIN.tif";
img = Image.FromFile(imagefilename);
Graphics g = this.CreateGraphics();
zoom = ((float)pictureBox.Width / (float)img.Width) * (img.HorizontalResolution / g.DpiX);
pictureBox.Paint += new PaintEventHandler(imageBox_Paint);
}
private void pictureBox_MouseMove(object sender, EventArgs e)
{
MouseEventArgs mouse = e as MouseEventArgs;
if (mouse.Button == MouseButtons.Left)
{
Point mousePosNow = mouse.Location;
int deltaX = mousePosNow.X - mouseDown.X;
int deltaY = mousePosNow.Y - mouseDown.Y;
imgx = (int)(startx + (deltaX / zoom));
imgy = (int)(starty + (deltaY / zoom));
pictureBox.Refresh();
}
}
private void imageBox_MouseDown(object sender, EventArgs e)
{
MouseEventArgs mouse = e as MouseEventArgs;
if (mouse.Button == MouseButtons.Left)
{
if (!mousepressed)
{
mousepressed = true;
mouseDown = mouse.Location;
startx = imgx;
starty = imgy;
}
}
}
private void imageBox_MouseUp(object sender, EventArgs e)
{
mousepressed = false;
}
protected override void OnMouseWheel(MouseEventArgs e)
{
float oldzoom = zoom;
if (e.Delta > 0)
{
zoom += 0.1F;
}
else if (e.Delta < 0)
{
zoom = Math.Max(zoom - 0.1F, 0.01F);
}
MouseEventArgs mouse = e as MouseEventArgs;
Point mousePosNow = mouse.Location;
int x = mousePosNow.X - pictureBox.Location.X;
int y = mousePosNow.Y - pictureBox.Location.Y;
int oldimagex = (int)(x / oldzoom);
int oldimagey = (int)(y / oldzoom);
int newimagex = (int)(x / zoom);
int newimagey = (int)(y / zoom);
imgx = newimagex - oldimagex + imgx;
imgy = newimagey - oldimagey + imgy;
pictureBox.Refresh();
}
private void imageBox_Paint(object sender, PaintEventArgs e)
{
e.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
e.Graphics.ScaleTransform(zoom, zoom);
e.Graphics.DrawImage(img, imgx, imgy);
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
const int WM_KEYDOWN = 0x100;
const int WM_SYSKEYDOWN = 0x104;
if ((msg.Msg == WM_KEYDOWN) || (msg.Msg == WM_SYSKEYDOWN))
{
switch (keyData)
{
case Keys.Right:
imgx -= (int)(pictureBox.Width * 0.1F / zoom);
pictureBox.Refresh();
break;
case Keys.Left:
imgx += (int)(pictureBox.Width * 0.1F / zoom);
pictureBox.Refresh();
break;
case Keys.Down:
imgy -= (int)(pictureBox.Height * 0.1F / zoom);
pictureBox.Refresh();
break;
case Keys.Up:
imgy += (int)(pictureBox.Height * 0.1F / zoom);
pictureBox.Refresh();
break;
case Keys.PageDown:
imgy -= (int)(pictureBox.Height * 0.90F / zoom);
pictureBox.Refresh();
break;
case Keys.PageUp:
imgy += (int)(pictureBox.Height * 0.90F / zoom);
pictureBox.Refresh();
break;
}
}
return base.ProcessCmdKey(ref msg, keyData);
}
private void ImageZoomMainForm_Load(object sender, EventArgs e)
{
}
}
}
面板内的图片框, 面板应将其 AutoSroll 设置为 True, SizeMode 为 Zoom 的图片框
改变轨迹栏可以增大或减小内部图片框的大小,使外部面板自动滚动
也可以使用图片框的多个鼠标事件进行拖动。