Uthistran Selvaraj.
Uthistran Selvaraj.

Reputation: 558

Panel and ScrollBar in Windows forms

I am using a panel to display a image in windows forms I am drawing image in the panel in Panel_Paint event as follows:

Graphics g = panel1.CreateGraphics();
Image im = new Bitmap(@"../../Data/#3_Page2.PNG");
g.DrawImage(im,new Point(10,10));

Now, the image is drawn as i expected, with some part of the bottom of the image not displaying as its height is greater than forms height. I have added the VScrollBar now. How do i make that panel to view the rest of the image with the help of VScrollBar.

Upvotes: 1

Views: 15671

Answers (2)

King King
King King

Reputation: 63317

This solution works, however if your image is large enough, there is a little flicker when you scroll (however it's acceptable). First you have to add a VScrollBar right on the right of your panel and a HScrollBar right under the bottom of your panel. This demo requires you have a VScrollBar named vScrollBar1 and HScrollBar named hScrollBar1, a Button named buttonOpenImage to allow user to open some image, a Panel named panel1 used as the main area to draw the image:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();            
        //To prevent/eliminate flicker, do this
        typeof(Panel).GetProperty("DoubleBuffered", 
                                  System.Reflection.BindingFlags.Instance | 
               System.Reflection.BindingFlags.NonPublic).SetValue(panel1, true, null);
        //------------------------
        UpdateScrollbarsState();
    }        
    int imgWidth, imgHeight;
    Image image;
    Point leftTop = Point.Empty;
    int lastV, lastH;
    private void OpenImage(){
        OpenFileDialog openFile = new OpenFileDialog();            
        openFile.FileOk += (s, e) => {
            try {
                image = Image.FromFile(openFile.FileName);
                //calculate the physical size of the image based on the resolution and its logical size.
                //We have to do this because the DrawImage is based on the physical size (not logical).
                imgWidth = (int)(image.Width * 96f / image.HorizontalResolution + 0.5);
                imgHeight = (int)(image.Height * 96f / image.VerticalResolution + 0.5);
                lastV = lastH = 0;
                UpdateScrollbarsState();
                vScrollBar1.Value = 0;
                hScrollBar1.Value = 0;
                panel1.Invalidate();
            }
            catch {
                image = null;
                MessageBox.Show("Image file is invalid or corrupted!");
            }
        };
        openFile.ShowDialog();
    }
    private void UpdateScrollbarsState() {
        //We have to update all the info about Minimum and Maximum
        vScrollBar1.Minimum = 0;
        hScrollBar1.Minimum = 0;
        vScrollBar1.Maximum = Math.Max(imgHeight-panel1.Height,0);
        hScrollBar1.Maximum = Math.Max(imgWidth-panel1.Width,0);
        vScrollBar1.Visible = vScrollBar1.Maximum > 0;
        hScrollBar1.Visible = hScrollBar1.Maximum > 0;
        if (vScrollBar1.Maximum == 0) {
            leftTop.Y = 0;
            lastV = 0;
        }
        if (hScrollBar1.Maximum == 0) {
            leftTop.X = 0;
            lastH = 0;
        }
    }
    private void panel1_Paint(object sender, PaintEventArgs e) {
        if (image == null) return;
        e.Graphics.DrawImage(image, leftTop);
    }
    //The ValueChanged event handler of your vScrollBar1
    private void vScrollBar1_ValueChanged(object sender, EventArgs e) {
        if (!vScrollBar1.Visible) return;
        leftTop.Offset(0, -vScrollBar1.Value + lastV);
        lastV = vScrollBar1.Value;
        panel1.Invalidate();
    }
    //The ValueChanged event handler of your hScrollBar1
    private void hScrollBar1_ValueChanged(object sender, EventArgs e) {
        if (!hScrollBar1.Visible) return;
        leftTop.Offset(lastH - hScrollBar1.Value, 0);
        lastH = hScrollBar1.Value;
        panel1.Invalidate();
    }
    //handler for SizeChanged event of the panel. However if resizing
    //the form causes the panel's size changing, you should attach this 
    //handler for form.
    private void panel1_SizeChanged(object sender, EventArgs e) {
        UpdateScrollbarsState();
    }
    //handler for the Click event of a button (click to open an image)
    private void buttonOpenImage_Click(object sender, EventArgs e) {
        OpenImage();
    }
}

Upvotes: 3

koprinkov
koprinkov

Reputation: 71

You can use PictureBox with SizeMode set to AutoSize and AutoScroll property of Panel. That way the panel should add scrollbars if they are needed.

PictureBox pictureBox = new System.Windows.Forms.PictureBox();
pictureBox.Image = new Bitmap(@"../../Data/#3_Page2.PNG");
pictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;

panel.AutoScroll = true;
panel.Controls.Add(this.pictureBox);

Upvotes: 5

Related Questions