许多网站都会显示一个特写窗口,其中显示放大的图像部分,以便您可以看到更多细节。您在主图像上移动鼠标,它会在单独的图片中显示特写。此示例执行的操作类似。(示例使用的一些数学运算非常棘手,因此您可能需要仔细查看才能了解其工作原理。)
特写图实际上只是原始图像的全尺寸副本。(“主”图像是较小比例的相同图像。)要显示特写图,程序会在名为picCloseup的PictureBox中显示全尺寸图像。该控件位于名为panCloseup的Panel内。通过在panCloseup内移动picCloseup,程序可以显示全尺寸图像的不同部分。
以下代码使程序准备启动。
// Save the original image.
private Bitmap OriginalImage, ShadedImage;
private int SmallWidth, SmallHeight;
private float ScaleX, ScaleY;
private void Form1_Load(object sender, EventArgs e)
{OriginalImage = picWhole.Image as Bitmap;picCloseup.Image = OriginalImage;picCloseup.SizeMode = PictureBoxSizeMode.AutoSize;// Make a shaded version of the image.ShadedImage = new Bitmap(OriginalImage);using (Graphics gr = Graphics.FromImage(ShadedImage)){using (Brush br =new SolidBrush(Color.FromArgb(128, 255, 255, 255))){Rectangle rect = new Rectangle(0, 0,ShadedImage.Width, ShadedImage.Height);gr.FillRectangle(br, rect);}}// Get scale factors to map from big scale to small scale.ScaleX = (float)panCloseup.ClientSize.Width /OriginalImage.Width;ScaleY = (float)panCloseup.ClientSize.Height /OriginalImage.Height;// See how big the closeup is on the small scale.SmallWidth = (int)(ScaleX * picWhole.ClientSize.Width);SmallHeight = (int)(ScaleY * picWhole.ClientSize.Height);
}
此代码保存原始图像并制作该图像的亮化版本。要制作亮化版本,它会复制原始图像,然后用半透明的白色矩形填充它。这将成为您将鼠标移到其上的主图像。
当鼠标移入或移出主图像时,将执行以下代码。
// Use the shaded background image.
private void picWhole_MouseEnter(object sender, EventArgs e)
{picWhole.Image = ShadedImage;panCloseup.Visible = true;
}// Use the regular image.
private void picWhole_MouseLeave(object sender, EventArgs e)
{picWhole.Image = OriginalImage;panCloseup.Visible = false;
}
当鼠标位于主图像之外时,程序显示正常的非亮化版本。当鼠标进入图像时,程序切换为显示亮化图像。
当鼠标在主图像上移动时,以下代码会显示鼠标周围区域的特写。
// Display a closeup of this area.
private Rectangle ViewingRectangle;
private void picWhole_MouseMove(object sender, MouseEventArgs e)
{// Position picCloseup inside its parent Panel.float x = (float)e.X / picWhole.ClientSize.Width *OriginalImage.Width -(float)panCloseup.ClientSize.Width / 2;float y = (float)e.Y / picWhole.ClientSize.Height *OriginalImage.Height -(float)panCloseup.ClientSize.Height / 2;if (x < 0) x = 0;if (y < 0) y = 0;if (x > OriginalImage.Width - panCloseup.ClientSize.Width)x = OriginalImage.Width - panCloseup.ClientSize.Width;if (y > OriginalImage.Height - panCloseup.ClientSize.Height)y = OriginalImage.Height - panCloseup.ClientSize.Height;picCloseup.Location = new Point(-(int)x, -(int)y);// Record the position we are viewing.ViewingRectangle = new Rectangle((int)x, (int)y,panCloseup.ClientSize.Width, panCloseup.ClientSize.Height);// Draw the closeup area.picWhole.Invalidate();
}
首先,代码决定鼠标周围的区域在哪里。如果该区域部分位于主图像之外,则代码会调整其 X 和 Y 坐标,使该区域位于主图像内。这样可以让特写显示尽可能多的图像。
代码将picCloseup移动到panCloseup内,以显示全尺寸图像的正确部分。然后,它将在变量ViewingRectangle中记录主图像上将显示的区域,并使主图像无效以使其重绘。以下代码显示了主图片的Paint事件处理程序,该处理程序处理该重绘。
// Draw the viewing area.
private void picWhole_Paint(object sender, PaintEventArgs e)
{// Scale so we can draw in the full scale coordinates.e.Graphics.ScaleTransform(ScaleX, ScaleY);// Draw the viewing area using the original image.e.Graphics.DrawImage(OriginalImage, ViewingRectangle, ViewingRectangle, GraphicsUnit.Pixel);//e.Graphics.DrawRectangle(Pens.Red, ViewingRectangle);
}
此代码使用变换,因此它可以使用全尺寸图像的坐标而不是主图像(您可能还记得,主图像是缩小比例的)的坐标进行绘制。然后,它将原始全尺寸图像的一部分复制到主图像上,以显示鼠标周围的区域。结果是主图像除了此区域外都被阴影化,此区域以原始亮度绘制。取消注释此方法中的最后一行,以在主图像的特写区域周围绘制一个红色矩形。
我承认这是一个令人困惑的例子,但它的效果非常酷,所以我鼓励你下载并尝试一下。如果你对代码进行一些实验,你就能弄清楚它是如何工作的。(土卫二是一颗特别奇怪的卫星!)