-
Apr 26th, 2013, 01:45 PM
#1
Thread Starter
Addicted Member
[RESOLVED] Some Graphics Help: Highlighting / Clickable Objects
As some of you might notice, I have been playing around with graphics a lot lately and unfortunately have run into some more problems/road blocks
That is an example of one of my graphic.
I am looking for a way to make each line clickable if possible, so when a user click on the line something will pop-up with information. It would also be nice if I could highlight that line :P
I found this lovely code at ---> http://social.msdn.microsoft.com/For...5-2e344389a6d8
Code:
Imports System.Drawing.Drawing2D
Public Class Form1
'the pictureWithPaths
Private pathBitmap As PathBitmap = Nothing
'the control to draw on
Private WithEvents panel1 As New Panel
Private Sub Form1_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
'cleanup
If Not pathBitmap Is Nothing Then
pathBitmap.Dispose()
End If
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
'intialize the panel and add it to the forms control collection
panel1.ClientSize = Me.ClientSize
Me.Controls.Add(panel1)
pathBitmap = New PathBitmap
'get a bitmap of desired size and just fill in one color for testing here
pathBitmap.Bmp = New Bitmap(panel1.ClientSize.Width, panel1.ClientSize.Height)
Using g As Graphics = Graphics.FromImage(pathBitmap.Bmp)
'draw the contents
g.SmoothingMode = SmoothingMode.AntiAlias
g.Clear(Color.Red)
g.FillEllipse(Brushes.Blue, New Rectangle(New Point(0, 0), pathBitmap.Bmp.Size))
'add the NamedPaths (GraphicsPaths and the names for the paths)
Dim gP1 As New GraphicsPath
gP1.FillMode = FillMode.Alternate
gP1.AddRectangle(New Rectangle(New Point(0, 0), pathBitmap.Bmp.Size))
gP1.AddEllipse(New Rectangle(New Point(0, 0), pathBitmap.Bmp.Size))
Dim p1 As New NamedPath() With {.Name = "RectWithoutEllipse", .Path = gP1}
pathBitmap.Add(p1)
Dim gP2 As New GraphicsPath
gP2.AddEllipse(New Rectangle(New Point(0, 0), pathBitmap.Bmp.Size))
Dim p2 As New NamedPath() With {.Name = "Ellipse", .Path = gP2}
pathBitmap.Add(p2)
End Using
End Sub
Private Sub panel1_MouseClick(sender As Object, e As MouseEventArgs) Handles panel1.MouseClick
'test the three Hittest methods
MessageBox.Show(pathBitmap.HitTest(e.X, e.Y).Name)
MessageBox.Show(pathBitmap.HitTest("Ellipse", e.X, e.Y).ToString)
If Not pathBitmap.PathList Is Nothing AndAlso pathBitmap.PathList.Count > 0 Then
MessageBox.Show(pathBitmap.HitTest(pathBitmap.PathList(0), e.X, e.Y).ToString)
End If
End Sub
Private Sub panel1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles panel1.Paint
'draw the picture
If Not pathBitmap Is Nothing AndAlso Not pathBitmap.Bmp Is Nothing Then
e.Graphics.DrawImageUnscaled(pathBitmap.Bmp, 0, 0)
End If
End Sub
End Class
Public Class PathBitmap
Implements IDisposable
Public Property Bmp As Bitmap
Public Property PathList As List(Of NamedPath)
Sub Add(gP As NamedPath)
If PathList Is Nothing Then
PathList = New List(Of NamedPath)
End If
PathList.Add(gP)
End Sub
Public Function HitTest(x As Single, y As Single) As NamedPath
If PathList Is Nothing Then
PathList = New List(Of NamedPath)
End If
For Each gP As NamedPath In PathList
If gP.IsVisible(x, y) Then
Return gP
End If
Next
Return Nothing
End Function
Public Function HitTest(gP As NamedPath, x As Single, y As Single) As Boolean
If PathList Is Nothing Then
PathList = New List(Of NamedPath)
End If
If gP.IsVisible(x, y) Then
Return True
End If
Return False
End Function
Public Function HitTest(name As String, x As Single, y As Single) As Boolean
If PathList Is Nothing Then
PathList = New List(Of NamedPath)
End If
For Each gP As NamedPath In PathList
If gP.Name = name AndAlso gP.IsVisible(x, y) Then
Return True
End If
Next
Return False
End Function
#Region "IDisposable Support"
Private disposedValue As Boolean
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
If Not PathList Is Nothing Then
For i As Integer = PathList.Count - 1 To 0 Step -1
PathList(i).Dispose()
Next
PathList.Clear()
End If
End If
End If
Me.disposedValue = True
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
Public Class NamedPath
Implements IDisposable
Public Property Path As GraphicsPath
Public Property Name As String
Public Function IsVisible(x As Single, y As Single)
If Not Path Is Nothing Then
Return Path.IsVisible(x, y)
End If
Return False
End Function
#Region "IDisposable Support"
Private disposedValue As Boolean
Protected Overridable Sub Dispose(disposing As Boolean)
If Not Me.disposedValue Then
If disposing Then
If Not Path Is Nothing Then
Path.Dispose()
End If
End If
End If
Me.disposedValue = True
End Sub
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
#End Region
End Class
It is truly awesome and helped me a lot. It allows you assign a path to everything you draw and then allow you to check that path in a mouse click or move event.
I managed to get it to work for rectangles but for whatever reason it wont work with my lines, if you guys have the time, you can copy and paste the code above and give it a try by adding a line as well.
-
Apr 26th, 2013, 01:50 PM
#2
Re: Some Graphics Help: Highlighting / Clickable Objects
I managed to get it to work for rectangles
You do realise that a line is just a long, thin rectangle, right?
As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"
Reviews: "dunfiddlin likes his DataTables" - jmcilhinney
Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!
-
Apr 26th, 2013, 02:02 PM
#3
Thread Starter
Addicted Member
Re: Some Graphics Help: Highlighting / Clickable Objects
Originally Posted by dunfiddlin
You do realise that a line is just a long, thin rectangle, right?
I understand that but I would prefer to use lines, instead of long thing rectangles, especially since I will be drawing a lot of them. It will just making everything easier in the end, espically for someone who gets the code later.
But I will probably end up going with thin rectangles since it works right now
-
Apr 26th, 2013, 02:13 PM
#4
Re: Some Graphics Help: Highlighting / Clickable Objects
The point is that the logic which underpins this is based on bitmaps and bitmaps are always rectangles. Even if you draw lines rather than rectangles you still have to assign the line to a rectangle in the end. There is no way to make it 'work with lines' other than to convert the lines into rectangles!
As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"
Reviews: "dunfiddlin likes his DataTables" - jmcilhinney
Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!
-
Apr 26th, 2013, 02:34 PM
#5
Thread Starter
Addicted Member
Re: Some Graphics Help: Highlighting / Clickable Objects
Originally Posted by dunfiddlin
The point is that the logic which underpins this is based on bitmaps and bitmaps are always rectangles. Even if you draw lines rather than rectangles you still have to assign the line to a rectangle in the end. There is no way to make it 'work with lines' other than to convert the lines into rectangles!
Fair enough, I did not know it worked like that. Thanks!
This is going to be fun :P
Edit: It wont let me +1 you, you have answered to many of my questions xD
-
Apr 26th, 2013, 03:10 PM
#6
Thread Starter
Addicted Member
Re: Some Graphics Help: Highlighting / Clickable Objects
I cannot seem to get he logic down for how this is going to work, I have my co-ordinates from point to point.
Code:
If y_loc(k) = y_loc(k + 1) And x_loc(k) = x_loc(k + 1) Then
Continue For
End If
If y_loc(k) = y_loc(k + 1) Then
g.FillRectangle(Brushes.HotPink, x_loc(k), y_loc(k), x_loc(k) - x_loc(k + 1), 2)
ElseIf x_loc(k) = x_loc(k + 1) Then
g.FillRectangle(Brushes.HotPink, x_loc(k), y_loc(k), 2, y_loc(k) - y_loc(k + 1))
End If
This made sense in my head. If the current y-position is the same as the next one then the width of the triangle will be the difference of the x points.
I will use this data set:
From: X - 384 Y - 220 To: X - 384 Y - 196
From: X - 384 Y - 196 To: X - 384 Y - 196
From: X - 384 Y - 196 To: X - 389 Y - 196
From: X - 389 Y - 196 To: X - 394 Y - 196
From: X - 394 Y - 196 To: X - 394 Y - 347
From: X - 394 Y - 347 To: X - 389 Y - 347
From: X - 389 Y - 347 To: X - 331 Y - 347
From: X - 331 Y - 347 To: X - 331 Y - 347
From: X - 331 Y - 347 To: X - 331 Y - 359
Since the first point, the X's are the same, my starting point will be 384,220 and the rectangle will be 24 units tall(220-196). But the lines are all over the place for some reason.
-
Apr 27th, 2013, 10:07 AM
#7
Re: Some Graphics Help: Highlighting / Clickable Objects
vb.net Code:
Function GetLineRect(ByVal x1 As Integer, ByVal y1 As Integer, ByVal x2 As Integer, ByVal y2 As Integer, ByVal LineWidth As Integer) As Rectangle
If x1 = x2 Then
If y1 < y2 Then
Return New Rectangle(x1, y1, LineWidth, y2 - y1)
Else
Return New Rectangle(x1, y2, LineWidth, y1 - y2)
End If
ElseIf y1 = y2 Then
If x1 < x2 Then
Return New Rectangle(x1, y1, x2 - x1, LineWidth)
Else
Return New Rectangle(x2, y1, x1 - x2, LineWidth)
End If
End If
End Function
Example:
vb.net Code:
e.Graphics.FillRectangle(Brushes.DarkRed, GetLineRect(10, 20, 10, 70, 2))
As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"
Reviews: "dunfiddlin likes his DataTables" - jmcilhinney
Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!
-
Apr 29th, 2013, 10:23 AM
#8
Thread Starter
Addicted Member
Re: Some Graphics Help: Highlighting / Clickable Objects
Originally Posted by dunfiddlin
vb.net Code:
Function GetLineRect(ByVal x1 As Integer, ByVal y1 As Integer, ByVal x2 As Integer, ByVal y2 As Integer, ByVal LineWidth As Integer) As Rectangle If x1 = x2 Then If y1 < y2 Then Return New Rectangle(x1, y1, LineWidth, y2 - y1) Else Return New Rectangle(x1, y2, LineWidth, y1 - y2) End If ElseIf y1 = y2 Then If x1 < x2 Then Return New Rectangle(x1, y1, x2 - x1, LineWidth) Else Return New Rectangle(x2, y1, x1 - x2, LineWidth) End If End If End Function
Example:
vb.net Code:
e.Graphics.FillRectangle(Brushes.DarkRed, GetLineRect(10, 20, 10, 70, 2))
Thank you very much, forgot to think about the < and >.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|