Recent

Author Topic: Accelerator keys  (Read 23534 times)

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Accelerator keys
« Reply #15 on: August 05, 2014, 01:49:36 pm »
Summary OS / LCL widget type -> result :
...
Windows      / Gtk                     -> >>>>>>>> Please can someone  test. <<<<<<

I presume you mean
Windows     / Qt
...or some other OS/widget combination?

rvk

  • Hero Member
  • *****
  • Posts: 6162
Re: Accelerator keys
« Reply #16 on: August 05, 2014, 02:21:36 pm »
Something I haven't figured out is how to just set the focus on TRadioButton without Toggling when there are more than one AccelChar target, but I'll find way.
The TRadioButtons in a TRadioGroup behave like this for me, but even if the AccelChar is unique which is not right according to Windows-standards ;D

QUESTIONS to rvk, Windows 7 : does it beep always when you do Alt+Valid_AccelChar (I think it shouldn't).  Does it beep always when you do Alt+INEXISTENT_AccelChar (I think it should).  Does TLabel.Caption.AccelTargetChar -> FocusControl ?
Yes, every Alt_key (valid or not) bleeps.
The Accelchar of a TLabel does set focus to the FocusControl of that TLabel.

The problem i had on August 02, 2014, 12:15:46 pm is still there. But it's not that the focus doesn't go to that control (TRadioButton) but the focus-lines are not visible (sometimes). I can't put my finger on it but it does happen from time to time. This, however, is a separate problem from what we're discussing here (so you can ignore that for now).

My testing now is this (consistently on 2 Windows 7 machines):

Windows 7 pro 64bit, Lazarus 1.2.4 r45510 FPC 2.6.4 i386-win32-win32/win64 (Language English Keyboard US)

*) All Alt + keys (valid or not) produce a bleep. (So the bleep is a bug when it comes to valid accelchars)
         (probably a missing key := 0 when handled somewhere is my delphi experience)

*) Pressing the accelchar for TCheckbox checks the box and sets focus on the box. (correct behavior)

*) Pressing the accelchar for TRadioButton DOES NOT check the circle (select), but does set the focus on the RadioButton. (incorrect behavior for it should select the circle)

*) The TCheckbox and TRadioButton within the TRadioGroup and TCheckGroup behave the same as their counterparts outside it.

*) Pressing the accelchar for TLabel does give control to the FocusControl of the TLabel (again with bleep but behavior is correct)

*) Pressing the accelchar for TButton does activate the onclick but does not set focus to the button. (correct)

The only problem here, which isn't Windows-behavior, is that the TRadioButtons should get selected with the accelchar. Now you would need to press the space-bar to select the choice you already made with the accelchar.

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: Accelerator keys
« Reply #17 on: August 05, 2014, 02:47:10 pm »
The problem i had on August 02, 2014, 12:15:46 pm is still there. But it's not that the focus doesn't go to that control (TRadioButton) but the focus-lines are not visible (sometimes). I can't put my finger on it but it does happen from time to time. This, however, is a separate problem from what we're discussing here (so you can ignore that for now).

Have you tried what I've suggested before ?

When it happens, press the tabulation key (for instance) and try again: you should now see the focus rectangle.


**Edit**

*) All Alt + keys (valid or not) produce a bleep. (So the bleep is a bug when it comes to valid accelchars)  (probably a missing key := 0 when handled somewhere is my delphi experience)

As explained in bug 19223, the beep is coming from the menu handler. A MNC_IGNORE value is returned by default to the received WM_MENUCHAR message, when no menu corresponds to the given mnemonic (whichever are the result for the controls themselves).

And this value provokes a beep: see http://msdn.microsoft.com/en-us/library/windows/desktop/ms646349%28v=vs.85%29.aspx

.
« Last Edit: August 05, 2014, 03:36:32 pm by ChrisF »

rvk

  • Hero Member
  • *****
  • Posts: 6162
Re: Accelerator keys
« Reply #18 on: August 05, 2014, 03:06:51 pm »
The problem i had on August 02, 2014, 12:15:46 pm is still there. But it's not that the focus doesn't go to that control (TRadioButton) but the focus-lines are not visible (sometimes). I can't put my finger on it but it does happen from time to time. This, however, is a separate problem from what we're discussing here (so you can ignore that for now).

Have you tried what I've suggested before ?

When it happens, press the tabulation key (for instance) and try again: you should now see the focus rectangle.
Yes, with some 'tabbing' around i get the focus rectangle back. But it shouldn't loose that rectangle. I can consistently see now that when starting my app there is no focused control (which is correct because there is none set) but when using an accelchar it should set focus on the control of that accelchar. (The focus does shift to the control but i can't see it because there is no focus rectangle.) It's just like the focus rectangle only becomes visible after doing some tabbing.

After that the focus rectangle usually stays visible (only once in a while i lost it again but i can't reproduce this consistently).
(So there is some inconsistency with the focus rectangle. But that's a different problem from the accelchar-behavior)

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: Accelerator keys
« Reply #19 on: August 05, 2014, 03:17:46 pm »
@rvk:
As far as I understand your latest description, this is the normal behavior for Windows since Windows 2000.

When you start a program:
-no mnemonic letters in the caption of the controls are underlined: you'll have to press 'Alt' to see them appeared,
-no focus rectangle is visible: you'll have to press a (tab,shift-tab,right,left,top,down) key first to see them.

As a consequence, Alt+letter does NOT make the focus rectangle visible.

Remember that making these tests within the IDE can lead to obtain false results.


**Edit**

Theoretically, the control which can focus and have the lowest taborder value in the group is focused when you start your program: just press the 'space' key to see it activated.

But:

-if the focus for the control is represented by a focus rectangle (checkbox for instance), you won't see it (see my former comment),

-a radiobutton is not focused if it's not checked. Which is also true for the tabulation process: only the checked radiobutton in the group can receive the focus with the tab/shift-tab keys. If none are selected, none can receive it. You'll have to click on it, or use the arrow keys (rigth,left,down,up), or access it true accelerator (which is not working for you).


Anyway, as you said, this is not the real problem concerning keyboard accelerators .

« Last Edit: August 05, 2014, 03:40:12 pm by ChrisF »

rvk

  • Hero Member
  • *****
  • Posts: 6162
Re: Accelerator keys
« Reply #20 on: August 05, 2014, 03:49:46 pm »
-no mnemonic letters in the caption of the controls are underlined: you'll have to press 'Alt' to see them appeared,
I do know that.

-no focus rectangle is visible: you'll have to press a (tab,shift-tab,right,left,top,down) key first to see them.
Yes, but pressing an Alt+key should ALSO focus that control with the focus rectangle. And that's not whats happening.

I made a test-program here with ActiveControl of the form1 at a TCheckbox and when starting the program (outside the ide) there is no visible focus-rectangle. (just as if the focus rectangle isn't initialized). All the Alt+key's don't give me the focus-rectangle. Only when pressing a tab the focus rectangle appears. After that the focus rectangle shifts according to the focused control.

How do i get a focus rectangle around my TCheckbox if that's the control i want my program to have control when starting that program? (I can't see what control has focus like this when starting a program and would always need to do a tab, an Alt+key doesn't work) (In the IDE it works correctly with the Find- and Print-dialog, there the Alt+key does give the correct focus rectangle directly) Even if i make a TEdit on my form my first control and press Alt+C (for the TCheckBox) the TCheckbox doesn't get the focus rectangle (but does get focus) which is very confusing. (other program's do provide direct focus rectangle)

But for now i'll leave it like it is until i can browse the bugtracker for similar problems (and it seems off-topic for this discussion  :D)

« Last Edit: August 05, 2014, 04:14:49 pm by rvk »

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: Accelerator keys
« Reply #21 on: August 05, 2014, 04:46:55 pm »
Well, it's not completely off-topic as it can help some other people to interpret more precisely their own results concerning the keyboard accelerators issues.

So, let's say just for the fun...

How do i get a focus rectangle around my TCheckbox if that's the control i want my program to have control when starting that program?

I'm afraid you'll have to force Windows to show the focus rectangle by yourself.

The LCL is hiding them by default (conformed to Windows standards). Extract of win32wsforms.pp, in TWin32WSCustomForm.CreateHandle:
Code: [Select]
  // Beginning with Windows 2000 the UI in an application may hide focus
  // rectangles and accelerator key indication. According to msdn we need to
  // initialize all root windows with this message
  if WindowsVersion >= wv2000 then
    Windows.SendMessage(Result, WM_CHANGEUISTATE,
      MakeWParam(UIS_INITIALIZE, UISF_HIDEFOCUS or UISF_HIDEACCEL), 0)


Here is one possible solution (see attached project). Extract:
Code: [Select]
uses
  Windows, Win32proc;

var
  ClearUI_HideFocus_Done: boolean = false;

procedure TForm1.FormActivate(Sender: TObject);
begin
  if not ClearUI_HideFocus_Done then
    begin
      if WindowsVersion >= wv2000 then
        SendMessage(Application.MainForm.Handle, WM_CHANGEUISTATE, MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), 0);
      ClearUI_HideFocus_Done := true;
    end;
end;



Eventually, you may also try to send an expected keyboard value to the form but I'm not sure it's working, and if it's working it'll change the control with the focus of course.

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: Accelerator keys
« Reply #22 on: August 05, 2014, 05:10:04 pm »
Summary OS / LCL widget type -> result :
Win XP          / Win32/Win64     -> None works and beeps
...
Since the Accelerators never worked in version of WIN/WIN up to and including XP, having duplicate targets for a single AccelChar, except for the really annoying beep, did not matter much.

Not for me.
 
As stated into my bug report (26562), on my own Windows XP configuration, IDE+LCL is working properly if the LCL has not been compiled with the '-O2' option.

The current version of Lazarus (i.e. 2.6.4) directly downloaded and installed without any modification is working properly. I'm not talking of the beep issue; this one is present for everybody and every Windows versions.

If I'm recompiling Lazarus with the '-O2' (let's say with the standard Optimized "IDE" profile, which includes this option) keyboard accelerators are no more working.

rvk

  • Hero Member
  • *****
  • Posts: 6162
Re: Accelerator keys
« Reply #23 on: August 05, 2014, 05:17:48 pm »
I'm afraid you'll have to force Windows to show the focus rectangle by yourself.
The LCL is hiding them by default (conformed to Windows standards).
Alright... That works.
When using the sendmessage in the FormActivate it directly shows the rectangle.
(Do you have a source for the fact Windows should hide the focus rectangle at startup of a program/dialog?)

I could accept (if the Windows-standard is to hide it) that the rectangle isn't visible when staring your program/dialog. But it should re-enable the focus rectangle when using the accelerator keys (the same behavior as for TAB). When entering a dialog you don't have a rectangle and if you press Alt+F for example a checkbox does get checked but you don't see what the focus is after that.

Even worse, with the problem of the TRadiobutton not being selected, when using the accelchar for a TRadiobutton you loose visible focus entirely (and you wouldn't even know that you could/need press space to activate it). I've never seen a dialog in other program where that happens. They always re-enable the focus-rectangle on accelerate keys.

But at least i know now how to fix half the focus rectangle problem (at startup).
Now we need to add the sendmessage-code to the accelchar-code, if it's confirmed that that should be default behavior.

Edit: Just tested this on Windows XP and there the selection of the TRadioButtons work correctly. Even the focus rectangle works correctly and works right away. (I did confirm compiling Lazarus with -O2 disables the shortkeys). But i found another problem. When compiling a program with Windows 7 and running it under Windows XP the accelerate keys don't work at all. (haven't tested it with the patches yet) Hurray for all the different versions of one OS  %)
« Last Edit: August 05, 2014, 06:35:49 pm by rvk »

BrunoK

  • Sr. Member
  • ****
  • Posts: 452
  • Retired programmer
Re: Accelerator keys
« Reply #24 on: August 05, 2014, 05:29:02 pm »
@howardpc
I may try to convert the 'aggressive' but working patches, to maybe an installable and more limited packet to handle the situation.
I don't know anything about what combination with Qt would be but am interested in the behaviour of any of the various :
OS         / Version                 / Lazarus        /LCL TYPE (new)  /  Desktop      / Keyboard
combinations. Desktop and Keyboard do not look not really important now.

@ChrisF on WinXP
The control in its WndProc first receives a LM_SYSCHAR that after not having (I think rightly, so other actions can override the default treatment) been processed in the concerned TWinControl descendent is translated somewhere (I don't remember where)  to a LN_SYSCHAR that is send (notified) to the WndProc. In the 'aggressive' patches I submitted, that initiates the scan (in TabOrder) of all potential targets. If the user application active form has effectively processed the LM_SYSCHAR it must set the Message.result to 1 (processed). >>> If Message.result is 0 <<<, then its the APPLICATION MENU that will look if it can do something with it and if Message.result is still 0 then Windows will beep.
In standard MS_win applications, it is first the ActiveControl that is asked to process the accel char and if unsuccessful the MAIN MENU. If you want to reach only the main menu you have to press and release Alt and the press the target char. That is the STANDARD.

If you are courageous and have time, make a backup of the lcl directory, load from
http://bugs.freepascal.org/view.php?id=26523
AccelChar.patch and modify the various lcl units. Then load and extract the udialogchar.zip to the lcl. It contains the unit udialogchar.pas unit that does the controlling of the hole operation. (Or do it in the reverse order and get a look at udialogchar.pas).
This works for me both with Lazarus 1.2.4 and 1.3, but I must recognize I work on an old XP duck so I wouldn't know how it works on the newer race machines.

It is 'aggressive' because it also handles Accel Char's on Tab's.Titles, TCustomGrid.Columns[].Title, TCustomGroup.Caption,
TLabel.Caption, TLabeledEdit.EditLabel.Caption. The logic applied is the same as GTK, just more aggressive.
Since I had problems with the RadioButton in groups, and when they are not the single target, I chose to set the focus to the active RadioButton in the group. When a TCustomTabControl has the focus or when in a TCustomGroup, pressing the AccelChar target WITHOUT Alt just sets the correct Tab or, for RadioButton, toggles it.

I'll see if I can do something installable as a package and submit it here, but suspect it will defeat the linker's dead code elimination.

As for the test form I used, see these three messy screen captures. Anything that has an Accel Char is reachable in a consistent way. These are not good examples to follow ...
Key to avoid : those requiring shift beaus it is easy to involuntarily switch the keyboard layout.

By the way, NoHideFocus.prj -> has no effect on my Win XP-Pro machine.


ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: Accelerator keys
« Reply #25 on: August 05, 2014, 07:46:30 pm »
@rvk:

Well, if I've correctly understood it, the standard is not to hide the focus rectangle (and the underlined letters too) by default, when starting.

In fact, it's : "when starting, do as it is configured for the current user". And by default, Windows configurations do include these 2 hidings.

This behavior can be change directly by the user in: Control Panel, under Appearance, Effects, option "Hide underlined letters for keyboard navigation until I press the Alt key".

Please note that this option is in fact common to the 2 sorts of hiding, though it's mentioning only one of them.

You can make a few tests by yourself by modifying this option. The LCL is quite respecting the user option (well, at least for me): hidden when starting if this option is checked, not hidden (both for underlined letters and focus rectangle) in the other case.


And this is quite conform to any Windows program behavior. Attached, one of my small sample programs I've quickly modified to see the effect of this option on a "standard" Windows program when it starts.

As this program is not using the LCL at all (it's using directly the Windows DialogBox API) and as it doesn't modify any UI state by itself, I consider it could be a sort of "reference" of what is expected for a "standard" Windows program concerning these 2 points (underlined letters + focus rectangle when starting).

The results are identical as those for the LCL.


However, I've noticed one difference between the LCL and the "direct" Windows DialogBox. When the option is checked (i.e. both hidden when starting), if you press the ALT key:

-for the LCL, only the underlined letters become visible; focus rectangle are not affected,
-for the Windows DialogBox, both of them become visible.

The second version is more logical, as you stated. But on the opposite, the first one is compatible with Delphi (at least with my own old version of Delphi). So, which one is better ? I guess the answer won't be the same one for everybody.


A few links concerning your question about the focus rectangle visibility (the second one is the more interesting one; I've already included it in one of my former posts):
http://msdn.microsoft.com/en-us/library/ms646335%28VS.85%29.aspx#_win32_UI_State
http://blogs.msdn.com/b/oldnewthing/archive/2005/05/03/414317.aspx



@BrunoK:

I couldn't remember the exact order of the different Windows events (and consecutive LCL processes) when a key is pressed; that's why I've not included any more precisions about them in my comment.

And you are quite right: if the focused control/form processes this keyboard event first, effectively it's quite possible in the message result (i.e. WM_SYSCHAR->LM_SYSCHAR) to tell Windows that the message has already been processed.

I'm just a bit surprised it's not already the case in the LCL: when a corresponding mnemonic (Alt+Char) has been found and is valid, I mean.


I've discovered lastly your own bug report; though I've not looked deeply into your code.

Briefly, what his the main idea ? LZDialogChar replaces the current DialogChar method: with a specific method (i.e. overidden) for each kind of control ?


Concerning your own NoHideFocus test (just another test result difference; great), which result do you get: no focus visible at all ? Never ?


**Edit1**
After having looked at the LCL source code again, it seems that the control mnemonics are processed in the DialogChar(var Message: TLMKey) method indeed. I guess this one is called after the menu handler, and that's why it's too late for the beep. Or ...


**Edit2**
@rvk:
So, apparently there is definitely something different between Windows XP and Windows 7 (and probably all 8.x) concerning this issue.
« Last Edit: August 05, 2014, 07:51:26 pm by ChrisF »

rvk

  • Hero Member
  • *****
  • Posts: 6162
Re: Accelerator keys
« Reply #26 on: August 05, 2014, 08:15:18 pm »
This behavior can be change directly by the user in: Control Panel, under Appearance, Effects, option "Hide underlined letters for keyboard navigation until I press the Alt key".
Yes... that works... (finaly found that option under the "Ease of access", "Make the keyboard easier to use"). It indeed determines the behavior and Lazarus correctly respects that setting.

But... from your link:
Quote
Underlines are hidden until you press the Alt key, and focus rectangles are hidden until you either press the Alt key or press the Tab key.
And that's where Lazarus goes wrong on Windows 7 (Windows XP it works correctly).
It does not re-enable the focus rectangle when pressing the Alt.

However, I've noticed one difference between the LCL and the "direct" Windows DialogBox. When the option is checked (i.e. both hidden when starting), if you press the ALT key:

-for the LCL, only the underlined letters become visible; focus rectangle are not affected,
-for the Windows DialogBox, both of them become visible.

The second version is more logical, as you stated. But on the opposite, the first one is compatible with Delphi (at least with my own old version of Delphi). So, which one is better ? I guess the answer won't be the same one for everybody.
Exactly what my point was. With Windows XP it behaves like the Windows DialogBox (both rectangle and underline become visible). I've never seen the other (LCL) behavior with Delphi (although i can't check right now). But every other Windows program (including Wordpad etc..) behaves like option 2 (Both become visible when Alt is pressed).

(haven't tested this on Windows 8 yet.)
« Last Edit: August 05, 2014, 08:17:28 pm by rvk »

ChrisF

  • Hero Member
  • *****
  • Posts: 542
Re: Accelerator keys
« Reply #27 on: August 06, 2014, 06:13:25 pm »
Quote
Underlines are hidden until you press the Alt key, and focus rectangles are hidden until you either press the Alt key or press the Tab key.
And that's where Lazarus goes wrong on Windows 7 (Windows XP it works correctly).
It does not re-enable the focus rectangle when pressing the Alt.

For me, it's not working neither with Windows XP: with my own Windows XP configuration, both Lazarus and Delphi don't make the focus rectangle visible when pressing Alt.

Which is quite comprehensive if you look at the concerned code.

Lazarus 2.4.2 (in win32callback.inc)
Code: [Select]
procedure UpdateUIState(CharCode: Word);
...
    case CharCode of
      VK_LEFT..VK_DOWN, VK_TAB:
        begin
          ParentForm := FindParentForm;
          if ParentForm <> nil then
            SendMessage(ParentForm.Handle, WM_CHANGEUISTATE, MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), 0);
        end;
      VK_MENU:
        begin
          ParentForm := FindParentForm;
          if ParentForm <> nil then
            SendMessage(ParentForm.Handle, WM_CHANGEUISTATE, MakeLong(UIS_CLEAR, UISF_HIDEACCEL), 0);
        end;

Delphi 7 (in Controls.pas) :
Code: [Select]
procedure TWinControl.UpdateUIState(CharCode: Word);
var
  Form: TCustomForm;
begin
  Form := GetParentForm(Self);
  if Assigned(Form) then
    case CharCode of
      VK_LEFT..VK_DOWN, VK_TAB:
        Form.Perform(WM_CHANGEUISTATE, MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), 0);
      VK_MENU:
        Form.Perform(WM_CHANGEUISTATE, MakeLong(UIS_CLEAR, UISF_HIDEACCEL), 0);
    end;
end;

Only one of the UI state is modified each time, depending of the keyboard key pressed.

As you said, standard Windows DialogBox proceeds differently with the 'ALT' key; but at least Lazarus is "conformed" with Delphi.

rvk

  • Hero Member
  • *****
  • Posts: 6162
Re: Accelerator keys
« Reply #28 on: August 07, 2014, 12:05:37 am »
As you said, standard Windows DialogBox proceeds differently with the 'ALT' key; but at least Lazarus is "conformed" with Delphi.
You're absolutely correct.
But is it a good thing Lazarus is following Delphi on this point and not the standard Windows behavior?.

If i look at code from VB they reset both IDEFOCUS and HIDEACCEL on the Alt-key.

I also found the following code from JVCL (in JvExForms.pas for TJvExCustomForm):
Code: [Select]
procedure TJvExCustomForm.CMDialogKey(var Msg: TCMDialogKey);
begin
  case Msg.CharCode of
    VK_LEFT..VK_DOWN, VK_TAB:
      SendMessage(Handle, WM_CHANGEUISTATE, MakeLong(UIS_CLEAR, UISF_HIDEFOCUS), 0);
    VK_MENU:
      SendMessage(Handle, WM_CHANGEUISTATE, MakeLong(UIS_CLEAR, UISF_HIDEFOCUS or UISF_HIDEACCEL), 0);
  end;
  inherited;
end;
So... yeah... TJvExCustomForm has implemented it, like i would expect
(with both resetting HIDEFOCUS and HIDEACCEL).

So it's just Delphi and Lazarus which behave differently.
(Like i said before, I've never seen a Windows-program behave like Delphi/Lazarus do on this point)

But at least we now know what the issue is (and if need be, i could correct this for myself).

Walmir

  • New Member
  • *
  • Posts: 39
Re: Accelerator keys
« Reply #29 on: August 12, 2014, 07:34:55 pm »
If I have a "File" menu with an "F" accelerator key in a main form and open a modal form with a button that has the same "F" accelerator, nothing happens when pressing ALT+F in tthe modal form
It seems that Lazarus is considering that a naccelerator clash, but it should not be so as long as I am in a modal form.
Someone else can confirm this behavior?

Lazarus 1.2.4
Windows 7

 

TinyPortal © 2005-2018