Solved

grid over jpg - continued

Posted on 2014-10-03
5
164 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
  • 4
5 Comments
 
LVL 35

Expert Comment

by:Robert Schutt
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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 91

Author Closing Comment

by:nobus
Comment Utility
many thanks - again - Robert!
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

New Windows 7 Installations take days for Windows-Updates to show up and install. This can easily be fixed. I have finally decided to write an article because this seems to get asked several times a day lately. This Article and the Links apply to…
When you start your Windows 10 PC and got an "Operating system not found" error or just saw  "Auto repair for startup". After a while, you have entered a loop for Auto repair which does not fix anything and you will be in a  panic as all your work w…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

728 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now