Avoid action shortcuts taking precedence over standard Windows hotkeys
In Windows, certain controls have particular standard keyboard behaviour. For example, in edit fields, pressing Control+Left/Right Arrow navigates by word, Shift+Left/Right selects text, Shift+Home selects to the beginning of the text, etc. There are quite a lot of these, spanning across more controls than just text fields.
Currently, if you define a walk.Action with a shortcut of, say, Ctrl+Left, set keyboard focus to a walk.TextEdit or walk.LineEdit and press the hotkey, the action is triggered instead and the text control doesn't get a look at the keystroke. Therefore, the user is unable to move by word. Or to put it another way, action shortcuts take precedence over everything else. I've experienced this before when using the wxWidgets framework, and wrote a detailed issue description but never got anywhere with a solution.
I'm developing an application particularly for blind, keyboard-only users. Do you have any idea how Walk or my application could be adapted to allow the focused widget to have a shot at processing keystrokes before the shortcut system?
Many thanks in advance, really enjoying using your library to create fast GUI apps! :)
As an aditional note, if I define an action with a shortcut which includes walk.ModControl along with a letter from walk.KeyB to walk.KeyZ, set keyboard focus to a walk.LineEdit widget and then press the shortcut, the action is triggered but Windows plays the default beep sound, suggesting an error in keyboard processing. Using a key like walk.Key1 or walk.KeyF1 for the shortcut doesn't cause the default beep.
With the code below I get the action executed before the focused LineEdit or TextEdit do their usual thing.
package main
import (
"github.com/lxn/walk"
. "github.com/lxn/walk/declarative"
)
func main() {
var te *walk.TextEdit
MainWindow{
MenuItems: []MenuItem{
Menu{
Text: "Edit",
Items: []MenuItem{
Action{
Text: "Do It",
Shortcut: Shortcut{Key: walk.KeyLeft, Modifiers: walk.ModControl},
OnTriggered: func(){
te.AppendText("nom")
},
},
},
},
},
MinSize: Size{400, 300},
Layout: VBox{},
Children: []Widget{
LineEdit{},
TextEdit{
AssignTo: &te,
VScroll: true,
},
},
}.Run()
}
Similar code using C#/WinForms only performs the menu item's action, as you have described.
For some reason, I wasn't able to make TranslateAccelerator and friends play nice with walk and so had to come up with some workaround.
Will have to look at this some more, but not sure when I will get to it.
I'd ideally like to suspend accelerator processing completely inside certain controls, because I think there are a lot of corner cases here and it would be easy to forget some/introduce nonstandard behaviour. When the user presses a keystroke strictly to navigate within some text, it's a separate intent from wanting to trigger the associated action. Consider, for example, an app like Winamp or foobar2000 which allows for the use of single-letter shortcut keys but suspends processing for them inside text fields so the user can type. Perhaps some sort of IgnoreAccelerators bool flag on a widget?
Any thoughts on the Windows default beep?
re: system bell, not sure if related, but I was getting the system bell every time someone hit enter in my lineedit ... was driving me nuts. Seems you need to swallow it to prevent it ... added this to WndProc of LineEdit. Hopefully this doesn't break other stuff?
case win.WM_CHAR:
// cryptonote-social: Stop the damn system bell from ringing on <enter>
if wParam == win.VK_RETURN {
return 0
}