Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Graphical Drag and Drop interface in VB.NET

Posted on 2005-03-22
15
Medium Priority
?
757 Views
Last Modified: 2010-05-08
I am trying to create a simple Calendar program.

But, I want an iterface that allows me to have a toolbox on the left hand side (Like the VS IDE one)
Be able to drag and drop a control which in this case, would be months, days and years. 3 objects. MONTH DAY and YEAR.
then, be able to have a Start and Finish place in the "designer" window to the right of the toolbox.

I need to be able to drag and drop items from the tool box onto the "designer" window. Then, be able to connect them with lines depending on what is programmed with each module.

so lets say I drag Month, Day and Years over to the designer. I want to be able to open a form that has the options for the Month. In this case, the month of the year.
then the same for the day and the one for the year object.


I know this is a rough draft, but I need to know where to start on this.
0
Comment
Question by:cjinsocal581
[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
  • 5
  • 5
  • 4
  • +1
15 Comments
 
LVL 6

Expert Comment

by:Svetlin_Panayotov
ID: 13609122
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 13611283
Are you trying to create a calendar designer system?  It sure sounds like that's the direction you have chosen to me.

Bob
0
 
LVL 6

Author Comment

by:cjinsocal581
ID: 13612473
Actually, no. I am trying to create a usable model that I can implement Drag and Drop items in any program I create. It could be a calendar, ivr or whatever.

Basically giving the end user the ability to set certain features of each item.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 6

Author Comment

by:cjinsocal581
ID: 13612509
Check this out: http://www.ivrsoft.com/ct-developer-studio.htm

Scroll down to the bottom, and see the "Script designer"

That is EXACTLY what I want to create.
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 13612660
Such broad questions make me ask, "Where do you want to start?"  

Do you have something going?  Do you need direction?  Did the article that Svetlin indicated give you any insights into drag/drop operations?  Do you understand about MDI applications?

Bob
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 13612740
Hi cjinsocal581,

I am currently on vacation until late next week so I can't give you all the code necessary.  =(

In the mean time, here is some code that demonstrates how to drag moveable/resizeable rectangles onto your form:
http://www.experts-exchange.com/Programming/Q_21136038.html

When I get home (if this question is still open) I will post another version that allows you to connect the rectangles with lines.  It will give you a good start on your app (I think).

~IM
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 13612773
Here is another version of that code that has more featuers and allows serialization:
http://www.experts-exchange.com/Programming/Programming_Languages/Dot_Net/VB_DOT_NET/Q_21158325.html
0
 
LVL 6

Author Comment

by:cjinsocal581
ID: 13612847
Idle_Mind: Thanks. This is an excellent start to it.

TheLearnedOne: I tried the example, but the sample that Idle_Mind provided is more of what I am looking for. I appreciate the effort on this one.
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 13612859
As always, the not-so-idle Mind comes through again.

Bob
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 13612953
I have a version at home that allows you to connect the boxes with a line using the drag handles as connection points.  Of course, the lines move as you resize/move the boxes but currently only straight lines are used so it will need much modification to get to the point where it behaves like the app you cited as an example.  =)
0
 
LVL 6

Author Comment

by:cjinsocal581
ID: 13612976
No worries... Have a good vacation and will wait for ya till you get back.

Again, that is WAY above and beyond what I need but it is close to what I want to accomplish.

I am trying to get it into a more simplistic manner.

A few items in a toolbox, drag them over to the "area" connect them and be able to program something on each one. Like message boxes or open other apps. Just basic calls.
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 13613044
What you can do is create an Interface that exposes some events that your "objects" raise and that your main app can trap.  Then derive a couple classes from the base BOX class and make them implement that Interface.  This will allow you to give them each their own properties/events/graphical looks while allowing common GUI interface code that can handle any new derived objects with little change in code for the main GUI part.
0
 
LVL 96

Expert Comment

by:Bob Learned
ID: 13697024
So, Mike, did you have a nice vacation?

Bob
0
 
LVL 86

Accepted Solution

by:
Mike Tomlinson earned 2000 total points
ID: 13698358
=)

Yes!  Thank You much Bob...was beautiful down in sunny San Diego, California.

Been awhile since I've been able to get my whole family down to visit with my parents.  The kids were excited to see Grandma and Grandpa again and they are both old enough so they might actually remember the trip when they are older.  My dad's health isn't very good so I really wanted to vacation before the passage of time dictated it instead be a flight worked around a funeral schedule.  =\


Anyhoo...below is the modified code from the second link I provided that allows you to place connecting lines between the drag handles on the boxes.  Drag at least two boxes on the form and then hit the "Connect" button.  When you hover over a box, the handles will highlight red showing you where the first endpoint of the line can be attached.  Then hover over another box and select another handle to attach to.  Now you can move/resize the boxes and the line will move accordingly.

Hope it helps you finish your project cjinsocal581.

Let me know what you guys think of it.  There are so many ways to go about this kind of thing I wasn't sure what the best way to represent the connections was...

' ----------------------------------------------------------------------------
' Class Sign
' ----------------------------------------------------------------------------
<Serializable()> Public Class Sign

    Public Enum SignEdge
        None = 0
        North = 1
        NorthEast = 2
        East = 3
        SouthEast = 4
        South = 5
        SouthWest = 6
        West = 7
        NorthWest = 8
    End Enum

    Public Enum Action
        None = 0
        Resize = 1
        Move = 2
        Editing = 3
    End Enum

    Public Text As String
    Public TextFont As Font
    Public TextColor As Color = Color.Black
    Private Rect As Rectangle
    Private RectHandles(7) As Rectangle
    Private Connections(7) As ArrayList

    Public ReadOnly Property signSize() As Size
        Get
            Return Rect.Size
        End Get
    End Property

    Public ReadOnly Property signLocation() As Point
        Get
            Return New Point(Rect.X, Rect.Y)
        End Get
    End Property

    Public Property signAction() As Action
        Get
            Return curAction
        End Get
        Set(ByVal Value As Action)
            curAction = Value
        End Set
    End Property

    Public ReadOnly Property getHandleCoord(ByVal edge As SignEdge) As Point
        Get
            Dim p As Point = New Point(Rect.X, Rect.Y)
            If Not (edge = SignEdge.None) Then
                p.X = RectHandles(edge - 1).X + (HandleWidth / 2)
                p.Y = RectHandles(edge - 1).Y + (HandleWidth / 2)
            End If
            Return p
        End Get
    End Property

    <NonSerialized()> Public showHandles As Boolean = False
    <NonSerialized()> Public Highlighted As Boolean = False
    <NonSerialized()> Public ConnectionCandidate As Boolean = False
    <NonSerialized()> Private draggingEdge As SignEdge = SignEdge.None
    <NonSerialized()> Private startX As Integer
    <NonSerialized()> Private startY As Integer
    <NonSerialized()> Private curAction As Action = Action.None
    <NonSerialized()> Public Const HandleWidth As Byte = 8
    <NonSerialized()> Private WithEvents sourcePictureBox As PictureBox = Nothing

    Private Sub New()
    End Sub

    Public Sub New(ByVal r As Rectangle)
        Rect = r
        updateRectHandles()
        Dim i As Integer
        For i = 0 To 7
            Connections(i) = New ArrayList
        Next
    End Sub

    Public Sub Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)
        If curAction = Action.Editing Then
            Dim pb As PictureBox = CType(sender, PictureBox)
            Dim sb As New SolidBrush(pb.BackColor)
            e.Graphics.FillRectangle(sb, Rect)
            sb.Dispose()
        End If
        If Highlighted Then
            e.Graphics.DrawRectangle(Pens.Red, Rect)
        Else
            e.Graphics.DrawRectangle(Pens.Black, Rect)
        End If
        If showHandles Then
            e.Graphics.FillRectangles(Brushes.Black, RectHandles)
        End If

        Dim textRect As New RectangleF(Rect.X + HandleWidth, Rect.Y + HandleWidth, Rect.Width - (2 * HandleWidth), Rect.Height - (2 * HandleWidth))
        If textRect.Width > 0 And textRect.Height > 0 Then
            Dim b As New SolidBrush(TextColor)
            e.Graphics.DrawString(Text, _
            IIf(TextFont Is Nothing, sender.font, TextFont), b, textRect)
            b.Dispose()
        End If

        Dim i As Integer
        Dim c As Connection
        Dim sourcePoint As Point
        Dim targetPoint As Point
        For i = 0 To 7
            For Each c In Connections(i)
                sourcePoint = Me.getHandleCoord(i + 1)
                targetPoint = c.ToSign.getHandleCoord(c.ToEdge)
                e.Graphics.DrawLine(Pens.Black, sourcePoint, targetPoint)
            Next
        Next

        If ConnectionCandidate Then
            e.Graphics.FillRectangles(Brushes.Red, RectHandles)
        End If
    End Sub

    Public Function isOverEdge(ByVal x As Integer, ByVal y As Integer) As SignEdge
        Dim i As Integer

        For i = 1 To 8
            If RectHandles(i - 1).Contains(x, y) Then
                Return i
            End If
        Next
        Return SignEdge.None
    End Function

    Public Function isOverSign(ByVal x As Integer, ByVal y As Integer) As Boolean
        Return Rect.Contains(x, y)
    End Function

    Public Sub dragEdge(ByVal pb As PictureBox, ByVal edge As SignEdge, ByVal x As Integer, ByVal y As Integer)
        curAction = Action.Resize
        draggingEdge = edge
        startX = x
        startY = y
        sourcePictureBox = pb
    End Sub

    Public Sub dragSign(ByVal pb As PictureBox, ByVal x As Integer, ByVal y As Integer)
        curAction = Action.Move
        startX = x
        startY = y
        sourcePictureBox = pb
    End Sub

    Private Sub sourcePictureBox_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles sourcePictureBox.MouseMove
        Dim p As Point
        Select Case curAction
            Case Action.Resize
                Select Case draggingEdge
                    Case SignEdge.North
                        Rect.Y = Rect.Y + (e.Y - startY)
                        Rect.Height = Rect.Height - (e.Y - startY)

                    Case SignEdge.NorthEast
                        Rect.Y = Rect.Y + (e.Y - startY)
                        Rect.Height = Rect.Height - (e.Y - startY)
                        Rect.Width = Rect.Width + (e.X - startX)

                    Case SignEdge.East
                        Rect.Width = Rect.Width + (e.X - startX)

                    Case SignEdge.SouthEast
                        Rect.Height = Rect.Height + (e.Y - startY)
                        Rect.Width = Rect.Width + (e.X - startX)

                    Case SignEdge.South
                        Rect.Height = Rect.Height + (e.Y - startY)

                    Case SignEdge.SouthWest
                        Rect.Height = Rect.Height + (e.Y - startY)
                        Rect.X = Rect.X + (e.X - startX)
                        Rect.Width = Rect.Width - (e.X - startX)

                    Case SignEdge.West
                        Rect.X = Rect.X + (e.X - startX)
                        Rect.Width = Rect.Width - (e.X - startX)

                    Case SignEdge.NorthWest
                        Rect.Y = Rect.Y + (e.Y - startY)
                        Rect.Height = Rect.Height - (e.Y - startY)
                        Rect.X = Rect.X + (e.X - startX)
                        Rect.Width = Rect.Width - (e.X - startX)

                End Select
                If Rect.Width < 0 Then
                    Rect.X = Rect.X + Rect.Width
                    Rect.Width = Math.Abs(Rect.Width)
                    Select Case draggingEdge
                        Case SignEdge.NorthEast
                            draggingEdge = SignEdge.NorthWest

                        Case SignEdge.East
                            draggingEdge = SignEdge.West

                        Case SignEdge.SouthEast
                            draggingEdge = SignEdge.SouthWest

                        Case SignEdge.SouthWest
                            draggingEdge = SignEdge.SouthEast

                        Case SignEdge.West
                            draggingEdge = SignEdge.East

                        Case SignEdge.NorthWest
                            draggingEdge = SignEdge.NorthEast

                    End Select
                End If
                If Rect.Height < 0 Then
                    Rect.Y = Rect.Y + Rect.Height
                    Rect.Height = Math.Abs(Rect.Height)
                    Select Case draggingEdge
                        Case SignEdge.North
                            draggingEdge = SignEdge.South

                        Case SignEdge.NorthEast
                            draggingEdge = SignEdge.SouthEast

                        Case SignEdge.SouthEast
                            draggingEdge = SignEdge.NorthEast

                        Case SignEdge.South
                            draggingEdge = SignEdge.North

                        Case SignEdge.SouthWest
                            draggingEdge = SignEdge.NorthWest

                        Case SignEdge.NorthWest
                            draggingEdge = SignEdge.SouthWest
                    End Select
                End If
                updateRectHandles()
                startX = e.X
                startY = e.Y
                sender.Refresh()

            Case Action.Move
                Rect.X = Rect.X + (e.X - startX)
                Rect.Y = Rect.Y + (e.Y - startY)
                updateRectHandles()
                startX = e.X
                startY = e.Y
                sender.Refresh()
        End Select
    End Sub

    Private Sub sourcePictureBox_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles sourcePictureBox.MouseUp
        sourcePictureBox = Nothing
        curAction = Action.None
    End Sub

    Private Sub updateRectHandles()
        Dim halfThreshold As Single = HandleWidth / 2
        RectHandles(0) = New Rectangle(Rect.X + (Rect.Width / 2) - halfThreshold, Rect.Y - halfThreshold, HandleWidth, HandleWidth)
        RectHandles(1) = New Rectangle(Rect.X + Rect.Width - halfThreshold, Rect.Y - halfThreshold, HandleWidth, HandleWidth)
        RectHandles(2) = New Rectangle(Rect.X + Rect.Width - halfThreshold, Rect.Y + (Rect.Height / 2) - halfThreshold, HandleWidth, HandleWidth)
        RectHandles(3) = New Rectangle(Rect.X + Rect.Width - halfThreshold, Rect.Y + Rect.Height - halfThreshold, HandleWidth, HandleWidth)
        RectHandles(4) = New Rectangle(Rect.X + (Rect.Width / 2) - halfThreshold, Rect.Y + Rect.Height - halfThreshold, HandleWidth, HandleWidth)
        RectHandles(5) = New Rectangle(Rect.X - halfThreshold, Rect.Y + Rect.Height - halfThreshold, HandleWidth, HandleWidth)
        RectHandles(6) = New Rectangle(Rect.X - halfThreshold, Rect.Y + (Rect.Height / 2) - halfThreshold, HandleWidth, HandleWidth)
        RectHandles(7) = New Rectangle(Rect.X - halfThreshold, Rect.Y - halfThreshold, HandleWidth, HandleWidth)
    End Sub

    Public Sub ConnectTo(ByVal FromEdge As SignEdge, ByVal ToSign As Sign, ByVal ToEdge As SignEdge)
        If (Not (ToSign Is Nothing)) And (Not (ToSign Is Me)) Then
            If (Not (FromEdge = SignEdge.None)) And (Not (ToEdge = SignEdge.None)) Then
                Dim c As New Connection
                c.ToSign = ToSign
                c.ToEdge = ToEdge
                Connections(FromEdge - 1).Add(c)
            End If
        End If
    End Sub

    <Serializable()> Private Class Connection
        Public ToSign As Sign
        Public ToEdge As SignEdge
    End Class

End Class



' ----------------------------------------------------------------------------
' Class Form1
' ----------------------------------------------------------------------------
Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Binary

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    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.
    Friend WithEvents PictureBox1 As System.Windows.Forms.PictureBox
    Friend WithEvents FontDialog1 As System.Windows.Forms.FontDialog
    Friend WithEvents ColorDialog1 As System.Windows.Forms.ColorDialog
    Friend WithEvents Button1 As System.Windows.Forms.Button
    Friend WithEvents Button2 As System.Windows.Forms.Button
    Friend WithEvents OpenFileDialog1 As System.Windows.Forms.OpenFileDialog
    Friend WithEvents SaveFileDialog1 As System.Windows.Forms.SaveFileDialog
    Friend WithEvents Button3 As System.Windows.Forms.Button
    Friend WithEvents Button4 As System.Windows.Forms.Button
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.PictureBox1 = New System.Windows.Forms.PictureBox
        Me.FontDialog1 = New System.Windows.Forms.FontDialog
        Me.ColorDialog1 = New System.Windows.Forms.ColorDialog
        Me.Button1 = New System.Windows.Forms.Button
        Me.Button2 = New System.Windows.Forms.Button
        Me.OpenFileDialog1 = New System.Windows.Forms.OpenFileDialog
        Me.SaveFileDialog1 = New System.Windows.Forms.SaveFileDialog
        Me.Button3 = New System.Windows.Forms.Button
        Me.Button4 = New System.Windows.Forms.Button
        Me.SuspendLayout()
        '
        'PictureBox1
        '
        Me.PictureBox1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) _
                    Or System.Windows.Forms.AnchorStyles.Left) _
                    Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.PictureBox1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.PictureBox1.Location = New System.Drawing.Point(8, 40)
        Me.PictureBox1.Name = "PictureBox1"
        Me.PictureBox1.Size = New System.Drawing.Size(616, 336)
        Me.PictureBox1.TabIndex = 0
        Me.PictureBox1.TabStop = False
        '
        'Button1
        '
        Me.Button1.Location = New System.Drawing.Point(8, 8)
        Me.Button1.Name = "Button1"
        Me.Button1.Size = New System.Drawing.Size(112, 24)
        Me.Button1.TabIndex = 1
        Me.Button1.Text = "Load Layout"
        '
        'Button2
        '
        Me.Button2.Location = New System.Drawing.Point(128, 8)
        Me.Button2.Name = "Button2"
        Me.Button2.Size = New System.Drawing.Size(112, 24)
        Me.Button2.TabIndex = 2
        Me.Button2.Text = "Save Layout"
        '
        'Button3
        '
        Me.Button3.Location = New System.Drawing.Point(248, 8)
        Me.Button3.Name = "Button3"
        Me.Button3.Size = New System.Drawing.Size(112, 24)
        Me.Button3.TabIndex = 3
        Me.Button3.Text = "Delete Sign"
        '
        'Button4
        '
        Me.Button4.Location = New System.Drawing.Point(368, 8)
        Me.Button4.Name = "Button4"
        Me.Button4.Size = New System.Drawing.Size(112, 24)
        Me.Button4.TabIndex = 5
        Me.Button4.Text = "Connect"
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(8, 19)
        Me.ClientSize = New System.Drawing.Size(632, 382)
        Me.Controls.Add(Me.Button4)
        Me.Controls.Add(Me.Button3)
        Me.Controls.Add(Me.Button2)
        Me.Controls.Add(Me.Button1)
        Me.Controls.Add(Me.PictureBox1)
        Me.Font = New System.Drawing.Font("Microsoft Sans Serif", 12.0!, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CType(0, Byte))
        Me.Name = "Form1"
        Me.Text = "RubberBanding Connectable Boxes in a PictureBox"
        Me.ResumeLayout(False)

    End Sub

#End Region

    Private Enum Action
        None = 0
        Creating = 1
        Sizing = 2
        Moving = 3
        Deleting = 4
        Connecting = 5
    End Enum

    Private startX As Integer
    Private startY As Integer
    Private lastX As Integer
    Private lastY As Integer
    Private firstBoxDrawn As Boolean = False
    Private Signs As New ArrayList
    Private curAction As Action = Action.None
    Private s As Sign
    Private se As Sign.SignEdge
    Private curSign As Sign
    Private selSign As Sign
    Private firstPoint As Boolean
    Private sourceSign As Sign
    Private sourceEdge As Sign.SignEdge
    Private targetSign As Sign
    Private targetEdge As Sign.SignEdge

    Private Sub PictureBox1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
        If e.Button = MouseButtons.Left Then
            If curAction = Action.None Then
                Dim p As Point = PictureBox1.PointToScreen(New Point(e.X, e.Y))
                startX = p.X
                startY = p.Y
                If curSign Is Nothing Then
                    If Not (selSign Is Nothing) Then
                        selSign.showHandles = False
                        selSign = Nothing
                        PictureBox1.Refresh()
                    End If
                ElseIf Not (curSign Is selSign) Then
                    If Not (selSign Is Nothing) Then
                        selSign.showHandles = False
                    End If
                    selSign = curSign
                    selSign.showHandles = True
                    PictureBox1.Refresh()
                End If
            ElseIf curAction = Action.Deleting Then
                If Not (curSign Is Nothing) Then
                    Signs.Remove(curSign)
                    PictureBox1.Refresh()
                End If
                Button3.Enabled = True
                curAction = Action.None
            ElseIf curAction = Action.Connecting Then
                If Not (se = Sign.SignEdge.None) Then
                    If Not firstPoint Then
                        sourceSign = curSign
                        sourceEdge = se
                        firstPoint = True
                    ElseIf Not (curSign Is sourceSign) Then
                        targetSign = curSign
                        targetEdge = se
                        sourceSign.ConnectTo(sourceEdge, targetSign, targetEdge)
                        curAction = Action.None
                        Button4.Enabled = True
                        PictureBox1.Refresh()
                    End If
                End If
            End If
        End If
    End Sub

    Private Sub PictureBox1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
        Dim p As Point
        If e.Button = MouseButtons.Left Then
            Select Case curAction
                Case Action.None
                    Cursor.Clip = sender.RectangleToScreen(New Rectangle(0, 0, sender.Width, sender.Height))
                    If Not (s Is Nothing) Then
                        If se = Sign.SignEdge.None Then
                            curAction = Action.Moving
                            s.dragSign(sender, e.X, e.Y)
                        Else
                            curAction = Action.Sizing
                            s.dragEdge(sender, se, e.X, e.Y)
                        End If
                    Else
                        curAction = Action.Creating
                        firstBoxDrawn = False
                        createSign(sender, e)
                    End If

                Case Action.Creating
                    createSign(sender, e)

            End Select
        ElseIf curAction = Action.None Or _
                curAction = Action.Deleting Or _
                curAction = Action.Connecting Then
            HighlightSign(sender, e)
            If curAction = Action.Connecting And firstPoint Then
                PictureBox1.Refresh()
                Dim g As Graphics = PictureBox1.CreateGraphics
                g.DrawLine(Pens.Black, sourceSign.getHandleCoord(sourceEdge), New Point(e.X, e.Y))
                g.Dispose()
            End If
        End If
    End Sub

    Private Sub HighlightSign(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        overSign(sender, e)
        If s Is Nothing Then
            If Not (curSign Is Nothing) Then
                curSign.Highlighted = False
                curSign.ConnectionCandidate = False
                curSign = Nothing
                sender.Refresh()
            End If
        Else
            If curSign Is Nothing Then
                curSign = s
                If curAction = Action.Connecting Then
                    curSign.ConnectionCandidate = True
                Else
                    curSign.Highlighted = True
                End If
                sender.Refresh()
            ElseIf Not (curSign Is s) Then
                curSign.Highlighted = False
                curSign.ConnectionCandidate = False
                curSign = s
                If curAction = Action.Connecting Then
                    curSign.ConnectionCandidate = True
                Else
                    curSign.Highlighted = True
                End If
                sender.Refresh()
            End If
        End If
    End Sub

    Private Sub overSign(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        s = Nothing
        se = Sign.SignEdge.None

        For Each s In Signs
            If s.signAction = Sign.Action.None Then
                se = s.isOverEdge(e.X, e.Y)
                If se <> Sign.SignEdge.None Then
                    If curAction = Action.Connecting Then
                        If s Is sourceSign Then
                            s = Nothing
                            se = Sign.SignEdge.None
                            sender.Cursor.Current = Cursors.Default
                        Else
                            sender.Cursor.Current = Cursors.Cross
                        End If
                        Exit Sub
                    ElseIf curAction = Action.Deleting Then
                        sender.Cursor.Current = Cursors.Cross
                        Exit Sub
                    ElseIf curAction = Action.None Then
                        If s.showHandles Then
                            Select Case se
                                Case Sign.SignEdge.North, Sign.SignEdge.South
                                    sender.Cursor.Current = Cursors.SizeNS

                                Case Sign.SignEdge.NorthEast, Sign.SignEdge.SouthWest
                                    sender.Cursor.Current = Cursors.SizeNESW

                                Case Sign.SignEdge.East, Sign.SignEdge.West
                                    sender.Cursor.Current = Cursors.SizeWE

                                Case Sign.SignEdge.SouthEast, Sign.SignEdge.NorthWest
                                    sender.Cursor.Current = Cursors.SizeNWSE

                            End Select
                            Exit Sub
                        Else
                            se = Sign.SignEdge.None
                        End If
                    End If
                End If
            End If
        Next

        For Each s In Signs
            If s.signAction = Sign.Action.None And s.isOverSign(e.X, e.Y) Then
                If (Not (selSign Is Nothing)) AndAlso (Not (s Is selSign)) Then
                    If selSign.isOverSign(e.X, e.Y) Then
                        s = selSign
                    End If
                End If
                If curAction = Action.Deleting Then
                    sender.Cursor.Current = Cursors.Cross
                ElseIf curAction = Action.Connecting Then
                    If s Is sourceSign Then
                        s = Nothing
                        se = Sign.SignEdge.None
                        sender.Cursor.Current = Cursors.Default
                    Else
                        sender.Cursor.Current = Cursors.Cross
                    End If
                ElseIf curAction = Action.None Then
                    sender.Cursor.Current = Cursors.SizeAll
                End If
                Exit Sub
            End If
        Next

        s = Nothing
        se = Sign.SignEdge.None
        sender.Cursor.Current = Cursors.Default
    End Sub

    Private Sub createSign(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs)
        Dim p As Point = sender.PointToScreen(New Point(e.X, e.Y))
        If Not firstBoxDrawn Then
            firstBoxDrawn = True
            ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, p.X - startX, p.Y - startY), Color.Black, FrameStyle.Dashed)
        Else
            ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, lastX - startX, lastY - startY), Color.Black, FrameStyle.Dashed)
            ControlPaint.DrawReversibleFrame(New Rectangle(startX, startY, p.X - startX, p.Y - startY), Color.Black, FrameStyle.Dashed)
        End If
        lastX = p.X
        lastY = p.Y
    End Sub

    Private Sub PictureBox1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
        If e.Button = MouseButtons.Left Then
            If Not (curAction = Action.Connecting) Then
                Cursor.Clip = New Rectangle(0, 0, Screen.GetBounds(New Point(0, 0)).Width, Screen.GetBounds(New Point(0, 0)).Height)
                If curAction = Action.Creating Then
                    If firstBoxDrawn Then
                        Dim r As Rectangle = New Rectangle(Math.Min(startX, lastX), Math.Min(startY, lastY), Math.Abs(lastX - startX), Math.Abs(lastY - startY))
                        ControlPaint.DrawReversibleFrame(r, Color.Black, FrameStyle.Dashed)
                        r = PictureBox1.RectangleToClient(r)
                        Dim s As New Sign(r)
                        s.Text = "New Sign" & vbCrLf & vbCrLf & Now().ToString
                        s.showHandles = True
                        s.Highlighted = True
                        Signs.Add(s)
                        selSign = s
                        sender.Refresh()
                    End If
                End If
                curAction = Action.None
                PictureBox1.Cursor.Show()
            End If
        End If
    End Sub

    Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
        Dim s As Sign
        For Each s In Signs
            If Not (s Is selSign) Then
                s.Paint(sender, e)
            End If
        Next
        If Not (selSign Is Nothing) Then
            selSign.Paint(sender, e)
        End If
    End Sub

    Private Sub PictureBox1_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles PictureBox1.DoubleClick
        Dim s As Sign
        Dim p As Point
        For Each s In Signs
            p = PictureBox1.PointToClient(Cursor.Position)
            If s.isOverSign(p.X, p.Y) Then
                If Not (selSign Is Nothing) Then
                    If selSign.isOverSign(p.X, p.Y) Then
                        s = selSign
                    End If
                End If

                Dim tb As New TextBox
                tb.BorderStyle = BorderStyle.None
                tb.BackColor = PictureBox1.BackColor
                tb.ForeColor = s.TextColor
                tb.Multiline = True
                Dim sLoc As Point = Me.PointToClient(PictureBox1.PointToScreen(s.signLocation))
                Dim sSize As Size = s.signSize
                sLoc.X = sLoc.X + s.HandleWidth + 2
                sLoc.Y = sLoc.Y + s.HandleWidth
                sSize.Width = sSize.Width - (2 * s.HandleWidth)
                sSize.Height = sSize.Height - (2 * s.HandleWidth)
                tb.Location = sLoc
                tb.Size = sSize
                tb.Text = s.Text
                If s.TextFont Is Nothing Then
                    tb.Font = PictureBox1.Font
                Else
                    tb.Font = s.TextFont
                End If
                tb.Tag = s

                AddHandler tb.KeyPress, AddressOf Me.tb_KeyPress
                AddHandler tb.KeyDown, AddressOf Me.tb_KeyDown
                Me.Controls.Add(tb)
                tb.Visible = True
                tb.BringToFront()
                tb.Focus()
                tb.SelectionStart = tb.Text.Length
                s.signAction = Sign.Action.Editing
                PictureBox1.Refresh()
                Exit Sub
            End If
        Next
    End Sub

    Private Sub tb_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs)
        If Asc(e.KeyChar) = 27 Then ' Escape
            sender.tag.text = sender.text
            sender.tag.signaction = Sign.Action.None
            Me.Controls.Remove(sender)
            PictureBox1.Refresh()
        End If
    End Sub

    Private Sub tb_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs)
        If e.KeyCode = Keys.F9 Then
            If FontDialog1.ShowDialog = DialogResult.OK Then
                sender.Tag.TextFont = FontDialog1.Font
                sender.Font = FontDialog1.Font
            End If
        ElseIf e.KeyCode = Keys.F10 Then
            If ColorDialog1.ShowDialog = DialogResult.OK Then
                sender.Tag.TextColor = ColorDialog1.Color
                sender.ForeColor = ColorDialog1.Color
            End If
        End If
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        OpenFileDialog1.Title = "Open a Previously Saved Layout"
        OpenFileDialog1.Filter = "Sign Layout Files (*.sly)|*.sly|All files (*.*)|*.*"
        If OpenFileDialog1.ShowDialog = DialogResult.OK Then
            Dim fs As New FileStream(OpenFileDialog1.FileName, FileMode.OpenOrCreate)
            Dim formatter As New BinaryFormatter
            Try
                Signs = DirectCast(formatter.Deserialize(fs), ArrayList)
                PictureBox1.Refresh()
            Catch x As SerializationException
                MsgBox("Failed to Deserialize. Reason: " & x.Message)
                Throw
            Finally
                fs.Close()
                MsgBox(OpenFileDialog1.FileName, MsgBoxStyle.Information, "Sign Layout Loaded")
            End Try
        End If
    End Sub

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        SaveFileDialog1.Title = "Save Sign Layout to a File"
        SaveFileDialog1.Filter = "Sign Layout Files (*.sly)|*.sly|All files (*.*)|*.*"
        If SaveFileDialog1.ShowDialog = DialogResult.OK Then
            Dim fs As New FileStream(SaveFileDialog1.FileName, FileMode.Create)
            Dim formatter As New BinaryFormatter
            Try
                formatter.Serialize(fs, Signs)
            Catch x As SerializationException
                MsgBox("Failed to serialize. Reason: " & x.Message)
                Throw
            Finally
                fs.Close()
                MsgBox(SaveFileDialog1.FileName, MsgBoxStyle.Information, "Sign Layout Saved")
            End Try
        End If
    End Sub

    Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
        Button3.Enabled = False
        curAction = Action.Deleting
    End Sub

    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        Button4.Enabled = False
        If Not (selSign Is Nothing) Then
            selSign.showHandles = False
            selSign = Nothing
            PictureBox1.Refresh()
        End If
        sourceSign = Nothing
        sourceEdge = Sign.SignEdge.None
        targetSign = Nothing
        targetEdge = Sign.SignEdge.None
        firstPoint = False
        curAction = Action.Connecting
    End Sub

End Class
0
 
LVL 6

Author Comment

by:cjinsocal581
ID: 13698486
Perfect! Thanks a million!!

Thanks for all the insight and help on this to you both. And glad to hear you enjoyed my neck of the woods.

Cheers,
Chris
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

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

I think the Typed DataTable and Typed DataSet are very good options when working with data, but I don't like auto-generated code. First, I create an Abstract Class for my DataTables Common Code.  This class Inherits from DataTable. Also, it can …
A while ago, I was working on a Windows Forms application and I needed a special label control with reflection (glass) effect to show some titles in a stylish way. I've always enjoyed working with graphics, but it's never too clever to re-invent …
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
In this video, Percona Solution Engineer Dimitri Vanoverbeke discusses why you want to use at least three nodes in a database cluster. To discuss how Percona Consulting can help with your design and architecture needs for your database and infras…
Suggested Courses

705 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