Solved

# Extending Rectangle Structure

Posted on 2006-06-06
282 Views
I am not sure that even the title of this message is valid but I'll ask this newbie question anyway. I want to create a version of a Rectangle that contains an index so that when they are clicked on (detected via hittest), I can get the index for the selected rectangle. I would set the index as I draw them of course. I am confused as to whether Rectangle is a structure or a structure and a class. I have seen a reference in the help file that says the constructor creates a new instance of this class yet Rectangle does not show up in Intillsense. I have scoured the web and cannot figure this out though I know it has to be simple. Your help is appreciated as I learn.
0

LVL 2

Expert Comment

Rectangle for having a hit test should be a class, I can setup a protocode for you:

class Rectangle
{
public int x;
public int y;

public int width;
public int height;

public boolean isHit(int px, int py)
{
return  (x <= px && px <= x + width) && (y <= py && py <= y + height);
}
}

You have to put all the Rectange Instance that you have created into some data structure, like array or Vector List etc such that you can test which rectangle has been hit, e.g.

List MyList   // Assume this is the list for holding the rectangles being hit
// Assume MyRectangleList holds all your rectangles
foreach (Rectangle r in MyRectangleList)
{
if (r.isHit(CurrentX, CurrentY))
{
}
}
0

LVL 1

Author Comment

I am not sure I understand. I assumed that you would need to inherit a Rectangle so GDI would know how to draw it. Am I confused?
0

LVL 48

Expert Comment

This is not direct answer to your question, but I don't think that keeping index inside of rectangle is right design decision. Rectangles, or any objects, should be kept in some container: vector, list etc. Object itself doesn't need to know anything about the way it is kept in the container - you can see such approach in akumanova's post.
In the case you use MFC, see MFC sample DRAWCLI which implements these algorithms.
0

LVL 1

Author Comment

I am using VB because I am most accustomed to the syntax but I can read C++ and convert it to VB without too much trouble. What I have done is add a right-click pop-up to DataGridView that displays the valid selections for a given cell. The control is an array of buttons drawn as rectangles each representing an integer with that text value in each rectangle. When the user left clicks one of the rectangles I want the value of the selected rectangle to be written into the cell. I could have used Button controls but they are significant overkill so I thought just adding a "value" to each rectangle or knowing the index would allow me to write that value. Right now the buttons are stored in an arraylist then removed when selected. The problem happens when one of the values has been previously selected and removed from the arraylist. Now there are, for example, 9 possible buttons but only 8 shown and if the one that is missong is in the middle of the list then if I iterate through the collection I have no way to know which button has been used.

I hope this is clear it all works pretty good except for this one last hing. I thought about storing the X,Y value (lower right hand corner) of each rectangle in a list when they are drawn then looking for e.X, e.Y after a hittest for the selected rectangle in that list and use the index as the value but this seemed like a kludge. Maybe it is the right way to do this? I am very much a newbie to OOP and VS.
0

LVL 85

Accepted Solution

Try this out...    (just add a PictureBox to a blank form)

Public Class Form1

Private Class MyRectangle

Private value As Integer
Private rect As Rectangle

Public ReadOnly Property DisplayValue() As Integer
Get
Return value
End Get
End Property

Public ReadOnly Property Rectangle() As Rectangle
Get
Return rect
End Get
End Property

Public Sub New(ByVal DisplayValue As Integer, ByVal layoutRectangle As Rectangle)
value = DisplayValue
rect = layoutRectangle
End Sub

Public Sub Paint(ByVal g As Graphics, ByVal f As Font)
g.DrawRectangle(Pens.Black, Me.Rectangle)
Dim sf As New StringFormat
sf.Alignment = StringAlignment.Center
Dim r As New Rectangle(Me.Rectangle.Left, Me.Rectangle.Top + Me.Rectangle.Height / 2 - g.MeasureString(Me.DisplayValue, f, Me.Rectangle.Size).Height / 2, Me.Rectangle.Width, Me.Rectangle.Height)
g.DrawString(Me.DisplayValue, f, Brushes.Black, r, sf)
End Sub

End Class

Private MyRects As New ArrayList

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
MyRects.Add(New MyRectangle("1", New Rectangle(10, 10, 25, 25)))
MyRects.Add(New MyRectangle("2", New Rectangle(45, 10, 25, 25)))
MyRects.Add(New MyRectangle("3", New Rectangle(80, 10, 25, 25)))
MyRects.Add(New MyRectangle("4", New Rectangle(10, 45, 25, 25)))
MyRects.Add(New MyRectangle("5", New Rectangle(45, 45, 25, 25)))
MyRects.Add(New MyRectangle("6", New Rectangle(80, 45, 25, 25)))
MyRects.Add(New MyRectangle("7", New Rectangle(10, 80, 25, 25)))
MyRects.Add(New MyRectangle("8", New Rectangle(45, 80, 25, 25)))
MyRects.Add(New MyRectangle("9", New Rectangle(80, 80, 25, 25)))
MyRects.Add(New MyRectangle("0", New Rectangle(45, 115, 25, 25)))
End Sub

Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
For Each mr As MyRectangle In MyRects
mr.Paint(e.Graphics, Me.Font)
Next
End Sub

Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
For Each mr As MyRectangle In MyRects
If mr.Rectangle.Contains(e.X, e.Y) Then
Debug.WriteLine(mr.DisplayValue & " selected")
MyRects.Remove(mr)
PictureBox1.Refresh()
Exit For
End If
Next
End Sub

End Class
0

LVL 1

Author Comment

That is perfect. It makes me envious to see what a real programmer (as compared to me) can do. Thanks for the help.
0

## Featured Post

### Suggested Solutions

Here we come across an interesting topic of coding guidelines while designing automation test scripts. The scope of this article will not be limited to QTP but to an overall extent of using VB Scripting for automation projects. Introduction Now…
This article is meant to give a basic understanding of how to use R Sweave as a way to merge LaTeX and R code seamlessly into one presentable document.
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…