Solved

grid over jpg - continued

Posted on 2014-10-03
5
173 Views
Last Modified: 2014-10-03
hello,
  i have asked for an add-on here :  http://www.experts-exchange.com/Programming/Languages/CPP/Q_28527294.html

it works fine, but i found a drawback ; if i position the fgrid somewhere - and change the # of rows, or Columns, it resets the grid back to 0.

can it be made to stay on the selected coordinates?
0
Comment
Question by:nobus
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
5 Comments
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 40359055
Well you could start by removing lines 90 and 91 (in the code posted on your previous question), which does the actual reset (shown in context here):
    Private Sub Rows_Cols_ValueChanged(sender As Object, e As System.EventArgs) Handles Rows.ValueChanged, Cols.ValueChanged
        GridOffsetX = 0 ' line 90
        GridOffsetY = 0 ' line 91
        PB.Refresh()
    End Sub

Open in new window

But like I said in a later comment, without that code the grid appears to jump when sliding it again after changing rows or columns.

That could possibly be remedied by remembering (in another global class variable) where you actually positioned the grid last but that would have to be based on the assumption that you actually click on a point of the grid that you want positioned on an exact spot. Then a bit of adding and subtracting should make it possible to reset the offsets (to something other than 0) to make sure that with the new rows/columns setting the grid actually stays put at that point, but only for that point.

EDIT: maybe even simpler by using that last clicked point as grid origin point instead of using offsets.
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 40359072
Yeah, probably the easiest way to do it:
Public Class Form1

    Private GridColor As Color = Color.Black
    ' additional members for grid offset
    Private GridOffsetX As Integer = 0
    Private GridOffsetY As Integer = 0
    Private GridOffsetPrvX As Integer = -1
    Private GridOffsetPrvY As Integer = -1
    Private GridMoving As Boolean = False

    Private WithEvents PB As New PictureBox
    Private WithEvents Rows As New NumericUpDown
    Private WithEvents Cols As New NumericUpDown
    Private WithEvents btnSelectFile As New Button
    Private WithEvents btnSelectColor As New Button

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Rows.Minimum = 2
        Cols.Minimum = 2

        Dim TLB As New TableLayoutPanel
        TLB.RowCount = 2
        TLB.RowStyles.Add(New RowStyle(SizeType.AutoSize))
        TLB.RowStyles.Add(New RowStyle(SizeType.Percent, 100))
        TLB.ColumnCount = 6
        TLB.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 20))
        TLB.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 20))
        TLB.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 20))
        TLB.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 20))
        TLB.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 20))
        TLB.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 20))

        Dim lbl As New Label
        lbl.Text = "Rows:"
        lbl.TextAlign = ContentAlignment.TopRight
        lbl.Dock = DockStyle.Bottom
        TLB.Controls.Add(lbl, 0, 0)
        TLB.Controls.Add(Rows, 1, 0)

        lbl = New Label
        lbl.Text = "Cols:"
        lbl.TextAlign = ContentAlignment.TopRight
        lbl.Dock = DockStyle.Bottom
        TLB.Controls.Add(lbl, 2, 0)
        TLB.Controls.Add(Cols, 3, 0)

        btnSelectFile.Text = "Pic"
        btnSelectFile.AutoSize = True
        btnSelectFile.Dock = DockStyle.Fill
        TLB.Controls.Add(btnSelectFile, 4, 0)

        btnSelectColor.Text = "Color"
        btnSelectColor.AutoSize = True
        btnSelectColor.Dock = DockStyle.Fill
        TLB.Controls.Add(btnSelectColor, 5, 0)

        PB.Dock = DockStyle.Fill
        PB.SizeMode = PictureBoxSizeMode.Zoom
        PB.BorderStyle = BorderStyle.FixedSingle
        TLB.Controls.Add(PB, 0, 1)
        TLB.SetColumnSpan(PB, 6)

        TLB.Dock = DockStyle.Fill
        Me.Controls.Add(TLB)
        Me.Text = "Image Grid Tool"
    End Sub

    Private Sub btnSelectFile_Click(sender As Object, e As System.EventArgs) Handles btnSelectFile.Click
        Static OFD As New OpenFileDialog
        OFD.Title = "Select an Image File"
        OFD.Filter = "Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|All files (*.*)|*.*"
        If OFD.ShowDialog = Windows.Forms.DialogResult.OK Then
            Try
                PB.Image = New Bitmap(Image.FromFile(OFD.FileName))
            Catch ex As Exception
                MessageBox.Show("File: " & OFD.FileName & vbCrLf & vbCrLf & ex.ToString, "Error Opening Image", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
        End If
    End Sub

    Private Sub btnSelectColor_Click(sender As Object, e As System.EventArgs) Handles btnSelectColor.Click
        Static CD As New ColorDialog
        If CD.ShowDialog = Windows.Forms.DialogResult.OK Then
            GridColor = CD.Color
            PB.Refresh()
        End If
    End Sub

    Private Sub Rows_Cols_ValueChanged(sender As Object, e As System.EventArgs) Handles Rows.ValueChanged, Cols.ValueChanged
        PB.Refresh()
    End Sub

    Private Sub PB_SizeChanged(sender As Object, e As System.EventArgs) Handles PB.SizeChanged
        PB.Refresh()
    End Sub

    Private Sub PB_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles PB.Paint
        Using pn As New Pen(GridColor)
            Dim xValue, yValue As Integer
            For y As Integer = 1 To Rows.Value
                yValue = (y / Rows.Value * PB.Height + GridOffsetY) Mod PB.Height
                If yValue > 0 And yValue < PB.Height - 3 Then ' don't draw line right up against top or bottom border
                    e.Graphics.DrawLine(pn, 0, yValue, PB.Width, yValue)
                End If
            Next
            For x As Integer = 1 To Cols.Value
                xValue = (x / Cols.Value * PB.Width + GridOffsetX) Mod PB.Width
                If xValue > 0 And xValue < PB.Width - 3 Then ' don't draw line right up against left or right border
                    e.Graphics.DrawLine(pn, xValue, 0, xValue, PB.Height)
                End If
            Next
        End Using
    End Sub

    Private Sub PB_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles PB.MouseDown
        If e.Button = Windows.Forms.MouseButtons.Left Then
            GridMoving = True
            GridOffsetPrvX = e.X
            GridOffsetPrvY = e.Y
        End If
    End Sub

    Private Sub PB_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles PB.MouseUp
        GridMoving = False
        GridOffsetX = e.X
        GridOffsetY = e.Y
    End Sub

    Private Sub PB_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles PB.MouseMove
        If GridMoving Then
            GridOffsetX += e.X - GridOffsetPrvX
            GridOffsetY += e.Y - GridOffsetPrvY
            ' keep it positive for the 'mod' to work in PB_Paint
            While GridOffsetX < 0
                GridOffsetX += PB.Width
            End While
            While GridOffsetY < 0
                GridOffsetY += PB.Height
            End While
            ' remember new position for next move
            GridOffsetPrvX = e.X
            GridOffsetPrvY = e.Y
            PB.Refresh()
        End If
    End Sub

End Class

Open in new window

0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 40359078
so in case you wonder; the last point is now set directly as the new offset on MouseUp which means the actual point where you release the mouse becomes the exact offset position with the effect of keeping the grid static, pinned to that point as it were, when changing rows/columns afterwards.

couple of notes:
- resize has a funky effect... (may want to put the reset back in for that?)
- the zoomstyle of the picturebox can have the visual effect of changing the actual position of the grid over the picture. If you elaborate on how you do the positioning and if you need to keep that 'static' as well, if needed it would be possible to do the calculations for that.
0
 
LVL 35

Accepted Solution

by:
Robert Schutt earned 500 total points
ID: 40359441
Well now I'm just having fun with this (and learning from it!) - here's a version that takes my previous remark about a static point as grid origin as its basis. The point is shown as a red circle but that's mainly to show what's going on, see comment - "can be removed".

There are some rounding problems when the form is resized very small but otherwise it should have a nice effect now: you choose an origin point and the grid stays static at that point and other changes (resize, changing rows or columns) revolve around that point, also taking into account the zooming of the image in the picturebox. Note that one more change I made is to draw the grid on the image only, not on the entire picturebox anymore.
Public Class Form1

    Private GridColor As Color = Color.Black
    ' additional members for grid offset
    Private GridOffsetX As Integer = 0
    Private GridOffsetY As Integer = 0
    Private GridMoving As Boolean = False
    Private PictureOffset As Point
    Private PictureZoomRatio As Single

    Private WithEvents PB As New PictureBox
    Private WithEvents Rows As New NumericUpDown
    Private WithEvents Cols As New NumericUpDown
    Private WithEvents btnSelectFile As New Button
    Private WithEvents btnSelectColor As New Button

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Rows.Minimum = 2
        Cols.Minimum = 2

        Dim TLB As New TableLayoutPanel
        TLB.RowCount = 2
        TLB.RowStyles.Add(New RowStyle(SizeType.AutoSize))
        TLB.RowStyles.Add(New RowStyle(SizeType.Percent, 100))
        TLB.ColumnCount = 6
        TLB.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 20))
        TLB.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 20))
        TLB.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 20))
        TLB.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 20))
        TLB.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 20))
        TLB.ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 20))

        Dim lbl As New Label
        lbl.Text = "Rows:"
        lbl.TextAlign = ContentAlignment.TopRight
        lbl.Dock = DockStyle.Bottom
        TLB.Controls.Add(lbl, 0, 0)
        TLB.Controls.Add(Rows, 1, 0)

        lbl = New Label
        lbl.Text = "Cols:"
        lbl.TextAlign = ContentAlignment.TopRight
        lbl.Dock = DockStyle.Bottom
        TLB.Controls.Add(lbl, 2, 0)
        TLB.Controls.Add(Cols, 3, 0)

        btnSelectFile.Text = "Pic"
        btnSelectFile.AutoSize = True
        btnSelectFile.Dock = DockStyle.Fill
        TLB.Controls.Add(btnSelectFile, 4, 0)

        btnSelectColor.Text = "Color"
        btnSelectColor.AutoSize = True
        btnSelectColor.Dock = DockStyle.Fill
        TLB.Controls.Add(btnSelectColor, 5, 0)

        PB.Dock = DockStyle.Fill
        PB.SizeMode = PictureBoxSizeMode.Zoom
        PB.BorderStyle = BorderStyle.FixedSingle
        TLB.Controls.Add(PB, 0, 1)
        TLB.SetColumnSpan(PB, 6)

        TLB.Dock = DockStyle.Fill
        Me.Controls.Add(TLB)
        Me.Text = "Image Grid Tool"
    End Sub

    Private Sub btnSelectFile_Click(sender As Object, e As System.EventArgs) Handles btnSelectFile.Click
        Static OFD As New OpenFileDialog
        OFD.Title = "Select an Image File"
        OFD.Filter = "Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|All files (*.*)|*.*"
        If OFD.ShowDialog = Windows.Forms.DialogResult.OK Then
            Try
                PB.Image = New Bitmap(Image.FromFile(OFD.FileName))
                PictureOffset = GetPictureOffset()
            Catch ex As Exception
                MessageBox.Show("File: " & OFD.FileName & vbCrLf & vbCrLf & ex.ToString, "Error Opening Image", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End Try
        End If
    End Sub

    Private Sub btnSelectColor_Click(sender As Object, e As System.EventArgs) Handles btnSelectColor.Click
        Static CD As New ColorDialog
        If CD.ShowDialog = Windows.Forms.DialogResult.OK Then
            GridColor = CD.Color
            PB.Refresh()
        End If
    End Sub

    Private Sub Rows_Cols_ValueChanged(sender As Object, e As System.EventArgs) Handles Rows.ValueChanged, Cols.ValueChanged
        PB.Refresh()
    End Sub

    Private Sub PB_SizeChanged(sender As Object, e As System.EventArgs) Handles PB.SizeChanged
        If PB.Image IsNot Nothing Then
            Select Case PB.SizeMode
                Case PictureBoxSizeMode.Zoom ' the others could be added if needed...
                    Dim bakRatio As Single = PictureZoomRatio
                    Dim NewPictureOffset As Point = GetPictureOffset()
                    PictureOffset = NewPictureOffset
                    GridOffsetX *= PictureZoomRatio / bakRatio
                    GridOffsetY *= PictureZoomRatio / bakRatio
            End Select
        End If
        PB.Refresh()
    End Sub

    Private Function GetPictureOffset() As Point
        Dim pbw As Integer = PB.Width, pbh As Integer = PB.Height
        If PB.BorderStyle = BorderStyle.FixedSingle Then pbw -= 2 : pbh -= 2
        Dim ratioX As Single = pbw / PB.Image.Width, ratioY As Single = pbh / PB.Image.Height
        Dim newImageWidth, newImageHeight As Integer
        If ratioX > ratioY Then
            PictureZoomRatio = ratioY
            newImageWidth = PB.Image.Width * ratioY
            newImageHeight = pbh
        Else
            PictureZoomRatio = ratioX
            newImageWidth = pbw
            newImageHeight = PB.Image.Height * ratioX
        End If
        Me.Text = String.Format("DEBUG: ratio x/y/final = {0}/{1}/{2}", ratioX, ratioY, PictureZoomRatio)
        Return New Point((pbw - newImageWidth) / 2, (pbh - newImageHeight) / 2)
    End Function

    Private Sub PB_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles PB.Paint
        Dim pbw As Integer = PB.Width, pbh As Integer = PB.Height
        If PB.Image IsNot Nothing Then
            pbw = PB.Image.Width * PictureZoomRatio
            pbh = PB.Image.Height * PictureZoomRatio
            ' some extra visual clues for "debugging" - can be removed or made into options
            e.Graphics.DrawRectangle(Pens.Red, PictureOffset.X, PictureOffset.Y, pbw - 1, pbh - 1)
            e.Graphics.DrawEllipse(Pens.Red, PictureOffset.X + GridOffsetX - 6, PictureOffset.Y + GridOffsetY - 6, 11, 11)
        Else
            If PB.BorderStyle = BorderStyle.FixedSingle Then pbw -= 2 : pbh -= 2
        End If
        Using pn As New Pen(GridColor)
            Dim xValue, yValue As Integer
            For y As Integer = 1 To Rows.Value
                yValue = (y / Rows.Value * pbh + GridOffsetY) Mod pbh
                If yValue > 0 And yValue < pbh - 3 Then ' don't draw line right up against top or bottom border
                    e.Graphics.DrawLine(pn, PictureOffset.X, yValue + PictureOffset.Y, pbw + PictureOffset.X, yValue + PictureOffset.Y)
                End If
            Next
            For x As Integer = 1 To Cols.Value
                xValue = (x / Cols.Value * pbw + GridOffsetX) Mod pbw
                If xValue > 0 And xValue < pbw - 3 Then ' don't draw line right up against left or right border
                    e.Graphics.DrawLine(pn, xValue + PictureOffset.X, PictureOffset.Y, xValue + PictureOffset.X, pbh + PictureOffset.Y)
                End If
            Next
        End Using
    End Sub

    Private Sub PB_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles PB.MouseDown
        If e.Button = Windows.Forms.MouseButtons.Left Then
            GridMoving = True
        End If
    End Sub

    Private Sub PB_MouseUp(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles PB.MouseUp
        GridMoving = False
        GridOffsetX = e.X - PictureOffset.X
        GridOffsetY = e.Y - PictureOffset.Y
        PB.Refresh()
    End Sub

    Private Sub PB_MouseMove(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles PB.MouseMove
        If GridMoving Then
            GridOffsetX = e.X - PictureOffset.X
            GridOffsetY = e.Y - PictureOffset.Y
            PB.Refresh()
        End If
    End Sub

End Class

Open in new window

0
 
LVL 92

Author Closing Comment

by:nobus
ID: 40359559
many thanks - again - Robert!
0

Featured Post

Three Reasons Why Backup is Strategic

Backup is strategic to your business because your data is strategic to your business. Without backup, your business will fail. This white paper explains why it is vital for you to design and immediately execute a backup strategy to protect 100 percent of your data.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When we want to run, execute or repeat a statement multiple times, a loop is necessary. This article covers the two types of loops in Python: the while loop and the for loop.
Whether you’re a college noob or a soon-to-be pro, these tips are sure to help you in your journey to becoming a programming ninja and stand out from the crowd.
This Micro Tutorial will give you a basic overview of Windows DVD Burner through its features and interface. This will be demonstrated using Windows 7 operating system.
The viewer will learn how to successfully create a multiboot device using the SARDU utility on Windows 7. Start the SARDU utility: Change the image directory to wherever you store your ISOs, this will prevent you from having 2 copies of an ISO wit…

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question