?
Solved

grid over jpg - continued

Posted on 2014-10-03
5
Medium Priority
?
180 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 2000 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

Back Up Your Microsoft Windows Server®

Back up all your Microsoft Windows Server – on-premises, in remote locations, in private and hybrid clouds. Your entire Windows Server will be backed up in one easy step with patented, block-level disk imaging. We achieve RTOs (recovery time objectives) as low as 15 seconds.

Question has a verified solution.

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

Possible fixes for Windows 7 and Windows Server 2008 updating problem. Solutions mentioned are from Microsoft themselves. I started a case with them from our Microsoft Silver Partner option to open a case and get direct support from Microsoft. If s…
Create a Windows 10 custom Image with custom task bar and custom start menu using XML for deployment.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Suggested Courses

762 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