Working with PictureBox
Master image display and manipulation in Visual Basic 2026 — load images from files, control SizeMode, build an interactive photo viewer with OpenFileDialog, and create a timer-driven slideshow, with GitHub Copilot assistance throughout.
Async/Await with HttpClient to load images from URLs without freezing the UI, and use Image?.Dispose() (null-conditional operator) to safely free memory before loading a new image.
PictureBox — Quick Reference
7.1 Understanding SizeMode
The SizeMode property is the single most important PictureBox setting. It controls what happens when the image dimensions don't match the PictureBox dimensions:
| SizeMode | Behaviour | Aspect Ratio | Best For |
|---|---|---|---|
| Normal | Natural size, top-left. Cropped if too large. | ✅ Preserved | Small icons, exact-size graphics |
| StretchImage | Fills entire PictureBox by stretching. | ❌ Distorted | Background fills (when distortion is OK) |
| AutoSize | PictureBox resizes to match the image. | ✅ Preserved | Fixed-size images, thumbnails |
| CenterImage | Centred at natural size. Cropped if too large. | ✅ Preserved | Logos, centred icons |
| Zoom ⭐ | Scales to fit, adds letterbox padding. | ✅ Preserved | Photos — the recommended default |
Click each SizeMode to see how it changes how the same image fits inside an identical 220×160 PictureBox.
7.2 Loading an Image at Design-Time
The simplest approach is setting the image in the Properties Window — no code needed. The image gets embedded in your project's Resources and ships inside the compiled EXE.
Add a PictureBox
Drag a PictureBox onto the form. Set BorderStyle = FixedSingle and BackColor = Black so it has a visible frame.
Click the Image Property
In the Properties Window find Image and click the … button. In the Select Resource dialog click Local resource → Import to browse for any image on your PC.
Set SizeMode = Zoom
The image appears instantly in the designer. Change SizeMode to Zoom so it fills the control proportionally without distortion.
Images embedded via the Properties Window become part of Project Resources — they compile into the EXE and always exist. Image.FromFile("C:\path\photo.jpg") requires the file to exist at that exact path on every user's machine. Use Resources for logos and icons that never change; use OpenFileDialog for user-selected photos.
7.3 Loading Images at Runtime
Example 7.1 — Load from a File Path
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load picDisplay.SizeMode = PictureBoxSizeMode.Zoom picDisplay.BackColor = Color.Black ' Load from a fixed path — file must exist picDisplay.Image = Image.FromFile("C:\Pictures\holiday.jpg") End Sub
If the path doesn't exist Image.FromFile() throws a FileNotFoundException and crashes the app. Use IO.File.Exists(path) to check first, or wrap in a Try…Catch block (covered fully in Lesson 24).
Example 7.2 — OpenFileDialog Photo Viewer
The OpenFileDialog control presents the standard Windows file browser. Drag it from the Toolbox onto the form — it lands in the component tray below (invisible at runtime).
Add OpenFileDialog
Drag OpenFileDialog from the Toolbox. Name it OFGSelectImage. Set its Filter to Image Files|*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.webp|All Files|*.*
Add a PictureBox and Button
Add picDisplay (SizeMode = Zoom, BackColor = Black) and btnView (Text = "📂 Open Image"). Add lblStatus below for feedback.
Write the Click Handler
Double-click btnView to create its Click event, then write the code below.
Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Me.Text = "Photo Viewer" picDisplay.SizeMode = PictureBoxSizeMode.Zoom picDisplay.BackColor = Color.Black picDisplay.BorderStyle = BorderStyle.FixedSingle OFGSelectImage.Filter = "Image Files|*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.webp|All Files|*.*" OFGSelectImage.Title = "Select an Image" lblStatus.Text = "No image loaded." End Sub Private Sub btnView_Click(sender As Object, e As EventArgs) Handles btnView.Click If OFGSelectImage.ShowDialog() = DialogResult.OK Then ' Null-conditional Dispose — safe even if Image is Nothing picDisplay.Image?.Dispose() picDisplay.Image = Image.FromFile(OFGSelectImage.FileName) Dim img = picDisplay.Image Me.Text = $"Photo Viewer — {IO.Path.GetFileName(OFGSelectImage.FileName)}" lblStatus.Text = $"✔ {OFGSelectImage.SafeFileName} ({img.Width} × {img.Height} px)" End If End Sub Private Sub btnClear_Click(sender As Object, e As EventArgs) Handles btnClear.Click picDisplay.Image?.Dispose() picDisplay.Image = Nothing Me.Text = "Photo Viewer" lblStatus.Text = "No image loaded." End Sub End Class
Choose a sample image from the dropdown (simulating OpenFileDialog), adjust SizeMode, then clear.
Click btnView to open
7.4 Manipulating PictureBox at Runtime
You can change PictureBox size, visibility, and image transformation at runtime — creating interactive controls, zoom buttons, and toggle effects.
' Zoom In — grow by 24×18 px each click Private Sub btnZoomIn_Click(sender As Object, e As EventArgs) Handles btnZoomIn.Click picDisplay.Width += 24 picDisplay.Height += 18 lblSize.Text = $"Size: {picDisplay.Width} × {picDisplay.Height}" End Sub ' Zoom Out — minimum 80×60 Private Sub btnZoomOut_Click(sender As Object, e As EventArgs) Handles btnZoomOut.Click If picDisplay.Width > 80 Then picDisplay.Width -= 24 picDisplay.Height -= 18 lblSize.Text = $"Size: {picDisplay.Width} × {picDisplay.Height}" End If End Sub ' Toggle show/hide Private Sub btnToggle_Click(sender As Object, e As EventArgs) Handles btnToggle.Click picDisplay.Visible = Not picDisplay.Visible btnToggle.Text = If(picDisplay.Visible, "Hide", "Show") End Sub ' Rotate 90° clockwise Private Sub btnRotate_Click(sender As Object, e As EventArgs) Handles btnRotate.Click If picDisplay.Image IsNot Nothing Then picDisplay.Image.RotateFlip(RotateFlipType.Rotate90FlipNone) picDisplay.Refresh() End If End Sub ' Flip horizontally Private Sub btnFlip_Click(sender As Object, e As EventArgs) Handles btnFlip.Click If picDisplay.Image IsNot Nothing Then picDisplay.Image.RotateFlip(RotateFlipType.RotateNoneFlipX) picDisplay.Refresh() End If End Sub
7.5 Building an Image Slideshow with Timer
A Timer control paired with a PictureBox and an array of image paths creates an automatic slideshow. The Timer fires a Tick event at a set interval, and the handler advances the image index — wrapping back to 0 using the Mod operator.
Public Class SlideShow Private _images() As String = { "C:\Photos\slide1.jpg", "C:\Photos\slide2.jpg", "C:\Photos\slide3.jpg", "C:\Photos\slide4.jpg" } Private _current As Integer = 0 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load picSlide.SizeMode = PictureBoxSizeMode.Zoom picSlide.BackColor = Color.Black Timer1.Interval = 3000 ' 3 seconds LoadSlide(_current) End Sub Private Sub LoadSlide(index As Integer) picSlide.Image?.Dispose() picSlide.Image = Image.FromFile(_images(index)) lblSlide.Text = $"Slide {index + 1} of {_images.Length}" End Sub ' Tick fires every 3 s — advance and wrap around with Mod Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick _current = (_current + 1) Mod _images.Length LoadSlide(_current) End Sub Private Sub btnPlay_Click(sender As Object, e As EventArgs) Handles btnPlay.Click Timer1.Start() : btnPlay.Enabled = False : btnPause.Enabled = True End Sub Private Sub btnPause_Click(sender As Object, e As EventArgs) Handles btnPause.Click Timer1.Stop() : btnPlay.Enabled = True : btnPause.Enabled = False End Sub Private Sub btnPrev_Click(sender As Object, e As EventArgs) Handles btnPrev.Click _current = (_current - 1 + _images.Length) Mod _images.Length LoadSlide(_current) End Sub Private Sub btnNext_Click(sender As Object, e As EventArgs) Handles btnNext.Click _current = (_current + 1) Mod _images.Length LoadSlide(_current) End Sub End Class
Press Play for the auto slideshow (3 s intervals) or use Prev/Next to browse manually.
7.6 New in VB 2026 / .NET 10 — Async URL Loading
Earlier versions required blocking WebClient calls that froze the UI. VB 2026 / .NET 10 makes this clean with Async/Await and HttpClient:
Imports System.Net.Http Public Class Form1 ' One shared instance — reused for all requests (best practice) Private Shared ReadOnly _http As New HttpClient() Private Async Sub btnLoadUrl_Click(sender As Object, e As EventArgs) Handles btnLoadUrl.Click Dim url = txtUrl.Text.Trim() If String.IsNullOrEmpty(url) Then Return lblStatus.Text = "Loading…" btnLoadUrl.Enabled = False picDisplay.Image?.Dispose() picDisplay.Image = Nothing Try ' Awaiting here — UI stays fully responsive during download Dim bytes = Await _http.GetByteArrayAsync(url) Dim ms = New IO.MemoryStream(bytes) picDisplay.Image = Image.FromStream(ms) lblStatus.Text = $"✔ {picDisplay.Image.Width} × {picDisplay.Image.Height} px" Catch ex As Exception lblStatus.Text = $"✘ Error: {ex.Message}" Finally btnLoadUrl.Enabled = True End Try End Sub End Class
The Async keyword on a Sub/Function and Await inside it allows long operations — downloads, file reads, database queries — to run on a background thread. The UI remains fully responsive: the user can still move the window and click other buttons while the image downloads. This pattern is essential for professional VB 2026 development and is fully supported in .NET 10.
7.7 GitHub Copilot — PictureBox Assistance
' Open image with OpenFileDialog, dispose old image safely, show filename and dimensions in lblStatus'' Open image with OpenFileDialog, dispose old image safely, show filename and dimensions in lblStatus Using dlg As New OpenFileDialog() dlg.Filter = "Images|*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.webp|All|*.*" If dlg.ShowDialog() = DialogResult.OK Then picDisplay.Image?.Dispose() picDisplay.Image = Image.FromFile(dlg.FileName) Dim img = picDisplay.Image lblStatus.Text = $"{dlg.SafeFileName} ({img.Width} × {img.Height} px)" Me.Text = $"Photo Viewer — {dlg.SafeFileName}" End If End Using
' Connect TrackBar1 to Timer1.Interval so speed ranges from 1s to 10s'' Connect TrackBar1 to Timer1.Interval so speed ranges from 1s to 10s ' In Form_Load: TrackBar1.Minimum = 1 TrackBar1.Maximum = 10 TrackBar1.Value = 3 Timer1.Interval = TrackBar1.Value * 1000 ' TrackBar scroll event: Private Sub TrackBar1_Scroll(sender As Object, e As EventArgs) Handles TrackBar1.Scroll Timer1.Interval = TrackBar1.Value * 1000 lblSpeed.Text = $"Speed: {TrackBar1.Value}s per slide" End Sub
Try these in the Copilot Chat panel while building PictureBox projects:
- "Add a TrackBar to control PictureBox opacity from 0% to 100%"
- "Save the current picDisplay image as PNG to the user's Pictures folder"
- "Load all images from a folder into a FlowLayoutPanel as thumbnails"
- "Add a fade transition between slideshow images using a Timer and opacity"
📘 Lesson Summary
- PictureBox supports JPG, PNG, BMP, GIF, TIFF, ICO, and WEBP image formats.
- SizeMode = Zoom is the recommended default — it scales the image proportionally without distortion. StretchImage distorts; Normal crops.
- Embed images at design-time via the Properties Window (Image property) to compile them into the EXE as Project Resources.
- Use
Image.FromFile(path)to load at runtime — always checkIO.File.Exists(path)or useTry…Catch. - OpenFileDialog shows the standard Windows file browser — set its
Filterproperty to list allowed image types. - Always call
picDisplay.Image?.Dispose()before loading a new image — the?.null-conditional operator makes this safe even when Image is Nothing. - Change
Width,Height, andVisibleat runtime. UseRotateFlip()to rotate or mirror, followed byRefresh(). - Combine PictureBox + Timer for a slideshow — use
(index + 1) Mod countto wrap back to the first slide. - In VB 2026 / .NET 10, use
Async/AwaitwithHttpClient.GetByteArrayAsync()to load images from URLs without freezing the UI.
Exercises
Exercise 7.1 — Enhanced Photo Viewer
- Build a photo viewer with OpenFileDialog supporting JPG, PNG, BMP, GIF, WEBP
- Display filename, pixel dimensions, and file size in Labels below the PictureBox
- Add Zoom In (+24px), Zoom Out (−24px, min 100px), Rotate 90°, and Flip Horizontal buttons
- Add a ComboBox to switch SizeMode live between Normal, Zoom, StretchImage, CenterImage
- Copilot challenge: Ask Copilot to "add a Save As button that saves the image to a user-chosen PNG path"
Exercise 7.2 — Slideshow with Speed Control
- Load 4 or more images into an array using OpenFileDialog on startup
- Add Play, Pause, Prev, Next buttons and a slide counter label
- Add a TrackBar (1–10 s) to control the auto-advance speed — update Timer.Interval on scroll
- Add navigation dots below the PictureBox that highlight the current slide index
- Copilot challenge: Ask Copilot to "add a crossfade effect between slides using two overlapping PictureBoxes"
Exercise 7.3 — Thumbnail Gallery
- Use a FlowLayoutPanel to hold 80×80 thumbnail PictureBoxes (SizeMode = Zoom)
- Load all images from a user-chosen folder using
Directory.GetFiles() - When a thumbnail is clicked, show the full image in a large PictureBox on the right
- Display the selected image's filename, dimensions, and file size in a StatusStrip
- Copilot challenge: Ask Copilot to "add right-click context menu to thumbnails with Open, Delete, and Set as Wallpaper options"
Related Resources
← Lesson 6
ListBox & ComboBox — list-based controls and item management.
Lesson 8 →
Data Types — Integer, Double, String, Boolean, Date and more.
PictureBox Docs
Official Microsoft reference for the Windows Forms PictureBox in .NET.
VB Sample Code
62 complete VB.NET programs — includes photo viewer and animation examples.
Featured Books
Visual Basic 2022 Made Easy
Complete coverage of PictureBox, OpenFileDialog, Timer, and image manipulation with step-by-step projects.
View on Amazon →
VB Programming With Code Examples
48 fully-explained VB.NET programs — includes complete photo viewer and slideshow applications with full source code.
View on Amazon →