.Net提供的PictureBox控件当图片大于显示区域时没有滚动条供滚动查看。不过好在这个功能可以很简单的通过Panel来实现。我们需要使用一个Panel来装PictureBox,再将Panel的AutoScroll设置为True,PictureBox的SizeMode设置为AutoSize。这样PictureBox的大小就由图片来决定了,而当PictureBox的大小超过了Panel时就会出现滚动条了(来自于Panel)。但值得注意的是不要将PictureBox控件Dock在Panel上,不然不会出现滚动条,只要将PictureBox的Location设置为0,0即可。Dock在父容器上时宽高就由父容器决定了,这和我们想要的AutoSize是相悖的,其实微软控件的一些属性是相悖的,但是在设计器中并没有体现出来而是在运行时体现,这就给我们带来了不少的困惑,需要慢慢的总结。

现在运行起来查看大图片就会出现滚动条了,但是你会发现鼠标滚轮不管用。看来我们还要加入一些代码来支持鼠标滚轮。我们可以利用Form上的MouseWheel事件来处理这个事情,只是进行一下区域判断,如果鼠标在Panel的区域内则改变Panel的垂直滚动数值即可。

private void mainForm_MouseWheel(object sender, MouseEventArgs e)
{
    // get screen point
    Point mousePoint = _mainForm.PointToScreen(e.Location);
    // whether in panel
    if (this.pnlImage.RectangleToScreen(this.pnlImage.ClientRectangle).Contains(mousePoint))
    {
        this.pnlImage.AutoScrollPosition = new Point(this.pnlImage.HorizontalScroll.Value, pnlImage.VerticalScroll.Value - e.Delta);
    }
}

e.Location就是鼠标在form中的位置,以窗口左上角为0,0来计算的。通过PointToScreen方法可以将其转化为屏幕坐标,以屏幕左上角为0,0来计算的。同样的将Panel的显示区域的坐标也转化为屏幕坐标,接下来就是判断一下当前的鼠标是否在Panel的显示区域就好了。


但是滚轮只能改变垂直滚动条,如果你还想更完美一些支持鼠标拖动来同时改变水平和垂直滚动条的话。还需要在PictureBox的MouseDown、MouseMove和MouseUp上来做点事情。大体的思路就是在MouseDown时记住一个坐标,在MouseMove时用当前坐标和记住的坐标进行比较从而得知鼠标的变化方向,并以此来改变滚动条的位置。

private Point _startLocation;
private void pbImage_MouseDown(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        _startLocation = e.Location;
        Cursor = Cursors.SizeAll;
    }
}
private void pbImage_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        int xOffset = _startLocation.X - e.X;
        int yOffset = _startLocation.Y - e.Y;
        this.pnlImage.AutoScrollPosition = new Point(this.pnlImage.HorizontalScroll.Value + xOffset, pnlImage.VerticalScroll.Value + yOffset);
    }
}
private void pbImage_MouseUp(object sender, MouseEventArgs e)
{
    Cursor = Cursors.Default;
}

如果你有更好的解决方案欢迎留言。Smile