LCL Key Handling/ja
キーを押し下げた (KeyDown)
When the widgetset receives a key press it must act as follows. Before letting the "native" widget handle the key, send CN_KEYDOWN/CN_SYSKEYDOWN to the LCL (CN_SYSKEYDOWN when alt key is down), which calls DoKeyDownBeforeInterface consisting of:
- call Application.NotifyKeyDownBeforeHandler (invokes before handlers)
- get parent form, if it has keypreview, call it's DoKeyDownBeforeInterface
- let the associated dragobject handle the key
- call KeyDownBeforeInterface (if control does not have csNoStdEvents in ControlStyle):
- call KeyDown:
- call OnKeyDown handler if any
- call KeyDown:
When unhandled, that is, Message.Result = 0, it lets the widget handle the key, and if the widget has not done anything useful, then send a LM_KEYDOWN/LM_SYSKEYDOWN message to the LCL, which calls DoRemainingKeyDown consisting of:
- if a popupmenu is assigned, check it for shortcuts (whether it is popped up or not)
- get parent form, let it handle possible shortcut (TCustomForm.IsShortcut):
- if form has OnShortcut event assigned, call it
- if form has Menu assigned, check it for shortcuts:
- iterate through all menu items for this menu, check shortcuts, ".Click" the item
- set the menu's ShortcutHandled property to false in the menu item's OnClick handler, if you did not handle the shortcut and want to let the key processing continue
- check the action lists for shortcuts, .Execute matching actions
- let the application handle a shortcut (Application.IsShortcut):
- if application has OnShortcut assigned, call it
- if there is a modal form active, let it handle a shortcut (see above, TCustomForm.IsShortcut)
- else if there is a focused form (Screen.ActiveCustomForm), let it handle a shortcut
- else if there is a main form (Application.MainForm), let it handle a shortcut
- if there is a Parent, iteratively call Parent.ChildKey to handle key message
- use it to handle key shortcuts in a certain "area", for example a panel
- TWinControl will call it's Parent's ChildKey; that's the "iteratively"
- call ControlKeyDown, which in TWinControl, calls Application.ControlKeyDown:
- handle tab navigation for controls
- if your custom control does something special with tab, override and inhibit, for example TCustomMemo
- call KeyDownAfterInterface; TWinControl does nothing here
- let Application call KeyDownAfter handlers
Note that result (returning 1 or 0 in Message.Result) matters sometimes: windows for example will only send a WM_CHAR message for a key when a WM_KEYDOWN message that key has returned 0.
キーを押している, キャラクタが送られている(KeyPress)
The widgetset can either send CN_CHAR message, or call the IntfUtf8KeyPress method. CN_CHAR does not support UTF-8 characters, so that is why a IntfUtf8KeyPress exists. CN_CHAR handling consists of:
- if widgetset (interface) does not send utf8 key presses, then call IntfUtf8KeyPress
- call DoKeyPress:
- get parent form, and if it has KeyPreview call it's DoKeyPress
- call KeyPress (if control does not have csNoStdEvents in ControlStyle):
- call OnKeyPress handler if any
IntfUtf8KeyPress (DoUtf8KeyPress) handling consists of:
- get parent form, and if it has KeyPreview call it's DoUtf8KeyPress
- call Utf8KeyPress (if control does not have csNoStdEvents in ControlStyle):
- call OnUtf8KeyPress handler if any
When unhandled, that is, Message.Result = 0, it lets the widget handle the key, and if the widget has not done anything useful, then send a LM_CHAR/LM_SYSCHAR message to the LCL, which calls SendDialogChar consisting of:
- get parent form and if found call it's .DialogChar:
- TWinControl broadcasts DialogChar to all it's children
- use it to implement accelerator shortcuts for controls "near" (on the same form) as the focused control
- example: TCustomLabel uses it to Focus the assigned .FocusControl when alt+accelerator is pressed
- TWinControl broadcasts DialogChar to all it's children
Releasing the key (KeyUp)
Releasing a key is very much, in the order of events happening, alike pressing a key, but some functions are missing. Again the widgetset will send a CN_KEYUP/CN_SYSKEYUP to the LCL before letting the widget handle the key, which will call DoKeyUpBeforeInterface consisting of:
- get parent form, if it has keypreview, call it's DoKeyUpBeforeInterface
- let the associated dragobject handle the key
- call KeyUpBeforeInterface (if control does not have csNoStdEvents in ControlStyle):
- call KeyUp:
- call OnKeyUp handler if any
- call KeyUp:
When unhandled, that is, Message.Result = 0, it lets the widget handle the key, and if the widget has not done anything useful, then send a LM_KEYUP/LM_SYSKEYUP message to the LCL, which calls DoRemainingKeyUp consisting of:
- call ControlKeyUp, which in TWinControl, calls Application.ControlKeyDown:
- handle Enter and Escape keys for forms
- if your custom control does something special with enter and escape, override and inhibit
- call KeyUpAfterInterface; TWinControl does nothing here