Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Click and Double-Click issue 3

Status
Not open for further replies.

Scott24x7

Programmer
Jul 12, 2001
2,826
JP
Hi all,
Haveing an odd issue with Click and Double-Click events.
No matter how quickly I double click, my click event fires first, and then the double click-event, though I'm only looking for the double click event to fire. Is there some way to fix this? A timer property for click at a global level of some type?


Best Regards,
Scott
ATS, CDCE, CTIA, CTDC

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Scott, I went out for a breath of fresh air, and consequently missed the last dozen or so posts in this thread. But I'd like to comment on a couple of your earlier statements:

It seems a little silly (just venting) that VFP created a Click event and a Double-Click event and then expect only one of them to be used on any object...

This is nothing to do with VFP. The fact that Click and Double-Click are separate events is a Windows thing. In fact, it pre-dates Windows, and goes back to the early Xerox PARC interface. And, given that there are two separate events, how could you prevent both of them from firing? When the user does the first click, how would the system know that a second click is coming along in a few hundred milliseconds?

I don't like the idea of the context menu because it means users have to move mice, and "target" their next click, and that's time.

True, but on the other hand, the solution I suggested has the advantage of being consistent with other Windows applications. The concept of right-clicking on an object and seeing a list of possible actions to perform on that object is one that would be familiar to all Windows users. However, if you really don't like that idea, there are other ways of letting the user choose which action to perform, other than having to distinguish between single and double clicks.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Is there any danger in creating a property on the image class I'm executing the Click from? Something like This.Clicktime = .5 where I establish Clicktime as a property of that class.
Then I don't need spurious text boxes to store hidden values in. :)

I quite like using a text box, because you can leave it visible during testing.

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
Talking about alternatives.

I put myself in user's place.
I click the object and nothing happens.
I become impatient and click the second time. This way I trigger a dblclick event, unwillingly.
Frequently users don't (wait to) read the messages, and press Enter.
This way, the image is deleted, and the user become angry :)

You've got already some good alternatives.
Instead of Click and DblCLick, you can use the MouseUp event, to propose combinations like Ctrl+click, Shift+click to your users.

Respectfully,
Vilhelm-Ion Praisach
Resita, Romania
 
Ok... you've convinced me to abandon this approach, and look for an alternative.
Mike, you make some great point on this. I think what I will do to keep it simple, and not compromise on the heavy entry is:

1) Click to Enlarge/Reduce (and keep that code there).
2) Right click will be to replace or add the image, so simple right click with nothing else to select.
3) In thinking about it, it will be rare to delete an image altogether, usually for "user mistake" in adding the wrong image to start with, and not haveing one to add. So I will create a "Remove Image" button next to the image with an "X" in the text (and nothing else to keep it small), and when a user clicks that, it will ask them "Do you want to remove this image" (Yes/Cancel) option.

That should keep the interface smooth, and not overload things...
Interesting lessons learned about Click and Double-Click events. Guess I never thought about how it would manage that overall from an Event Model standpoint, and not a VFP standpoint.

Now, back to making my TWAIN scan work. :)


Best Regards,
Scott
ATS, CDCE, CTIA, CTDC

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Scott, I'd make one very small change to your proposed solution. You wrote:

when a user clicks that, it will ask them "Do you want to remove this image" (Yes/Cancel) option.

If you are asking a question ("Do you want to remove the image?"), the choices should be Yes or No. If you are making a statement ("You are about to delete the image."), the choices should be OK or Cancel. I wouldn't mix them. (Ignoring the fact that there is no Yes/Cancel option in the standard message box.)

But this is just my personal preference. Others will disagree.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike, Mike, Mike.... there you go with that "real" English stuffs again. [rednose]

I agree. Asking a yes/no question and NOT giving yes/no as options for the answer is just rude.

I've NEVER understood why MessageBox() supports Yes/No/Cancel as an option. No says "don't do this". What does "Cancel" say that isn't "don't do this"? <g>
 
Jeeze you guys are stickler... the option under MESSAGEBOX is OK/Cancel (Not Yes/Cancel), and that's what I've gone with. I don't see an issue with "Do you want to remove this image" with an "Ok or Cancel" not satisfying that question...

Cancel says, "Ooops, I made a mistake" it's not at all vague about what you are click. Ok says proceed... it will be gone.

Now, this solution for me is finalized... Here's what I did.

I decided NOT to use a command button or anything anywhere near it. While perhaps slightly unconventional, I have utilized a transparent PNG which has a red "X" in it (that is obviously not a "character X", but a graphic). With a very faint dotted outline, placed in the upper right corner of the image below it. I used transparent PNG so that it doesn't really obscure the view of the file. It's only about 10 pixels high, visible and obvious, but not intrusive. I have added a "Tool Tip Text" that when you hover over it stays "Click to remove image". So before you click it, you get a message about what it does.

Click it, you get asked as stated above.

Single click on the image makes the image appear in full size, and click it again, it returns to previous size. Right click, and GETFILE() (wrapped in a procedure that does some other control) allows you to pick an image to include.

AND... for consistency, the option buttons that GETFILE() provide are... "OK or Cancel". So I'm vindicated. :)

Best Regards,
Scott
ATS, CDCE, CTIA, CTDC

"Everything should be made as simple as possible, and no simpler."[hammer]
 
You know, Scott, there's one other tiny detail I would add to your solution (at risk of being called a stickler again; or maybe that should read: in the hope of being called a stickler again).

When you hover the mouse over the image at normal size, change the mouse icon to a magnifying glass with a little plus sign in it. When the image is full size, change it to a magnifying glass with a minus sign in it. That would make an excellent visual cue. And it would be consistent with the behaviour of some other Windows applications.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike, that's a brilliant idea. Doesn't win you a "stickler" I only use that in negative connotation... :) (i.e. splitting hairs).
This is good value, and I agree. That will help. Might almost make sense to make that it's own subclass...

Best Regards,
Scott
ATS, CDCE, CTIA, CTDC

"Everything should be made as simple as possible, and no simpler."[hammer]
 
You know you can choose several sets of answer buttons in a messagebox. YES/NO are one OK/CANCEL another, you can also have YEs/No/Cancel or Abort/Retry/Ignore.

Anyway, I wonder how Mike got your attention with a sentence "given that there are two separate events, how could you prevent both of them from firing?" I just said "There's nothing yet invented predicting the future".

Anyway, I just tried in C# and there you only have Click, MouseDown and MouseUp, C# Winforms also have a specific MouseClick event, which differs from the normal Click (I think) by only reacting to mouse clicks, while the normal click event also reacts to a SPACE key while the button has focus.

And I thought about any Windows interface on the same object having using click and doubleclick. There is something, quite easy to find. Any shortcut on the desktop reacts to a click by just being selected and a double click starts the open action. But it also selects the icon, because the click runs first.

What you could do to stay with your interface is making a zoom animation starting with a click. The double click then can interrupt that zoom in operation and you have the unwritten interface rules satisfied, that an event has a instant response, the user sees his click was detected.

Anyway, you se you don't get around using a timer, if you want to both not prevent the second click event and also be able look back at the short past in the timer event. Griffs idea to init some property holding the Seconds() value can work, but you always have the click first, which is detected as the click is way past the initially stored SECONDS(), more than .5 seconds past it. You just need to set that value to the current SECONDS() value at the end of the click, so the second click can be measured to be in the .5 seconds interval. But in his simple click event without a timer you always will have a click first and a doubleclick secondly, and that has two problems: 1. If you react to the click already, you can only do the double click on top of what you do at click, not instead. 2. If you only react to the double click, you can't react to the click - To let the Click event occur after the .5 seconds have passed you have no event, the user would need to click for a second time to trigger the click event after .5 seconds have passed, therefore making it two single clicks, but that would only start waiting for the double click again. The solution would be to start a timer at the first click (if SECONDS()-propertyvalue>.5) which waits .5 seconds to then do the click action in it's timer or stop the timer, if the second click occurs before the timer event goes off. But that has the most important downside of making a click only work with a latency of .5 seconds - simple because you can't react to the click right away as you can't foresee the future.

Or in other words: If you want to accept two clicks within .5 seconds as a doubleclick, then you have to wait .5 seconds to see, whether a second click occurs, you can only judge what event you had after .5 seconds and that's way to much time for users used to instant actions of clicks. It's not too much timer to wait for a web page to react to a link click, but you still would be used to see the browser react with a status bar message "waiting for server.com".

And what do you want to put there as statuts message for .5 seconds? "Waiting for you"?

The example of the desktop links to start apps is, that you can only have a click/doubleclick event pair on the same object, if it won't matter, that the click event occurs additional to the doubleclick.

If you want the OS to make that decision for you and only trigger wither click or doubleclick event in VFP, then the same problem applies, the OS would need to wait for the double click interval to be able to make that decision about what event you really had.

A wait time of .5 seconds before an image pops out zoomed can be noticed - and will be an annoyance. A smooth zoom in animation taking perhaps 2 seconds would not really have a big effect, if you doubleclick within .1 seconds, you might then fade the picture to transparency to illustrate the deletion of it while continuing to zoom.

Bye, Olaf.
 
Actually, Griff, I did you wrong, your idea includes setting the seconds() value at the end of the click. Yet I only very rarely get it to evaluate a double click as double click.

Anyway, the click would always occur, too. And it would occur first. Which is just the normal behaviour of the native events:

Code:
Public ofrm
ofrm = Createobject("myform")
ofrm.Show()

Define Class myform As Form

    Procedure Click()
       Activate Screen
       ? "Click"
    EndProc
    
    Procedure DblClick()
       Activate Screen
       ? "DblClick"
    EndProc

Enddefine

You will not ever make a double "DblClick" appear, you'll always have a click event first. So you have to live with that and start the click action in a way the user has enough time to make the second click on the same object, like a zoom animation would do.

Bye, Olaf.
 
Olaf,

My suggestion is to manage the dblclick in the click, dump the dblclick event itself.

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
Yes Griff,

but as said it doesn't work:
Code:
Public ofrm
ofrm = Createobject("myform")
ofrm.Show()

Define Class myform As Form

	Procedure Init()
		AddProperty(Thisform,"_lastclick", Seconds())
	Endproc

	Procedure Click()
		Activate Screen


		If Seconds() < Thisform._lastclick+.5
			? "Double Click"
			&& do your doubleclick event stuff here
		Else
			? "Click"
			&& do your click event stuff here
		Endif
		&& store the current seconds() in the text field
		Thisform._lastclick= Seconds()
	Endproc

Enddefine

Ar least on Windows7 and with VFP9 this very rarely shows up DblClick. As if VFP prevents the click event happening again. What happens instead of the secondary Click is the DblClick event. Your idea is OK, but it does only work in theory.

If you frenetically click you get Doubleclicks, but if you doubleclick once only, then wait, you only get click without the doubleclick. In theory your code should print Click and Doubleclick right after one another, as each double click has a click first and then a double click. Instead of a second click even the DblClick event occurs. Therefore your idea is nice but not working.

The point is, ig you freneteically click of course even the click event will occur fast enough. But if you use the application you'll do a single doubleclick only, and then your code only shows a click, the second click doesn't go into the click event.

I'll illustrate this by also implementing the DblClick:

Code:
Public ofrm
ofrm = Createobject("myform")
ofrm.Show()

Define Class myform As Form

	Procedure Init()
		AddProperty(Thisform,"_lastclick", Seconds())
	Endproc

	Procedure Click()
		Activate Screen
		If Seconds() < Thisform._lastclick+.5
			? "Double Click"
			&& do your doubleclick event stuff here
		Else
			? "Click"
			&& do your click event stuff here
		Endif
		&& store the current seconds() in the property
		Thisform._lastclick= Seconds()
	Endproc

	Procedure DblClick()
		Activate Screen
		? "Real DblClick"
		Thisform._lastclick= Seconds()
	Endproc

Enddefine

If you click frenetically on this form you get only Doubleclicks from your click event, but if you do doubleclicks with each a pause of over .5 Seconds your "fake" doubleclick inside the click event does not occur, only the real dblclick. The reason is, if you doubleclick the second click event does not trigger the click event code, it only triggers the DblClick event. If you frenteically click wach third click now triggers the normal click event and let's your click code see it as double click.

That can also be seen, if you do triple clicks with a pause of >.5 seconds you get Click, Real DblClick and Double Click in that order.

So Griff, in the end your else branch detects a triple click event in the click event, but the second click, which is the real double click always goes in the DblClick event and does not trigger the click event, too.

Bye, Olaf.
 
I used +1 not +.5

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
It doesn't matter what time interval you use, I adapted it to my _Dblclick, if I set it to 1 I only have to pause longer to see the behaviour.

1. The first click triggers the native Click event
2. The second click triggers the native DblClick event and not the Click event(!)
3. The Third click triggers the native Click event. If that happens within .5 (or 1) second, you get your double click, but indeed it's only happening with each third click.

You invented the triple click event.

Bye, Olaf.
 
triple click?

well it must be a bit locally dependant.

B-)

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
Well, no. The second click does never arrive at the Clik event. Please do as users of an application would do, do a distinct double click. Users knowing a double click will cause some action will not frenteically click on something, they only would do a distinct double click. And then the click event only fires with the first click, the second click doesn't go there.

To illustrate this even further, look at this output including the MouseDown/Up Events, which happen every click:

Code:
Public ofrm
ofrm = Createobject("myform")
ofrm.Show()

Define Class myform As Form

	Procedure Init()
		AddProperty(Thisform,"_lastclick", Seconds())
		AddProperty(Thisform,"_clickcount", 0)
	Endproc

	Procedure Click()
		Activate Screen
		If Seconds() < Thisform._lastclick+1
			thisform._clickcount = thisform._clickcount + 1
			&& do your doubleclick event stuff here
			? Seconds(),"Griffs Double Click = Triple Click",thisform._clickcount
		Else
			thisform._clickcount=1
			? Seconds(),"Click",thisform._clickcount
			&& do your click event stuff here
		EndIf
		? thisform._clickcount
		&& store the current seconds() in the property
		Thisform._lastclick= Seconds()
	Endproc

	Procedure DblClick()
		Activate Screen
		thisform._clickcount = thisform._clickcount + 1
		? Seconds(),"Native Double Click",thisform._clickcount
		Thisform._lastclick= Seconds()
	EndProc
	
	
	Procedure MouseDown()
		LPARAMETERS nButton, nShift, nXCoord, nYCoord
		Activate Screen
		? Seconds(),"MouseDown",thisform._clickcount
	EndProc
	
	Procedure MouseUp()
		LPARAMETERS nButton, nShift, nXCoord, nYCoord
		Activate Screen
		? Seconds(),"MouseUp",thisform._clickcount
	EndProc

Enddefine
Your Click detection resets the click counter I introduced, your Double Click detection never happens at click count 2. It doesn't happen at multiples of three only, but the second click after the click always goes into the native DblClick event and not the Click event.

Bye, Olaf.
 
Olaf said:
Anyway, I just tried in C# and there you only have Click, MouseDown and MouseUp, C# Winforms also have a specific MouseClick event, which differs from the normal Click (I think) by only reacting to mouse clicks, while the normal click event also reacts to a SPACE key while the button has focus.

That's an interesting point.

As you know, that distinction doesn't exist in VFP. VFP fires the Click in the following cases: (i) click with the mouse; (ii) press the spacebar when the control has focus; and (iii) press the Enter key when the control has focus. In cases (ii) and (iii), it also fires the Keypress (before the Click).

I'm not sure why I am mentioning this. I wonder if it has any practical uses.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike,
I took your recommendation one step further. So the image does have now the + or - "magnifying glass" depending on the state of the image (zoomed or normal size). But I also created a visual cue with the "Remove Image" "X", by creating a "glowing" version of the image, so when you mouse over it, it appears to "glow", to let you know there is something more to it. And of course the tool tip text helps to show what will happen if you press it. I think it's a nice, smooth interface, which will also work in touch screen environments (not that I expect this to be used as a touch application, but you never know...)
In any case, I think it's a very smooth and intuitive interface, consistent across all image manipulation in the system now. Thanks to all for your influence in making this work better.


Best Regards,
Scott
ATS, CDCE, CTIA, CTDC

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Scott, your idea of a "glowing" image sounds interesting. Out of curiosity, how do you do that? I can think of several ways of highlighting a control in that way, but I'd be interested to hear your approach.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top