Link to home
Start Free TrialLog in
Avatar of Dodsworth
Dodsworth

asked on

Aspect Ratio Sizing Math

I have a form with some GDI drawn rectangles on.  
The user can specify the size and location of these rectangles.

I need some math to handle when the users specifies a rectangle that is beyond the bounds of the form.  
I don't want to prevent oversizing, rather I want to constrain the rectangles within a given area but still preserve their relative positions and aspect ratios by reducing their size.

Hope that makes sense
Avatar of Bob Learned
Bob Learned
Flag of United States of America image

Aspect ratio = width / height.

If the width > height, then you will get a number > 1
If height > width, then you will get a number < 1

For a given height, you can determine the width by height * aspect ratio.

Avatar of Dodsworth
Dodsworth

ASKER

Math Meltdown!

How do I do it?
Hmmm...seemed self-explanatory.

Try something like this:


    Dim rect As New Rectangle(0, 0, 10, 5)
    ResizeRectangle(rect, 20)
 
...
 
    Public Shared Sub ResizeRectangle(ByRef rect As Rectangle, ByVal newHeight As Integer)
        Dim aspect As Decimal = rect.Width / rect.Height
 
        rect.Width = newHeight * aspect
        rect.Height = newHeight
    End Sub

Open in new window

First iterate over all of your rectangles and store their size/position with respect to the current size of the drawing area.

So if you had a drawing area of 500x750 and a rectangle at (25,100) with a size of 100x75:

    Dim locF As New PointF(25/500, 100/750)
    Dim sizF As New PointF(100/500, 75/750)

This could be thought of as the "percentage" of the location/size of the rectangle with respect to the drawing area.

Then you change your drawing area size to something else and you can calculate the new size position of the rectangle using the "percentage" values:

    Dim newLocation As New Point(NewWidth * locF.X, NewHeight * locF.Y)
    Dim NewSize As New Size(NewWidth * sizF.X, NewHeight * sizF.Y)
I think I see where your coming from but I'm not changing the size of the drawing area.

I've attached some code that draws 4 rectangles of a given size with a given space between.
When the size & gap becomes too large for all the rectangles to fit on the screen they should be scaled down to fit.

I know this sounds odd.  It's for a wizard.  The REAL dimentions of the rectangles and spacing will be applied elsewhere when the dialog is closed !
Imports System.Windows.Forms
 
Public Class QuickBed
    Public intScale As Integer = 0
    Private Sub OK_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK_Button.Click
        Me.DialogResult = System.Windows.Forms.DialogResult.OK
        Me.Close()
    End Sub
 
    Private Sub Cancel_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Cancel_Button.Click
        Me.DialogResult = System.Windows.Forms.DialogResult.Cancel
        Me.Close()
    End Sub
 
    Private Sub QuickBed_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
        Dim mXPos As Integer = 20
        Dim mYPos As Integer = 20
        e.Graphics.DrawRectangle(Pens.Black, mXPos, mYPos, CInt(nudLength.Text * 100), CInt(nudWidth.Text * 100))
        mYPos = mYPos + (nudWidth.Text * 100) + (nudPath.Text * 100)
        e.Graphics.DrawRectangle(Pens.Black, mXPos, mYPos, CInt(nudLength.Text * 100), CInt(nudWidth.Text * 100))
        mYPos = 20
        mXPos = mXPos + (nudLength.Text * 100) + (nudPath.Text * 100)
        e.Graphics.DrawRectangle(Pens.Black, mXPos, mYPos, CInt(nudLength.Text * 100), CInt(nudWidth.Text * 100))
        mYPos = mYPos + (nudWidth.Text * 100) + (nudPath.Text * 100)
        e.Graphics.DrawRectangle(Pens.Black, mXPos, mYPos, CInt(nudLength.Text * 100), CInt(nudWidth.Text * 100))
    End Sub
 
    Private Sub Size_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles nudWidth.ValueChanged, nudPath.ValueChanged, nudLength.ValueChanged
        'Size the rectangles so that they always fit the dialog
        'X?? = (nudLength.Text * 200) + (nudPath.Text * 200) + 40
        'Y?? = (nudWidth.Text * 200) + (nudPath.Text * 200) + 40
        Me.Invalidate()
    End Sub
End Class
 
 
 
 
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class QuickBed
    Inherits System.Windows.Forms.Form
 
    'Form overrides dispose to clean up the component list.
    <System.Diagnostics.DebuggerNonUserCode()> _
    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Try
            If disposing AndAlso components IsNot Nothing Then
                components.Dispose()
            End If
        Finally
            MyBase.Dispose(disposing)
        End Try
    End Sub
 
    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer
 
    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> _
    Private Sub InitializeComponent()
        Me.TableLayoutPanel1 = New System.Windows.Forms.TableLayoutPanel
        Me.OK_Button = New System.Windows.Forms.Button
        Me.Cancel_Button = New System.Windows.Forms.Button
        Me.nudLength = New System.Windows.Forms.NumericUpDown
        Me.nudWidth = New System.Windows.Forms.NumericUpDown
        Me.lblBy = New System.Windows.Forms.Label
        Me.nudPath = New System.Windows.Forms.NumericUpDown
        Me.TableLayoutPanel1.SuspendLayout()
        CType(Me.nudLength, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.nudWidth, System.ComponentModel.ISupportInitialize).BeginInit()
        CType(Me.nudPath, System.ComponentModel.ISupportInitialize).BeginInit()
        Me.SuspendLayout()
        '
        'TableLayoutPanel1
        '
        Me.TableLayoutPanel1.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.TableLayoutPanel1.ColumnCount = 2
        Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
        Me.TableLayoutPanel1.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
        Me.TableLayoutPanel1.Controls.Add(Me.OK_Button, 0, 0)
        Me.TableLayoutPanel1.Controls.Add(Me.Cancel_Button, 1, 0)
        Me.TableLayoutPanel1.Location = New System.Drawing.Point(448, 369)
        Me.TableLayoutPanel1.Name = "TableLayoutPanel1"
        Me.TableLayoutPanel1.RowCount = 1
        Me.TableLayoutPanel1.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50.0!))
        Me.TableLayoutPanel1.Size = New System.Drawing.Size(146, 29)
        Me.TableLayoutPanel1.TabIndex = 0
        '
        'OK_Button
        '
        Me.OK_Button.Anchor = System.Windows.Forms.AnchorStyles.None
        Me.OK_Button.Location = New System.Drawing.Point(3, 3)
        Me.OK_Button.Name = "OK_Button"
        Me.OK_Button.Size = New System.Drawing.Size(67, 23)
        Me.OK_Button.TabIndex = 0
        Me.OK_Button.Text = "OK"
        '
        'Cancel_Button
        '
        Me.Cancel_Button.Anchor = System.Windows.Forms.AnchorStyles.None
        Me.Cancel_Button.DialogResult = System.Windows.Forms.DialogResult.Cancel
        Me.Cancel_Button.Location = New System.Drawing.Point(76, 3)
        Me.Cancel_Button.Name = "Cancel_Button"
        Me.Cancel_Button.Size = New System.Drawing.Size(67, 23)
        Me.Cancel_Button.TabIndex = 1
        Me.Cancel_Button.Text = "Cancel"
        '
        'nudLength
        '
        Me.nudLength.DecimalPlaces = 1
        Me.nudLength.Increment = New Decimal(New Integer() {1, 0, 0, 65536})
        Me.nudLength.Location = New System.Drawing.Point(6, 377)
        Me.nudLength.Name = "nudLength"
        Me.nudLength.Size = New System.Drawing.Size(45, 20)
        Me.nudLength.TabIndex = 1
        Me.nudLength.Value = New Decimal(New Integer() {24, 0, 0, 65536})
        '
        'nudWidth
        '
        Me.nudWidth.DecimalPlaces = 1
        Me.nudWidth.Increment = New Decimal(New Integer() {1, 0, 0, 65536})
        Me.nudWidth.Location = New System.Drawing.Point(79, 377)
        Me.nudWidth.Name = "nudWidth"
        Me.nudWidth.Size = New System.Drawing.Size(45, 20)
        Me.nudWidth.TabIndex = 2
        Me.nudWidth.Value = New Decimal(New Integer() {12, 0, 0, 65536})
        '
        'lblBy
        '
        Me.lblBy.Location = New System.Drawing.Point(57, 380)
        Me.lblBy.Name = "lblBy"
        Me.lblBy.Size = New System.Drawing.Size(18, 17)
        Me.lblBy.TabIndex = 4
        Me.lblBy.Text = "X"
        '
        'nudPath
        '
        Me.nudPath.DecimalPlaces = 1
        Me.nudPath.Increment = New Decimal(New Integer() {1, 0, 0, 65536})
        Me.nudPath.Location = New System.Drawing.Point(150, 378)
        Me.nudPath.Name = "nudPath"
        Me.nudPath.Size = New System.Drawing.Size(45, 20)
        Me.nudPath.TabIndex = 5
        Me.nudPath.Value = New Decimal(New Integer() {7, 0, 0, 65536})
        '
        'QuickBed
        '
        Me.AcceptButton = Me.OK_Button
        Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
        Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
        Me.CancelButton = Me.Cancel_Button
        Me.ClientSize = New System.Drawing.Size(606, 410)
        Me.Controls.Add(Me.nudPath)
        Me.Controls.Add(Me.lblBy)
        Me.Controls.Add(Me.nudWidth)
        Me.Controls.Add(Me.nudLength)
        Me.Controls.Add(Me.TableLayoutPanel1)
        Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog
        Me.MaximizeBox = False
        Me.MinimizeBox = False
        Me.Name = "QuickBed"
        Me.ShowInTaskbar = False
        Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent
        Me.Text = "QuickBed"
        Me.TableLayoutPanel1.ResumeLayout(False)
        CType(Me.nudLength, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.nudWidth, System.ComponentModel.ISupportInitialize).EndInit()
        CType(Me.nudPath, System.ComponentModel.ISupportInitialize).EndInit()
        Me.ResumeLayout(False)
 
    End Sub
    Friend WithEvents TableLayoutPanel1 As System.Windows.Forms.TableLayoutPanel
    Friend WithEvents OK_Button As System.Windows.Forms.Button
    Friend WithEvents Cancel_Button As System.Windows.Forms.Button
    Friend WithEvents nudLength As System.Windows.Forms.NumericUpDown
    Friend WithEvents nudWidth As System.Windows.Forms.NumericUpDown
    Friend WithEvents lblBy As System.Windows.Forms.Label
    Friend WithEvents nudPath As System.Windows.Forms.NumericUpDown
 
End Class

Open in new window

"I think I see where your coming from but I'm not changing the size of the drawing area."

"When the size & gap becomes too large for all the rectangles to fit on the screen they should be scaled down to fit."

It's still the same concept...you need to store the RELATIONSHIP or PERCENTAGE of what the rectangles should occupy with respect to the UNSCALED area.  Then you can translate those values into the scaled drawing space.
Can I transform the group rather than each rect individually ?
Haven't studied your code closely...

Perhaps you can do something like this:
Public Class Form1
 
    Private scaleValue As Single = 1
    Private gp As New Drawing.Drawing2D.GraphicsPath
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        gp.AddRectangle(New Rectangle(10, 10, 25, 25))
        gp.AddRectangle(New Rectangle(50, 10, 10, 10))
        gp.AddRectangle(New Rectangle(10, 50, 50, 15))
    End Sub
 
    Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
        e.Graphics.ScaleTransform(scaleValue, scaleValue)
        e.Graphics.DrawPath(Pens.Black, gp)
    End Sub
 
    Private Sub btnSmaller_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSmaller.Click
        scaleValue = scaleValue - (scaleValue / 10)
        PictureBox1.Refresh()
    End Sub
 
    Private Sub btnBigger_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBigger.Click
        scaleValue = scaleValue + (scaleValue / 10)
        PictureBox1.Refresh()
    End Sub
 
End Class

Open in new window

You said:

    "The REAL dimentions of the rectangles and spacing will be applied elsewhere when the dialog is closed !"

Here is another approach...this scales both the x and y axis so that the entire GraphicsPath is drawn inside the PictureBox.  It doesn't matter how big or small the GraphicsPath or the PictureBox is...

The "REAL" dimensions are still preserved in the GraphicsPath so you can utilize that data elsewhere however you need.
Public Class Form1
 
    Private scaleValue As Single = -1
    Private gp As New Drawing.Drawing2D.GraphicsPath
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        gp.AddRectangle(New Rectangle(10, 10, 25, 25))
        gp.AddRectangle(New Rectangle(100, 10, 10, 10))
        gp.AddRectangle(New Rectangle(75, 50, 50, 15))
    End Sub
 
    Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
        If PictureBox1.IsHandleCreated Then
            Dim slop As Integer = 5
            Dim rf As RectangleF = gp.GetBounds
            Dim sf As New SizeF(PictureBox1.ClientRectangle.Width / (rf.Left + rf.Width + slop), PictureBox1.ClientRectangle.Height / (rf.Top + rf.Height + slop))
            e.Graphics.ScaleTransform(sf.Width, sf.Height)
            e.Graphics.DrawPath(Pens.Black, gp)
        End If
    End Sub
 
End Class

Open in new window

That works well but I need to 'Lock' the X Y scaling.

Currently if I expand X then Y remains unchanged.  This is not an issue with the rectangle sizing but does effect the display of the horizontal and vertical 'Gap' widths.
"That works well but I need to 'Lock' the X Y scaling."

Refer back to Bob's original comments on Aspect Ratio...

You need to apply that to the solution I have given.  First calculate the UNSCALED width to height aspect ratio (by examining the bounds).  Then calculate the necessary scale factor for the x axis.  Finally calculate the corresponding scale factor for the y xis using the aspect ratio computed at the beginning.
Like this ?

Dim scale As Integer = actualWidth / actualHeight
e.Graphics.ScaleTransform(ClientRectangle.Width / actualWidth, ClientRectangle.Width / actualWidth * scale)

Sorry to be thick but this doesn't seem to work correctly
Right...so this scales the X axis to fit in the PictureBox and then scales the Y axis appropriately to preserve the aspect ratio:
Public Class Form1
 
    Private scaleValue As Single = -1
    Private gp As New Drawing.Drawing2D.GraphicsPath
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        gp.AddRectangle(New Rectangle(10, 10, 25, 25))
        gp.AddRectangle(New Rectangle(100, 10, 10, 10))
        gp.AddRectangle(New Rectangle(75, 50, 50, 15))
    End Sub
 
    Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
        If PictureBox1.IsHandleCreated Then
            Dim slop As Integer = 5
            Dim rf As RectangleF = gp.GetBounds
            Dim aspectRatio As Double = (rf.Left + rf.Width + slop) / (rf.Top + rf.Height + slop)
            Dim xScale As Double = PictureBox1.ClientRectangle.Width / (rf.Left + rf.Width + slop)
            Dim yScale As Double = xScale / aspectRatio
            e.Graphics.ScaleTransform(xScale, yScale)
            e.Graphics.DrawPath(Pens.Black, gp)
        End If
    End Sub
 
 
End Class

Open in new window

Oh 'eck
I now get the sizing math but your solution is based on adding rectangles to a gp on frm.load.

It's the size of the rectangles and the space between then that is changed by the user.

Let me rephraze my question....

Four rectangles spaced in two rows of two columns.  Distance between each rectangle both horizontally a vertically is identicle.  User can increase the width of the rectangles, the height and the distance between them.  Height, width and distance between are common to all rectangles.

When the user 'sizes' the rectangle group beyond the bounds of the picturebox the group should be transformed to remain within the bounds of the picturebox

"...but your solution is based on adding rectangles to a gp on frm.load."

You can clear the GraphicsPath and rebuild it whenever or from whereever you want:

Public Class Form1
 
    Private scaleValue As Single = -1
    Private gp As New Drawing.Drawing2D.GraphicsPath
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        BuildRectangles()
    End Sub
 
    Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
        If PictureBox1.IsHandleCreated Then
            Dim slop As Integer = 5
            Dim rf As RectangleF = gp.GetBounds
            Dim aspectRatio As Double = (rf.Left + rf.Width + slop) / (rf.Top + rf.Height + slop)
            Dim xScale As Double = PictureBox1.ClientRectangle.Width / (rf.Left + rf.Width + slop)
            Dim yScale As Double = xScale / aspectRatio
            e.Graphics.ScaleTransform(xScale, yScale)
            e.Graphics.DrawPath(Pens.Black, gp)
        End If
    End Sub
 
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        BuildRectangles()
    End Sub
 
    Private Sub BuildRectangles()
        ' ...use whatever parameters you need...
        gp.Reset()
        gp.AddRectangle(New Rectangle(10, 10, 25, 25))
        gp.AddRectangle(New Rectangle(100, 10, 10, 10))
        gp.AddRectangle(New Rectangle(75, 50, 50, 15))
        PictureBox1.Refresh()
    End Sub
 
End Class

Open in new window

I added my rectangles to your code but they do not size within the PB correctly.
Imports System.Windows.Forms
 
Public Class QuickBed
 
    Private gp As New Drawing.Drawing2D.GraphicsPath
 
    Private Sub OK_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK_Button.Click
        Me.DialogResult = System.Windows.Forms.DialogResult.OK
        Me.Close()
    End Sub
 
    Private Sub Cancel_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Cancel_Button.Click
        Me.DialogResult = System.Windows.Forms.DialogResult.Cancel
        Me.Close()
    End Sub
 
    Private Sub pbQuickBed_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint, pbQuickBed.Paint
 
        Dim slop As Integer = 5
        Dim rf As RectangleF = gp.GetBounds
        Dim aspectRatio As Double = (rf.Left + rf.Width + slop) / (rf.Top + rf.Height + slop)
        Dim xScale As Double = pbQuickBed.ClientRectangle.Width / (rf.Left + rf.Width + slop)
        Dim yScale As Double = xScale / aspectRatio
        e.Graphics.ScaleTransform(xScale, yScale)
        e.Graphics.DrawPath(Pens.Black, gp)
 
    End Sub
 
    Private Sub Size_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles nudWidth.ValueChanged, nudPath.ValueChanged, nudLength.ValueChanged
        BuildRectangles()
    End Sub
    Private Sub BuildRectangles()
 
        Dim mXPos As Integer = 20
        Dim mYPos As Integer = 20
 
        gp.Reset()
        gp.AddRectangle(New Rectangle(mXPos, mYPos, CInt(nudLength.Text * 100), CInt(nudWidth.Text * 100)))
        mYPos = mYPos + (nudWidth.Text * 100) + (nudPath.Text * 100)
        gp.AddRectangle(New Rectangle(mXPos, mYPos, CInt(nudLength.Text * 100), CInt(nudWidth.Text * 100)))
        mYPos = 20
        mXPos = mXPos + (nudLength.Text * 100) + (nudPath.Text * 100)
        gp.AddRectangle(New Rectangle(mXPos, mYPos, CInt(nudLength.Text * 100), CInt(nudWidth.Text * 100)))
        mYPos = mYPos + (nudWidth.Text * 100) + (nudPath.Text * 100)
        gp.AddRectangle(New Rectangle(mXPos, mYPos, CInt(nudLength.Text * 100), CInt(nudWidth.Text * 100)))
        pbQuickBed.Refresh()
    End Sub
 
End Class

Open in new window

You should NOT have the "MyBase.Paint" here:

    Private Sub pbQuickBed_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles pbQuickBed.Paint

Could you be more specific on the sizing problem?...
Difficult to say what's happening ! (you could paste my code and see)

If I set width and height of the rects to 1 they do not appear square.
Decrease the width below 1 and the rects move out of the PB bounds to the bottom.
Increase the height above 1 and the same happens.
I'll be at the Experts-Exchange Core Conference in San Luis Obispo, CA today and tomorrow so I may not be able to get back to this one until this weekend...  =\
Have fun ;)
Hi Dodsworth,

Have you made any progress on this project?...was going to start playing with this again but want to make sure I am using your latest code.

(or if you've figured it out...remove it from my inbox...)

~IM
No more progress... I decided to attend my own private Beer Conference while you were away ;)
Any further thoughts ?
So near......
Please finish this for me IM, your genius knows no bounds ;)
Lol...I'll play with it some more today.  =)
Based on your high level description:

    "Four rectangles spaced in two rows of two columns.  Distance between each rectangle both horizontally a vertically is identicle.  User can increase the width of the rectangles, the height and the distance between them.  Height, width and distance between are common to all rectangles."

How about this one then?
Public Class QuickBed
 
    Private Sub QuickBed_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        pbQuickBed.SizeMode = PictureBoxSizeMode.Zoom
    End Sub
 
    Private Sub OK_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK_Button.Click
        Me.DialogResult = System.Windows.Forms.DialogResult.OK
    End Sub
 
    Private Sub Cancel_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Cancel_Button.Click
        Me.DialogResult = System.Windows.Forms.DialogResult.Cancel
    End Sub
 
    Private Sub Size_ValueChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles nudWidth.ValueChanged, nudSpace.ValueChanged, nudHeight.ValueChanged
        pbQuickBed.Image = BuildRectangles()
    End Sub
 
    Private Function BuildRectangles() As Bitmap
        Dim mXPos As Integer = 20
        Dim mYPos As Integer = 20
 
        Dim bmp As New Bitmap(CInt((2 * nudWidth.Value) + (2 * mXPos) + nudSpace.Value), CInt((2 * nudHeight.Value) + (2 * mYPos) + nudSpace.Value))
        Dim G As Graphics = Graphics.FromImage(bmp)
 
        G.DrawRectangle(Pens.Black, New Rectangle(mXPos, mYPos, nudWidth.Value, nudHeight.Value))
        G.DrawRectangle(Pens.Black, New Rectangle(mXPos + nudWidth.Value + nudSpace.Value, mYPos, nudWidth.Value, nudHeight.Value))
        G.DrawRectangle(Pens.Black, New Rectangle(mXPos, mYPos + nudHeight.Value + nudSpace.Value, nudWidth.Value, nudHeight.Value))
        G.DrawRectangle(Pens.Black, New Rectangle(mXPos + nudWidth.Value + nudSpace.Value, mYPos + nudHeight.Value + nudSpace.Value, nudWidth.Value, nudHeight.Value))
        G.Dispose()
        Return bmp
    End Function
 
End Class

Open in new window

QuickBed.jpg
Ah PictureBoxSizeMode.Zoom.... clever trick

I need the Rects to fill more of the PB (less empty space)
The width and length values would typically be between 0.5 and 15.

which bit do I tweek to get them visible when that small ?
ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial