Picturebox objects
Picturebox objects
Picturebox objects
Picturebox objects
Picturebox objects
Picturebox objects Picturebox objects Picturebox objects Picturebox objects Picturebox objects Picturebox objects Picturebox objects Picturebox objects
Picturebox objects Picturebox objects
Picturebox objects
Go Back  Xtreme Visual Basic Talk > > > Picturebox objects


Reply
 
Thread Tools Display Modes
  #1  
Old 10-03-2012, 08:41 AM
supercrewed supercrewed is offline
Centurion
 
Join Date: Feb 2004
Posts: 152
Default Picturebox objects


Is it possible to have the object in a picturebox as selectable items, ie; Lines, ellippes, and so on? So that when you click on the object i could display information about the object.
Reply With Quote
  #2  
Old 10-03-2012, 10:24 AM
AtmaWeapon's Avatar
AtmaWeaponPicturebox objects AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

Well, it kind of depends on what you mean by "object" and whether you really need to use a PictureBox, but I think I can make some safe assumptions.

If you're parenting controls into the PictureBox (which is a thing, but has to be done in code instead of the designer), the question makes no sense because you can use plain old events. Which is why I'm guessing this isn't the case.

So I'm assuming that means you're using a Paint event to draw things in a PictureBox. I could also assume you're drawing onto an image the PictureBox is displaying; that's similar. Or maybe you're using CreateGraphics(); if that's true, you probably shouldn't. I'm going to use "Paint event in a PictureBox" and let someone call me a hypocrite since I usually say "Ahhhhh why are you using a PictureBox???" In my opinion, it's easier to do this if you make your own control and separate classes. In my experience, people get scared when my examples do that. I'm going to write it the quick way, and if you're interested in what I consider the professional way, feel free to ask. I'd love to do it.

If you're drawing things, you already have some information on hand:
  • What the shape of the thing is.
  • What data is associated with the thing.
  • Where the thing is drawn.
That's what you need to know to make "clickable" shapes. In the control that contains the items, you need to handle mouse events and check if the mouse is "inside" a shape. If so, you do what is needed.

I've attached an example with some clickable shapes in a picturebox. Have a look at it and the comments and see if it makes things clear.
Attached Files
File Type: zip PictureBoxWithClickableObjects.zip (66.8 KB, 27 views)
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #3  
Old 10-03-2012, 02:05 PM
supercrewed supercrewed is offline
Centurion
 
Join Date: Feb 2004
Posts: 152
Default

Thank you, what I'm trying to do is to make a program, for our company to generate G code programs, but on this particular one, I need to include some graphics since it will be the most complex I've made. Without getting long winded, the operator inputs data, as he, or she does, the part is coming to life, in the graphics window, similar to a CAD program, but not as complex. Now let's say they want to check the dimensional characteristics about one of the objects in the graphics window, and then it would be provided for them. Such as; the size of the hole, X, Y coordinates, and so on. What is the best way to accomplish this?
Reply With Quote
  #4  
Old 10-03-2012, 02:24 PM
passel's Avatar
passelPicturebox objects passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 8,028
Default

Have you looked at AtmaWeapon's code yet?
I've just opened up the forum, been busy, so haven't yet, but I suspect it has to be a reasonable example.

Unfortunately, unless you go with some third party tool, and I'm not aware of one since I haven't looked, there is not magic here. You are drawing things, so you will need to keep track of where they are, and be able to take a position, usually a click from the mouse, and convert and compare that position against your objects in some manner.

I have confidence that what AtmaWeapon has given you should point you down that path. I would think that you should work to understand what that example is doing, and if you don't think it will help you with your objective, then ask specific questions.
There is often not a best way to accomplish a given task, but a myriad of ways, and you have to choose. The "best" choice for a given person, is usually the one they can understand the best.
See if you can build on understanding what AtmaWeapon has done.
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.
Reply With Quote
  #5  
Old 10-03-2012, 02:31 PM
supercrewed supercrewed is offline
Centurion
 
Join Date: Feb 2004
Posts: 152
Default

Yes, but i will have to dig into it some more later, when i get home from work.
Reply With Quote
  #6  
Old 10-03-2012, 02:38 PM
supercrewed supercrewed is offline
Centurion
 
Join Date: Feb 2004
Posts: 152
Default

Ok, I took the time to look at it, even at work, and it is pretty slick, more than likely I can put this to work, as for the other data, I'd like to display, that should easy, Thanks again
Reply With Quote
  #7  
Old 10-03-2012, 07:34 PM
hDC_0Picturebox objects hDC_0 is offline
Contributor

* Expert *
 
Join Date: Feb 2004
Posts: 560
Default Pixel perfect hit testing on matrix adjusted shapes using .IsVisible

I looked at AW's example and the use of "List(Of" structures is very clever,
but I noticed these comment lines above the Picturebox1_Click event:
Quote:
' Here's where we decide if the user clicked on a shape. It's not super accurate
' for the ellipse, but making it pixel-perfect is a much more complicated prospect.
Would it really be that "much more" complicated?

For instance if you performed hit testing with .IsVisible against a GraphicsPath?
Perform Hit Testing with Shapes

As noted in this StackOverFlow thread this method can even be made to work with Matrix adjusted (translated, rotated, scaled) shapes using the
Matrix.TransformPoints method (instead of the Matrix.TransformVectors method which lacks translation).

For complex shapes, graphics paths can be converted to regions and combined (using Region.Union) and hit tested against using Region.IsVisible.
Region: Union code example

Of course for best performance it is still reasonable to do a basic bounding rectangle test first and then nest the .IsVisible test(s) inside the loop.
Reply With Quote
  #8  
Old 10-03-2012, 10:52 PM
AtmaWeapon's Avatar
AtmaWeaponPicturebox objects AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

Eh, for the purposes of "I only have 30 minutes to make this example, yes." My version did what it needed to do in one line of hit testing so as not to make the example bigger and to stick to primitives where possible. I left the asterisk that I knew it was terrible in there for people like you
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #9  
Old 10-04-2012, 12:04 AM
passel's Avatar
passelPicturebox objects passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 8,028
Default

Since AtmaWeapon already did the "bulk" of the work, I've modified his example to use a class, as he mentioned (perhaps not exactly the way he would have used a class), and to use a GraphicsPath for drawing and hit testing as hDC_0 mentioned, so you would have a "simple" example of those two things.
Using a GraphicsPath, rather than the Rectangle structure that AtmaWeapon used, has to use more memory, and maybe other resources, but the tradeoff is a bit simpler code in the drawing since you don't have to select what type of drawing to do based on "Data" because what you're drawing is already captured in the GraphicsPath.
And Hit Testing is also more accurate since it will conform to the path (i.e. the shape).
I don't know if you can count on the program exiting to clean up all the resources the GraphicsPath used, so extra code also has to be added to dispose of those objects when the form closes.

The other thing done, was to do the hit testing in the reverse order of the way the objects were drawn. That way, if you have overlapping items, the "topmost" item is "selected".
I've changed the coordinates, so that the rectangle overlaps the ellipse. If we didn't do the hit test "top to bottom", the area where the rectangle and ellipse overlap would report the ellipse clicked on, not the rectangle.
Code:
Imports System.Drawing.Drawing2D 'to get GraphicsPath

Public Class Form1

  Private Class shapeType
    Public Color As Color
    Public Data As String
    Public Path As GraphicsPath
  End Class

  ' Every shape has a rectangle that represents its bounds, a color, and a string
  ' for some descriptive data. Ideally you would make a class to represent a shape.
  ' Or a structure. There are a number of differences as to why you may choose one or the other.
  ' But, I would suggest reading up on the differences, not going to explain them all here.

  Private _shape As New List(Of shapeType)

  Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    For i As Integer = 0 To _shape.Count - 1
      _shape(i).Path.Dispose()   'release the resource the GraphicsPaths used
    Next
  End Sub

  Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Dim shape As New shapeType  'Create an instance of the shapeType class

    shape.Color = Color.Blue
    shape.Data = "ellipse"
    shape.Path = New GraphicsPath
    shape.Path.AddEllipse(New Rectangle(10, 10, 20, 30))
    _shape.Add(shape)  'added this instance reference to the list

    shape = New shapeType     'Need another instance since the current is already added to the list

    shape.Color = Color.Yellow
    shape.Data = "rectangle"
    shape.Path = New GraphicsPath
    shape.Path.AddRectangle(New Rectangle(20, 20, 30, 20))
    _shape.Add(shape)        'add this instance reference to the list

  End Sub

  ' Draws the shapes in the picturebox; 
  ' The only "magic" here is since the path already defines what we are drawing, ellipse or rectangle
  ' it is just a single FillPath command, rather than a series of conditions based on the shape.
  ' I'm sure there is more storage required for the GraphicsPath compared to just the rectangle, but
  ' the tradeoff is simpler code here and easier hit testing later, especially if things overlap.

  Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
    Dim g As Graphics = e.Graphics

    For i As Integer = 0 To _shape.Count - 1
      Using b As New SolidBrush(_shape(i).Color)
        g.FillPath(b, _shape(i).Path)
      End Using
    Next
  End Sub

  ' Here's where we decide if the user clicked on a shape. 
  'The graphics path will return true for all points inside the path.
  'So, even though the IsVisible would make you think if the path was "underneath" another object
  'it wouldn't be visible so should return false, that is not true.
  'The IsVisible really means WouldBeFilled, and depending on fill mode, and complexity of the shape, the path may have
  'holes in it, (areas not filled), so IsVisible would be False in those holes.

  'Since we're drawing simple shapes, there are no holes, and because the rectangle overlaps the ellipse, the ellipse
  'Would return True for IsVisible, even for the part "under" the rectangle.
  'So, hit testing would normally be in the reverse order to the order drawn, so the "upper" objects are hit tested first.

  Private Sub PictureBox1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles PictureBox1.Click
    ' First, get where the mouse is. This is relative to the top-left corner of the
    ' monitor; "screen coordinates".
    Dim clickPosScreen As Point = Cursor.Position

    ' Our shapes are relative to the top left corner of the PictureBox; "client coordinates".
    ' The PointToClient() method converts from screen coordinates to client coordinates.
    Dim clickPosClient As Point = PictureBox1.PointToClient(clickPosScreen)

    ' Now decide if the click is "inside" any of the shapes. If so, put the data in the
    ' text box.
    For i As Integer = _shape.Count - 1 To 0 Step -1  'Note we're doing hit test in reverse order, last drawn, first tested
      If _shape(i).Path.IsVisible(clickPosClient) Then
        TextBox1.Text = String.Format("You clicked the {0}.", _shape(i).Data)
        Return
      End If
    Next

    ' If no shapes were clicked, clear the text box.
    TextBox1.Clear()
  End Sub
End Class
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 10-04-2012 at 12:11 AM.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
Picturebox objects
Picturebox objects
Picturebox objects Picturebox objects
Picturebox objects
Picturebox objects
Picturebox objects Picturebox objects Picturebox objects Picturebox objects Picturebox objects Picturebox objects Picturebox objects
Picturebox objects
Picturebox objects
 
Picturebox objects
Picturebox objects
 
-->