Regarding Accelerators
Posted: Fri Nov 28, 2014 9:04 pm
Hello,
I'll begin this post by saying that I've only been learning PureBasic for a few hours, but I've hit up against a problem which, for my coding purposes, may be a bit of a deal breaker. I'm developing on Windows 7. Here's what I want to create, to demonstrate this problem:
A user authentication window with the following controls:
A label and text field for a person's username;
A label and a text field for the person's password;
A Connect button; and
a Help button.
An extremely simple window. The labels for the controls, in my code, are as follows:
In the past, I've created GUIs using wxWidgets (wxPython), C#/WinForms, AutoHotkey and AutoIt. In all of those cases, creating a form with the labels stated above would exibhit the following behaviour in terms of keyboard access:
1. Pressing Alt+U or Alt+P would focus the Username or Password field, respectively;
2. Pressing Alt+C or Alt+H would activate the Connect or Help button, respectively; and
3. If the keyboard focus was placed on one of the buttons, Alt would not need to be added to these combinations (so a user could, for example, while focussed on the Connect button, press H to activate Help or U to jump to Username).
This is completely standard behaviour in most GUIs on Windows. No additional effort is required on the part of the programmer to make these standard features of native controls work. They just... do, regardless of the language or GUI toolkit in use. However, PureBasic seems not to allow this. Visually, the letters designated as accelerators in the control labels are underlined, and if the controls are queried using accessibility APIs, the accelerators are recognised. However, trying to use any of the expected functionality outlined above results in absolutely nothing. If I press Alt+U, Alt+P, Alt+C or Alt+H, I hear a default Windows ding sound, and if I focus on one of the buttons and then press U, P, C or H, nothing happens at all.
I can't use AddKeyboardShortcut in these cases, partly because it would add tons of unnecessary boilerplate to my code, but mainly because these keyboard-based interactions are standard. They are expected to work a certain way for the end user and, despite the fact that I am primarily a keyboard user myself, it would take lots of effort on my part to replicate them. Defining hotkeys for Alt+U, Alt+P etc and using SetActiveGadget is all very well and good, but it wouldn't address the problem of single-key shortcuts when a button is focussed rather than a text field. Plus, the problems would just keep growing as I added different types of controls to my interface, and it would quickly become unmanageable. Is the user focussed on a check box or button? If so, allow single-key shortcuts. If not, don't. But then I might add radio buttons to my interface, which from a keyboard user's perspective have a completely different set of rules and expected behaviour that I then have to deal with.
Sorry for the long post, and I'll be happy to clarrify any of my points. Keyboard access is a complex topic, but the majority of my users will be keyboard-only ones, so it needs to be done right. Windows gets it right in most cases, but it seems like PureBasic isn't allowing it to.
Here is my code. Please excuse the control spacing and layout - I'm a completely blind developer so if somebody decides to change the dimensions before running my sample, I'd appreciate knowing what you've changed.
I'll begin this post by saying that I've only been learning PureBasic for a few hours, but I've hit up against a problem which, for my coding purposes, may be a bit of a deal breaker. I'm developing on Windows 7. Here's what I want to create, to demonstrate this problem:
A user authentication window with the following controls:
A label and text field for a person's username;
A label and a text field for the person's password;
A Connect button; and
a Help button.
An extremely simple window. The labels for the controls, in my code, are as follows:
Code: Select all
"&Username"
"&Password"
"&Connect"
"&Help"
1. Pressing Alt+U or Alt+P would focus the Username or Password field, respectively;
2. Pressing Alt+C or Alt+H would activate the Connect or Help button, respectively; and
3. If the keyboard focus was placed on one of the buttons, Alt would not need to be added to these combinations (so a user could, for example, while focussed on the Connect button, press H to activate Help or U to jump to Username).
This is completely standard behaviour in most GUIs on Windows. No additional effort is required on the part of the programmer to make these standard features of native controls work. They just... do, regardless of the language or GUI toolkit in use. However, PureBasic seems not to allow this. Visually, the letters designated as accelerators in the control labels are underlined, and if the controls are queried using accessibility APIs, the accelerators are recognised. However, trying to use any of the expected functionality outlined above results in absolutely nothing. If I press Alt+U, Alt+P, Alt+C or Alt+H, I hear a default Windows ding sound, and if I focus on one of the buttons and then press U, P, C or H, nothing happens at all.
I can't use AddKeyboardShortcut in these cases, partly because it would add tons of unnecessary boilerplate to my code, but mainly because these keyboard-based interactions are standard. They are expected to work a certain way for the end user and, despite the fact that I am primarily a keyboard user myself, it would take lots of effort on my part to replicate them. Defining hotkeys for Alt+U, Alt+P etc and using SetActiveGadget is all very well and good, but it wouldn't address the problem of single-key shortcuts when a button is focussed rather than a text field. Plus, the problems would just keep growing as I added different types of controls to my interface, and it would quickly become unmanageable. Is the user focussed on a check box or button? If so, allow single-key shortcuts. If not, don't. But then I might add radio buttons to my interface, which from a keyboard user's perspective have a completely different set of rules and expected behaviour that I then have to deal with.
Sorry for the long post, and I'll be happy to clarrify any of my points. Keyboard access is a complex topic, but the majority of my users will be keyboard-only ones, so it needs to be done right. Windows gets it right in most cases, but it seems like PureBasic isn't allowing it to.
Here is my code. Please excuse the control spacing and layout - I'm a completely blind developer so if somebody decides to change the dimensions before running my sample, I'd appreciate knowing what you've changed.
Code: Select all
EnableExplicit
Enumeration
#WindowMain
#UsernameText
#UsernameField
#PasswordText
#PasswordField
#ConnectButton
#HelpButton
EndEnumeration
Procedure ConnectButtonHandler()
MessageRequester("Connect", "The Connect button was pressed.")
EndProcedure
Procedure HelpButtonHandler()
MessageRequester("Help", "The Help button was pressed.")
EndProcedure
Procedure WindowCreate()
Protected Flags
Flags = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget| #PB_Window_TitleBar
OpenWindow(#WindowMain, 50, 50, 450, 400, "Accelerator Test", Flags)
TextGadget(#UsernameText, 5, 10, 10, 10, "&Username")
StringGadget(#UsernameField, 10, 10, 10, 10, "")
TextGadget(#PasswordText, 5, 10, 10, 10, "&Password")
StringGadget(#PasswordField, 10, 10, 10, 10, "", #PB_String_Password)
ButtonGadget(#ConnectButton, 10, 10, 10, 10, "&Connect")
BindGadgetEvent(#ConnectButton, @ConnectButtonHandler())
ButtonGadget(#HelpButton, 30, 10, 10, 10, "&Help")
BindGadgetEvent(#HelpButton, @HelpButtonHandler())
SetActiveGadget(#UsernameField)
EndProcedure
Procedure WindowDestroy()
CloseWindow(#WindowMain)
EndProcedure
Define.l Event, EventWindow, EventGadget, EventType, EventMenu
WindowCreate()
Repeat
Event = WaitWindowEvent()
EventWindow = EventWindow()
EventGadget = EventGadget()
EventType = EventType()
Select Event
Case #PB_Event_CloseWindow
If EventWindow = #WindowMain
WindowDestroy()
Break
EndIf
EndSelect
Forever