Picturebox : maintain 4:3 aspect ratio

Xancholy

Well-known member
Joined
Aug 29, 2006
Messages
143
Programming Experience
Beginner
I have a picturebox in a horizontal splitpanel.

I would like the dimensions of the picturebox to :
  • grow/shrink as the form is sized OR
  • if the splitpanel shrinks/grows
BUT
the picturebox must retain a 4:3 aspect ratio

I have tried anchoring & docking just won't work.

How can I code this to make this possible ?

Thanks
 
Thanks JMC. The following code does the job.

but can anyone please tell me why VBE2008 generates an exception on form load but once the exception is cleared the form works perfectly. This does not seem to occur on VBE2005. Can someone else please help me verify that this is indeed the case ?

VB.NET:
Public Class Form1


Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
   ResizePictureBox()
End Sub

Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
   ResizePictureBox()
End Sub

Private Sub ResizePictureBox()
   Dim sz As Size = PictureBox1.Parent.Size
   If sz.Height < sz.Width Then
    PictureBox1.Size = New Size(sz.Height * 1.33333, sz.Height)
    PictureBox1.Location = New Point(sz.Width / 2 - PictureBox1.Width / 2, 0)
   Else
    PictureBox1.Size = New Size(sz.Width, sz.Width * 0.75)
    PictureBox1.Location = New Point(0, sz.Height / 2 - PictureBox1.Height / 2)
   End If
End Sub

Private Sub SplitContainer1_SplitterMoved(ByVal sender As Object, ByVal e As System.Windows.Forms.SplitterEventArgs) Handles SplitContainer1.SplitterMoved
     ResizePictureBox()
End Sub

End Class
 
Last edited:
Are you keeping all the information about this alleged exception to yourself for a reason? It presumably has a type and it presumably provides an error message. If you want us to tell you what the problem might be then that would be useful information.
 
Are you keeping all the information about this alleged exception to yourself for a reason?

That's funny - I had access to the code at the time of posting, but not the exception details.

To recreate exception that occurs in nested splitcontainers....
Drag splitcontainer1 onto form with vertical split. Drag splitcontainer2 into pane2 of splitcontainer1 and split horizontally.

Drop Picturebox1 into pane1 of splitcontainer2.

Run code. Exception details below:

System.InvalidOperationException was unhandled
Message="An error occurred creating the form. See Exception.InnerException for details. The error is: Object reference not set to an instance of an object."
Source="WindowsApplication1"
StackTrace:
at WindowsApplication1.My.MyProject.MyForms.Create__Instance__[T](T Instance) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 190
at WindowsApplication1.My.MyProject.MyForms.get_Form1()
at WindowsApplication1.My.MyApplication.OnCreateMainForm() in C:\Documents and Settings\My Computer\Local Settings\Application Data\Temporary Projects\WindowsApplication1\My Project\Application.Designer.vb:line 35
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
at WindowsApplication1.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException: System.NullReferenceException
Message="Object reference not set to an instance of an object."
Source="WindowsApplication1"
StackTrace:
at WindowsApplication1.Form1.ResizePictureBox() in C:\Documents and Settings\My Computer\Local Settings\Application Data\Temporary Projects\WindowsApplication1\Form1.vb:line 11
at WindowsApplication1.Form1.SplitContainer1_SplitterMoved(Object sender, SplitterEventArgs e) in C:\Documents and Settings\My Computer\Local Settings\Application Data\Temporary Projects\WindowsApplication1\Form1.vb:line 22
at System.Windows.Forms.SplitContainer.OnSplitterMoved(SplitterEventArgs e)
at System.Windows.Forms.SplitContainer.set_SplitterDistance(Int32 value)
at WindowsApplication1.Form1.InitializeComponent() in C:\Documents and Settings\My Computer\Local Settings\Application Data\Temporary Projects\WindowsApplication1\Form1.Designer.vb:line 45
at WindowsApplication1.Form1..ctor()
InnerException:
 
See, this is why it is essential that you provide details of the exception. Without we're just guessing. With it we can see exactly what's happening. From that stack trace I can see that the exception is occurring from within the ResizePictureBox method. The problem is that as the form is constructed the child controls will raise various events. It's obvious from that stack trace that the SplitterMoved event of SplitContainer1 is being raised, which is then causing ResizePictureBox to be called. If you're getting a NullReferenceException is ResizePictureBox then you're almost certainly referring to something that hasn't been properly constructed at that stage. It's then a simple matter of placing a break point on the ResizePictureBox method and stepping through it. Sure enough, doing so reveals that PictureBox1.Parent is Nothing, therefore trying to access PictureBox1.Parent.Size throws the exception.

Fixing it is then a simple matter of just checking that PictureBox1.Parent is not Nothing before trying to access it:
VB.NET:
Private Sub ResizePictureBox()
    [B][U]If Me.PictureBox1 IsNot Nothing AndAlso Me.PictureBox1.Parent IsNot Nothing Then[/U][/B]
        Dim sz As Size = PictureBox1.Parent.Size
        If sz.Height < sz.Width Then
            PictureBox1.Size = New Size(CInt(sz.Height * 1.33333), sz.Height)
            PictureBox1.Location = New Point(CInt(sz.Width / 2 - PictureBox1.Width / 2), 0)
        Else
            PictureBox1.Size = New Size(sz.Width, CInt(sz.Width * 0.75))
            PictureBox1.Location = New Point(0, CInt(sz.Height / 2 - PictureBox1.Height / 2))
        End If
    End If
End Sub
I was able to do all that because you provided the details of the exception. That information is provided to you by the IDE as a diagnostic tool. If you want us to diagnose the issue then it follows that you need to pass that information on to us. Hopefully this has demonstrated that and I also hope it has shown you how you can use that information yourself to diagnose issues yourself. The stack trace shows you every method that execution passed through so you should usually be able to debug one or more of those methods to find the issue yourself. NullReferenceExceptions are usually the easiest to find too.

Finally, I should mention that your code does not compile with Option Strict On, therefore you must have Option Strict Off. I suggest that you change that immediately and never work with Option Strict Off unless there is a specific reason to do so. The ONLY reason that I've ever come across to have Option Strict Off is when dealing with COM components that require late-binding. In that case you should still have Option Strict On for the project and place all the code that requires late-binding in separate files, then set Option Strict Off for those files only.

Having Option Strict On will throw up some errors to begin with and may be a bit confusing at first, but it will make your code more efficient and more robust, as well as making you a better developer faster by giving you a better understanding of how data flows through your app and in what forms.
 
Thanks for switching on my option strict. My codeblock shows what I am attempting. And yes, it is now throwing up all kinds of warnings.

With that said, do you have safer code for what I am trying to achieve here ?
 
I've added the CInt operators to the code I posted that are required to make it work with Option Strict On. The problem there was that you were trying to create a Size object and you were passing a Double value to a constructor that required an Integer. All you had to do was explicitly convert the Double value to an Integer, which CInt does. That's all that's ever required with Option Strict On: use explicit casts and conversions to make sure that you are always passing the type of data that the target expects. What that will do is draw to your attention places where the actual data cannot be cast or converted, therefore forcing you to fix at design time an error that otherwise would not have shown up until run time. It also guarantees you'll always get Intellisense and it makes your code run faster by negating the need for run time type checking.
 
Back
Top