views:

189

answers:

4

I have a dialog created from a template. It has controls listed in the template in the following order:

  • some irrelevant controls
  • a label with an accelerator (let's pretend it's Alt-A)
  • an edit box
  • OK and Cancel buttons

Normally when I hit Alt-A the keybord focus is transferred to the edit box - just as needed. However I sometimes need to disable to edit box.

If I hit Alt-A when the edit box is disabled the effect is that the OK button is pressed and that is definitely not what I want. I would prefer to have no action taken in this case. What could I do to workaround this?

A: 

I'm not so familiar with MFC, so I'm trying to answer in general terms:

As far as I can make it out, what happens is that you have a so-called accelerator conflict. A is the accel key for both the edit box, and - I'm guessing here - the Apply button.

The solution is to avoid this situation. Ambiguous accel keys are a PITA for users, as you've yourself discovered. In KDE, therefore, we have an automatism that assigns accel keys at runtime based on some heuristics. That's often enough, though it occasionally yields suboptimal results.

If you're using some form of form designer to lay out the controls visually, these tools usually have a way to check for accel key conflicts. Otherwise, back in the olden days, I'd click on all accel keys while testing to see whether they'd work as expected.

But the bottomline is: Don't let duplicate accel keys happen in the same scope.

I don't duplicate anything. The problem is that the accelerator triggers the next non-disabled control. When editbox is enabled it is the next non-disabled control. When it is disabled the OK button becomes the next non-disabled control.
sharptooth
A: 

When you enable/disable the edit box you can either enable/disable the label control with the accelerator as well, or simply add/remove the accelerator on the label by changing the window text. Both should give you the desired behaviour.

Steve Beedie
Disabling the label will make it grayed out - that's not appropriate in my case. And tweaking the text is horrible - I will need to remember the position of the ampersand symbol for each label text I tweak this way. Horrible, but would work.
sharptooth
If you're using string resources for the labels, set the value with the ampersand and use that when enabled, and simply remove the ampersand when disabling. No remembering of positions required.
Steve Beedie
I actually have the labels defined as static controls in the dialog template. If I go this way I'll need to remember where the ampersand was so that when I enable the dependent control the accelerator becomes functional again.
sharptooth
A: 

I just tried this and it seemed to work ... albeit it's a sneaky method.

After the edit control, drop in a button (sized arbitrarily). Change the property on the button to be "Owner Draw" but don't actually implement any drawing logic. Also, make sure it's tab order is set to be immediately after the edit control.

This will have the effect of making the button invisible when run. When the edit control is disabled, the invisible button is really triggered to no effect.

NOTE : You can't just remove WS_VISIBLE from (or otherwise hide or disable) the button as that may make the control invisible, but also prevents the control from being in the tab order.

Using this method, your focus will disappear (as it's on an invisible button) when you hit the accelerator when the edit control is disabled. If you don't like this, add a handler to the new invisible button to set the focus to where you'd like it in the case that the edit control is disabled. That way the accelerator clicks the button, invokes the handler, which restores focus to where you'd like.

Hope this helps!

paradoxpenguin
A: 

It's been a long time since I've worked in MFC and Windows SDK, but from an architecture point of view, there should be an event handler you can hook into. Maintain an internal flag for when the edit box is disabled. When the edit box is disabled, eat any Alt-A events.

Mike Yam