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 strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to detect Click + [Shift, Ctrl, Alt] 2

Status
Not open for further replies.

bfwriter

Technical User
Jul 22, 2006
35
US
Sorry for the newbie question...

Is there a function to detect whether a Click event is Shift+Click, Ctrl+Click, Alt+Click, or (plain) Click? I am aware that the MouseDown event provides that status natively, but don't see how to pass that status to the Click event to be used in a DO CASE selector.

Thanks,
Will
 
Why want to forward it to Click? If you need that info about modifier key pressed and as you already know this info comes into MouseDown, then use the MouseDown event instead of Click. Move your Click code to Mousedown, Problem solved.

Bye, Olaf.



 
Many thanks, Olaf. That's great.
Works like a charm.
I much appreciate your help.
Will
 
Probably overkill for this discussion, but Mousedown() is not the same as Click().

A click is actually a composite event made up of BOTH mousedown() and mouseup() on the same control. Since mousedown() and mouseup() are also used in processing dragdrop operations, those are where you really need to know about the modifier keys. It's actually possible to get a mousedown() but not get a click() if the user slides the mouse pointer off the current control before releasing the mouse button.

It's worth fiddling with all the mouse events to make sure you understand what you're getting, and when.
 
Actually not "overkill" at all, Dan. (At least for me.)

I didn't bother to elaborate before, but my confusion (above) about thinking I couldn't put my Click code into the MouseDown event was due to my unfamiliarity with drag-and-drop apps; and I carried the vague notion that Mouse-Down and -Up were exclusively for that. Your explanation is very helpful.

Bests,
Will
 
Well, even if MouseDown was just for Drag&Drop, how would it only occur when you start a drag? How would a computer know in advance that you will drag? It could perhaps delay the mousedown, unless there also is a mousemove afterwards. But why should it, and how would MouseDown then ever happen on it's own? Why would there be such an event, if it only could hapen in conjunction with a drag?

You can easily let VFP log events, even without writing code in them, by SET EVENTTRACKING. It's easier to setup in the Debugger Tools Menu item "Event Tracking". You can pick which events to track, and eg limit the list to just all MOUSE... events.

What I observe is: Click is only caused by MouseDown + Up on the same control, but neither MouseDown nor Mouseup are suppressed, they also occur. The same goes for DblClick: Each DblClick has a preceeding Click, and that also isn't suppressed, the events happen additionally. So no problem, unless you are a control freak (pun intended) and only accept a real click event to be valid. Even then you could just store a value like "SHIFT" "ALT" "CTRL" or combinations of them in This.TAG and evaluate the TAG property in Click.

Bye, Olaf.

 
Actually not "overkill" at all, Dan. (At least for me.)

I didn't bother to elaborate before, but my confusion (above) that I couldn't put my Click code into the MouseDown event was due to my unfamiliarity with drag-and-drop apps; and I until now carried the vague notion that Mouse-Down and -Up were exclusively for that. Your explanation is very helpful.

Bests,
Will
 
I would go with Olaf's suggestion of using the MouseDown to store the state of the Alt, etc. keys, but to actually evaluate them in the Click.

However ....

Olaf, you suggested using the Tag property to store this information. I have always resited using that property, on the basis that you never know when it might clash with something else: another method of the same class using it for a different purpose, perhaps. What do you think about that? (I know this is not really relevant to the main problem, but still ....)

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Tag isn't a bad place for this sort of thing. From discussions early in the first alpha release, that's what it was intended for.

Although note that tag comes from VB, where they could not create their own subclasses with properties of their own. In the VFP world, we never really got into using tag for much because it was so easy to create our own.
 
You can of course create a dedicated poroperty. But as you should have an overview where in code you make use of TAG or not, it would be ok. Also MouseDown and Click will normally occur one after the other. Even if other events also use the tag property, this is likely not to interfere, here. Set TAG at mousedwon, either clear it in click or not, doesn't matter much, next mousedown will set it just in time before click again.

Another side note: I used the TAG to store the return value of a form from it's Unload, when I used modal forms with do form ... to variable. And that's another case I would alsways recommend it again, if there weren't more elegant solutions to forms returning values without even being modal by design patterns like mediator or specifically form handlers.

In this case I wouldn't create a button class just to be able to create a property for the short term storage of the key pressed in mousedown. Too much effort, even if you know you can select the button and save as class, then change the class, replace the form button. If you're really interested in the modifier keys at click you could also bindevent to keyboard events, or DECLARE INTEGER GetKeyState IN user32 INTEGER vKey and call it with vKey=16 for SHIFT, vKey=17 for CTRL and vKey=18 for ALT.

Bye, Olaf.

 
All good points.

Olaf, you say you wouldn't create a button class just for the ability to save the key state between MouseDown and Click. Nor would I. But don't you have your own base button class anyway? In fact, don't you have a whole library of your own base classes, which you use exactly for this sort of generic low-level customisation? That way, you'd be able to add this sort of feature at that low-level, without having to create a special class for it.

Similarly, you say you use Tag to store the value to be returned from a modal form. In my base custom form class, I have a property named ModalResult that is used for that purpose. It's the same idea, except that it's a custom property, not the native Tag property.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
>In fact, don't you have a whole library of your own base classes
Yes, and they all base on _commmandbutton, a class based on the native commandbutton.

But I don't assume everybody has. I rather assume people use native classes in their forms. Maybe that assumption is too pessimistic.

In regard of the Tag usage for unload, I had bad luck with userdefined properties, at least with objects added at runtime, Unload is even after destroy, so you can be sure Tag is still there, as it's native, other things migt already have been released, if they were dynamically added, at least.

My current approach is rather to pass around objects, no matter if they are relasesd/removed, the caller has control, if he created the object, he posesses the one original reference, which keeps the object alive.

Bye, Olaf.
 
What if a client will "click" on a control (with focus) by means of ENTER or SPACE on a keyboard, which is completely legal in Windows.
I thought that additional calling MouseDown() from somewhere will fix the problem, but it will not, because no parameters are received by MouseDown procedure when invoked programmatically.
How one should deal with this?
Tom
 
Tom,

I thought of that too. But it shouldn't be a problem, provided the Click always clears the property that stores the state of the keys in question. The MouseDown stores the key states, and the Click processes them, and then clears them. If there is a Click without a MouseDown (because the user pressed Enter or Space), then the keys will appear to be in the default state, which is presumably what you want.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
If you want to react to modifier key + ENTER or modifier key + SPACE, you can do so in Keypress, which isn't triggered by SHIFT, ALT or CTRL alone, but in combination. In that way you can react to mouse clicks with mousedown and keyboard "clicks" with KeyPress.

Bye, Olaf.
 
...and to reuse the same code you best put that code into a user defined method and call that from both MouseDown and KeyPress to unify this.

Well, you expand the idea to just store the modifier key state in MouseDown or KeyPress and then let the normal Click be the unified event, which it is anyway.

By the way, there is no UX guideline suggesting any different behaviour from SHIFT or ALT or CTRL + Click than from a "normal" click, the only thing I can think of is multiple selection, but that's done in a listbox and you don't have to program anything for the listbox to have that behaviour, simply set it to Multiselect = .T. - Well, off topic, as this is about the command button. I would really suggest not to make a button do different things with modifier keys.

If you need this, it's not straight forward, but unusual behaviour. What can I think of? Click = sorting ascending SHIFT+Click = sorting descending. Well, that could also be done by click/dblclick or alternating with each click. Even for keyboard users double hitting ENTER or SPACE is as convenient as SHIT+ENTER, isn't it? And mouse users, will they really use the keyboard as short cut to two clicks? You rather could define hot keys via command button captions to make a whole form easy to use with just the keyboard.

Bye, Olaf.

 
Mike and Olaf
Thanks to your help and inspiration I see now a suitable solution.
I'm sending Shift-Ctrl-Alt state as a numeric parameter to form's method MyClick from both MouseDown and KeyPress and I even need not to have temporary storage to these values.
So I have only
Code:
*** in KeyPress method
Thisform.MyClick(nShiftAltCtrl)

*** and in MouseDown
Thisform.MyClick(nShift)

I agree that using Shift, Ctrl or Alt combination with mouse or keyboard click can't be generally recommended. I'd completely eliminate combinations with Alt other then keyboard shortcuts used by program of course. But combinations with Shift or Ctrl are used in Internet Explorers, and so well accepted by users.
Sometimes such combination maybe useful or at least acceptable as Olaf mentioned. I occasionally use Shift + Click on CommandButton, when program offers some additional actions over standard button click actions.
The sense of my post was not to promote obscure key combinations, but to keep a code safe under all circumstances.
Tom
 
Tom,

I take your point about keeping code safe rather than promoting obscure key combinations. (If I want to provide some additional actions for a click, I generally attach a drop-down menu to the button, but that's just my own preference.)

Regarding your code: You would also need to check the nButton parameter to the MouseDown, to distinguish between right- and left-clicks. That should be easy enough.

Also, you might need to take account of the fact that a drag-and-drop operation fires MouseDown, but not Click (as Dan pointed out). Even if the application doesn't involve drag-and-drop, the user might conceivably still try to drag something, even though the app doesn't let them do so. The MouseDown would still fire in that case, so you might need to take action to inhibit the Click.

These issues probably won't apply in many cases, but it's worth keeping them in mind.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
>Also, you might need to take account of the fact that a drag-and-drop operation fires MouseDown, but not Click (as Dan pointed out).
>Even if the application doesn't involve drag-and-drop, the user might conceivably still try to drag something, even though the app doesn't let them do so.
>The MouseDown would still fire in that case, so you might need to take action to inhibit the Click.

Completely correct, that's why you could really make use of the normal Click() event, instead of calling MyClick(). That's what I meant as I wrote "expand the idea to just store the modifier key state in MouseDown or KeyPress and then let the normal Click be the unified event". That means instead of calling MyClick you just let Keypress and Mousedown set TAg (or other dedicated properties) and evaluate these properties in the click. You might also store SECONDS() to make sure the Click() happens right after MouseDown or Keypress.

Today I really had to fiddle with these low level events in case of a barcode scanner with Postamble "ENTER", so after the 13 EAN digits the barcode scanner sends ENTER. Which is nice in a situation you have SET CONFIRM ON, but not in my situation, as I had set Textbox.MaxLength=13 and SET CONFIRM OFF, instead. This meant the ENTER was sent to the next control in tab order, and that caused a functionality which should be manuylla triggered by ENTER, or not, depending on what the user wants to select next. I stop explaining the workflow, that would only lead off topic.

Why I tell this: 1. I made use of the TAG, I did use Mousedown and Keypress here, to solve the problem and especially swalled the ENTER with NODEFAULT in the Keypress of the next control. On the other side: It will be vary hard to tell next month, why I did this. So you better document such codes and what they mean and what they do and why they are there.

"To keep a code safe under all circumstances." is a good reason, but I don't see how quering modifer keys in a click event helps keeping something safe. What keeps code safe is clean, lean code, you can easily maintain and oversee and know what it does why. So if you ask me for my overall recommendation: I would not implement the feature to consider modifier keys with clicks. Rather add more buttons or use dblclick and/or right click, context menus.

What a collegou from a different software company does and showed in a regular meeting we have every month is, to have some small "hot spot" buttons, which when clicked, reveal more options. A bit like a context menu does, but which user really does know and use context menus? And besides: How do you use a right click in a touch interface?

UX is a topic of it's own. I'm a bit turtured by a current project, because the workflow is designed so fully guides with disabling/enabling controls, setting automatic focus etc, that any error in the logic, or any circumstance like a barcode scanner postamble disturbs the process and causes extra cases to be considered, that it's hard to meet the mile stoenes. I would always suggest to not narrow down the user to what should be enabled/disabled in the current situation, but instead keep anything enabled and rather give users too much rights than too less (within the limitations, that make sense). Eg it is nice, if a save button only get's active, when there is a change to save, but it's a catastrophe, if the button never get's enabled, because of an error in the code detecting changes. So why not have the save button enabled anyway. My customer is wanting such or comparable things and I couldn't talk them out of it, it's in their mind. I know no application, that does disable a save toolbar button or menu item.

Agin in short: Don't do what needs special programming and can't be simply set with one or two properties. There are seldom expceptions to the rule: keep it simple. This is mant for both the user and the developer.

Bye, Olaf.
 
Olaf said:
What a collegou from a different software company does and showed in a regular meeting we have every month is, to have some small "hot spot" buttons, which when clicked, reveal more options.

Another familiar device is to have the main button, and a smaller button immediately next to it, with the smaller button showing a down arrow. When you click on the main button, you get the default action. When you click the smaller button, you get the menu of alternative actions (with the default at the top of the menu).

Quite a few applications use this approach, which is fairly intuitive for the user.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top