Determining if a click is on the canvas background or an object

I am using the following code to determine if a click is on a rectangle in a canvas. The rectangles are all held in an array of BITCObjects (a custom class to hold each rectangle and a variety of related parameters for it) called mRects().

In the MouseDown event in the DesktopCanvas:

For i As Integer = mRects.LastIndex DownTo 0
  Var r As BITCObject = mRects(i)
  If r.ClickedWithin(x, y) Then
     // do stuff here 
    Return True
  End If
Next

There’s a method within the BITCObject class called ClickedWithin, which is used to determine if you are clicking inside of an object:

Public Function ClickedWithin(px As Integer, py As Integer) As Boolean{
   Return (px >= X) And (px <= X + Width) And (py >= Y) And (py <= Y + Height)
}

This all works just fine. You can, for example, create multiple BITCObjects on the canvas, click on them and have them indicate the clicked one is currently selected. Double click and a popover window appears to let you edit the parameters for that object. Right click and get a contextual menu that lets you do stuff to that object. All works fine.

But because the ClickedWithin method is inside the class object and you have to iterate through all the objects in the mRects() array and test them one at a time, I can’t just add an Else statement to the mousedown event. This is because clicking on a different object than the one currently being tested, will trigger as clicking on the background.

That is:

For i As Integer = mRects.LastIndex DownTo 0
  Var r As BITCObject = mRects(i)
  If r.ClickedWithin(x, y) Then
     // do stuff here 
    Return True
  else
    //This is not clicked on THIS object,
    //but it's not necessarily the background. It could be
    //a different rectangle than the one we're currently testing
  End If
Next

So what’s the best way to see if a click on a canvas is on a rectangle drawn on that canvas or not. One thought I had was creating a picture of the rectangles on the canvas, with the rectangles full and the background transparent, then testing against that to see if the click is on a transparent part or a part with visible color. But complicating matters: the rectangle doesn’t always have a fill, sometimes the background is partially or completely transparent and it only contains text.

Set a flag (boolean variable) and set it in the loop. Change Return to Exit - quit the loop early and continue execution on the next line after the loop.

Var inRect as boolean = False
For i As Integer = mRects.LastIndex DownTo 0
  Var r As BITCObject = mRects(i)
  If r.ClickedWithin(x, y) Then
     // do stuff here 
     inRect = True
     Exit
  End If
Next
if not inRect then
   // clicked on canvas
end
3 Likes

Of course! Thank you!

No need to make things harder than it is:

Var clickedObject As Rect
For i As Integer = mRects.LastIndex DownTo 0
clickedObject = mRects(i)
  If clickedObject .Contains(x, y) Then // .Contains is a method already existing on rect instances
     // do stuff here, 

     Exit For i // Exit this loop (or call all clicked objects)
  End If
Next
if  clickedObject <> Nil then
   // clicked on canvas, specificly in the clickedObject 
end
1 Like