Double Clicks

| | Comments (8)

If you've ever made an app with custom UI that needs to respond to double clicks, then you've probably caught yourself wondering how to do it. And you've probably come up with a solution.

But was it the proper solution?

Here's the things you need to remember when testing whether something is a double click.

1) Are the two clicks close enough in time? That's a no-brainer that everyone gets right. You use system declares to find out what the OS thinks the proper time-between-clicks should be for a double click and you save the old click time to compare against the new one.

2) Are the two clicks from the same button? It's not a double click if it's a right/left click combination. It has to be two left or two right clicks.

3) Are the modifier keys in the same state? It's not a double click if the first one has shift held down and the second one has control. If the modifier key states aren't the same, it's not a double click.

4) Are the clicks in the proper location relative to one another. Here's where it gets really fun. On Windows, there's a declare into GetSystemMetrics (usually returns 4 or 5) -- if the clicks are further away than the cx and cy returned from this call, it's not a double click. This holds true for Linux as well (but I don't know if there's a declare or not). However, on the Mac, it's element-based. So if you are clicking on say a listbox, then the two clicks need to be on the same row of the listbox, but not within 5 pixels of one another. So the basic rule of thumb is, use the system declares if you have them, otherwise default to about a 5 by 5 area, and if you're on the Mac and using an element-based UI item, base it on the width and height of a single element.

5) As if that's not bad enough, if you process both single clicks and double clicks as different events, you're in for a whole world of hurt. You can't know when a double click has happened until a certain period of time has elapsed because a single click could really be the start of a double click. So if you want these events to be doing different operations (like the way the tray items do on Windows), then you need to throw a timer in there and only fire the SingleClick event if the timer's fired before a second click comes in. Btw, if you're UI is such that a single click is a selction and a double click is an operation on a selection (like in a listbox), then you don't have to worry about this sort of thing.

Phew! Ok, now by show of hands -- who here has gotten their double click code wrong before?

8 Comments

Not me - I've never needed to do this :-P

:: raises hand :: don't believe me? Try ListBox.DoubleClick on Windows -- you'll see that it's ignoring the rectangle area and just basing it off the entire row (like the Mac should, and does, behave).

Not a good record
I think I always get (1) right with some assistance from the LR,
(2)I have to admit I never check it's the same button.
(3) Heaven only knows what complications I've caused with modifier keys.
(4) I wrongly use 5 pixels, though I do get it right for the mac (probably the only thing I get right for the mac) and
(5) I nearly always get right because I always consider it individually for the circumstances.

*raises hand*

Though I can talk myself out of it: It was on Classic MacOS, and I didn't go through the hassle of trying to detect mouse buttons, because back in the WaitNextEvent days, multi-button mice were a hack. Though I dont really remember whether I checked the modifiers, so I guess two half-mistakes makes one full one any day :-)

Thanks for posting this handy list!

Or you can use the appropriate system events. When I write non-Rb Windows code, I just listen for WM_LBUTTONDBLCLK and let the OS decide what a double-click is... That might be harder in the Rb framework (multi-platform, needs to get things at a pretty low-level to send them on, etc), but if you can use them I recommend letting the system do as much work as possible.

There is a Linux function (actually you need to call two) -- you figured out how to declare them for me for my book :)

Leave a comment

Disclaimer

I'm currently an employee of REAL Software. My blog is mine. The opinions represented in this blog are mine as well and may not represent my employer's opinions. All original material is copyrighted and property of the author.

REALbasic® is a registered trademark of REAL Software, Inc. REAL SQL Server™ and Lingua™ are pending trademarks of REAL Software, Inc. All rights reserved.