Subclassing TextField - Creating Double-Click event - any gotchas

I’m in the process of subclassing a TextField control. I’ve created a DoubleClick event. From this subclass control I will be subclassing it further in relation to database controls which will account for text, numbers, dates etc. I’m wanting the DoubleClick event to be available when I’m working with my database forms. The code is below but my main concern is this, are there any gotchas to be aware of, especially for further subclassed controls? I’ll be using the DoubleClick event for my date entry controls, opening up a date-picker window. I also want it available for stuff that I haven’t even thought of just yet but if not activated I want the mouse functions concerned with the control to default to their normal state; hence any gotchas?

I’m also open to suggestions if the below could be coded more efficiently or differently.

Created new class : TextField_DoubleClick (I don’t use this name, only for forum purpose) Super class is TextField
Create event definition : DoubleClick ( X as Integer, Y as Integer)
Create properties: lastClickTicks, lastClickX and lastClickY (all as Integer)

Function MouseDown(X As Integer, Y As Integer) As Boolean
  dim doubleClickTime, currentClickTicks as Integer
  
  #if targetWin32 then
    Declare Function GetDoubleClickTime Lib "User32.DLL" () as Integer
    doubleClickTime = GetDoubleClickTime() / 10
  #endif
  
  currentClickTicks = ticks
  
  if not IsContextualClick then                      // not a right click
    
    if (currentClickTicks - lastClickTicks) <= doubleClickTime then
      //if the two clicks occured close enough together in space
      if abs(X - lastClickX) <= 5 and abs(Y - LastClickY) <= 5 then
        HighlightWord(X,Y)     // My function -  simply called to highlight selected word (same as default behaviour)
        RaiseEvent DoubleClick(x,y)
        return true     // don't need to set lastClickTicks etc. as job done, they can be reset next first click.
      end if
    end if
    
    // only a single click at this time, need to record timing info so second click can be compared to it.
    lastClickTicks = currentClickTicks
    lastClickX = X
    lastClickY = Y
  end if
  
  return false     // so as not to cancel out the mouse action.
End Function

In my testing, I’ve subclassed this control further and it all appears to work, that is, if the DoubleClick event is not activated then a double click in the control merely selects a word, if any, of the control. If code is entered in the DoubleClick event then that code is activated.

ps. I’ve removed references to the Mac & Linux code. Having said that, for this instance I don’t really see the point in calling operating system functions, one could merely assume that a double click speed is quick, less than one second, maybe two.

Hi Steven,

try this… it works for me…

dim doubleClickTime, currentClickTicks as Integer static lastClickTicks as integer static lastClickX as Integer static lastClickY as Integer

[quote=12686:@Jürgen Wagner]Hi Steven,
try this… it works for me…

dim doubleClickTime, currentClickTicks as Integer
static lastClickTicks as integer
static lastClickX as Integer
static lastClickY as Integer[/quote]

The old static statement thanks, that cleans things up a little, don’t need to create separate properties and having to search for them in different areas of the IDE albeit within the same tree of the subclass control (still getting use to Xojo IDE). Never used the static statement before, well not for many years. Thanks for pointing this out.

Except static isn’t really appropriate here. Storing a value in a static property is exactly the same as storing it in a module’s global property. It will work here only because X/Y should be different enough as you move between controls so as to force a reset of the properties, but it’s more appropriate to store values unique to an instance of a class within class properties.

Your code does not allow the subclassed instance to use the MouseDown event. Was that intentional? If not, Raise MouseDown(X,Y) as the top of the event and, if true, return true immediately.

Another approach to this problem would be to introduce a “DoubleClick As Boolean” property instead of raising an event. The code I’m envisioning would go something like this:

zDoubleClick = CodeToFigureOutIfThisWasADoubleClick
return Raise MouseDown(X,Y)

The instance could then check the “DoubleClick” (or whatever) calculated property and modify its behavior accordingly, the most appropriate place for that check being MouseDown or MouseUp, but not limited to those. The advantage is flexibility, but I’m not advocating it per se, just throwing it out there as an alternative.

You highlight a word on double-click manually within your code, but couldn’t you just return false after you fire your DoubleClick event and let Xojo deal with it? (I’m guessing you tried that and there was some other reason you wanted to do it that way.)

I don’t think any of these count as the “pitfalls” you were concerned about. Overall, the concept should work well.

If only I could edit my reply above, I’d change “pitfalls” to “gotchas”.

Thanks Kem

Point taken.

Yes you’re right. Not intentional, I’ll include this RaisedEvent.

[quote=12710:@Kem Tekinay]Another approach to this problem would be to introduce a “DoubleClick As Boolean” property instead of raising an event. The code I’m envisioning would go something like this:

zDoubleClick = CodeToFigureOutIfThisWasADoubleClick
return Raise MouseDown(X,Y)[/quote]

Must admit, need time to think this through.

You know what, in my testing I detected that the default behaviour wasn’t happening and so I went about writing a little routine. You’re right returning mousedown false, Xojo reverts back to the default behaviour state. In drafting I had things all over the place which obviously gave results (and side effects) I wasn’t expecting or wanting.

The only issue I could see then is that your DoubleClick event will fire before the word is highlighted. I’m not sure if that matters to you.