WM CHAR
This message is sent when an operator presses a key.
Syntax
param1 USHORT fsflags /* Keyboard control codes. */ UCHAR ucrepeat /* Repeat count. */ UCHAR ucscancode /* Hardware scan code. */ param2 USHORT usch /* Character code. */ USHORT usvk /* Virtual key codes. */
- in Frame Controls
This message is sent by controls to their owner window if they do not process the key stroke themselves. It is the most common means by which the input focus is switched around the various controls in a dialog box.
Parameters
- fsflags (USHORT) - Input
- Keyboard control codes.
- KC_CHAR
- Indicates that usch value is valid.
- KC_SCANCODE
- Indicates that ucscancode is valid. Generally, this is set in all WM_CHAR messages generated from actual operator input. However, if the message has been generated by an application that has issued the WinSetHook function to filter keystrokes, or posted to the application queue, this may not be set.
- KC_VIRTUALKEY
- Indicates that usvk is valid. Normally usvk should be given precedence when processing the message. Note: For those using hooks, when this bit is set, KC_SCANCODE should usually be set as well.
- KC_KEYUP
- The event is a key-up transition; otherwise it is a down transition.
- KC_PREVDOWN
- The key has been previously down; otherwise it has been previously up.
- KC_DEADKEY
- The character code is a dead key. The application is responsible for displaying the glyph for the dead key without advancing the cursor.
- KC_COMPOSITE
- The character code is formed by combining the current key with the previous dead key.
- KC_INVALIDCOMP
- The character code is not a valid combination with the preceding dead key. The application is responsible for advancing the cursor past the dead-key glyph and then, if the current character is not a space, sounding the alarm and displaying the new character code.
- KC_LONEKEY
- Indicates if the key is pressed and released without any other keys being pressed or released between the time the key goes down and up.
- KC_SHIFT
- The SHIFT state is active when key press or release occurred.
- KC_ALT
- The ALT state is active when key press or release occurred.
- KC_CTRL
- The CTRL state was active when key press or release occurred.
- ucrepeat (UCHAR) - Input
- Repeat count.
- ucscancode (UCHAR) - Input
- Hardware scan code. A keyboard-generated value that identifies the keyboard event. This is the raw scan code, not the translated scan code.
- usch (USHORT) - Input
- Character code. The character value translation of the keyboard event resulting from the current code page that would apply if the CTRL or ALT keys were not depressed.
- usvk (USHORT) - Input
- Virtual key codes. A virtual key value translation of the keyboard event resulting from the virtual key code table. The low-order byte contains the vk value, and the high-order byte is always set to zero by the standard translate table. This value applies if fsflags does not contain KC_VIRTUALKEY.
Returns
- rc (BOOL) - returns
- Processed indicator.
- TRUE
- Message processed
- FALSE
- Message ignored.
Remarks
This message is posted to the queue associated with the window that has the focus.
The set of keys that causes a WM_CHAR message is device-dependent.
When this message is processed, precedence should normally be given to a valid virtual key if there is one contained in the message.
There are several instances when a window procedure may receive this message with the KC_KEYUP bit set, although it did not receive this message for the down transition of the key.
For example,
- The down transition of the key is translated by the function WinTranslateAccel, into a WM_COMMAND, WM_SYSCOMMAND, WM_HELP, or a WM_NULL message.
- The key down causes the input focus to change (tab to another window, dismiss a dialog, exit a program, and so on).
- Some other event happens that changes the focus between the time that the key is pressed down and the time that it is released.
Applications should normally only process WM_CHAR messages that do not have the KC_KEYUP bit set.
Except for the special instance where the LONEKEY flag is set on an accelerator key definition, all translations are done on the down stroke of the character.
When the current character is a double-byte character then param2 contains both bytes of the double-byte character. These bytes are in the order CHAR1FROMMP, CHAR2FROMMP. When the current character is a single-byte character, CHAR2FROMMP contains 0.
in Circular Slider Controls
The slider control window procedure responds to this message by sending it to its owner if it has not processed the key stroke.
This is the most common means by which the input focus is switched around the various controls in a dialog box.
The keystrokes processed by a circular slider control are:
Keystroke | Action |
---|---|
Left Arrow | Moves the slider arm left one increment. |
Right Arrow | Moves the slider arm right one increment. |
- A circular slider control only processes left and right arrow keystrokes. These keys move the slider arm one increment to the left or right.
in Entry Fields
The entry field control window procedure responds to this message by sending it to its owner if it has not processed the keystroke. This is the most common means by which the input focus is switched around the various controls in a dialog box.
Unlike other controls, the usvk field of the message WM_CHAR takes precedence over other fields only when the Shift key is pressed.
If this message contains a valid usch field of the message WM_CHAR, that character is entered into the text in insert or overtype mode.
The keystrokes processed by an entry field control are:
Keystroke | Action |
---|---|
Left arrow | Move the cursor one character to the left. |
Right arrow | Move the cursor one character to the right. |
Shift+Left arrow | Extend the selection by one character to the left. |
Shift+Right arrow | Extend the selection by one character to the right. |
Home | Move the cursor to the beginning of the text. |
End | Move the cursor to the end of the text. |
Backspace | Delete the character to the left of the cursor. |
Delete | When the selection is an insertion point, delete the character to the right of the cursor, otherwise delete the current selection, but do not put it in the clipboard. |
Shift+Del | Cut the current selection to the clipboard. |
Shift+Ins | Replace the current selection with the text contents from the clipboard. |
Ctrl+Del | Delete to the end of the field. |
Ctrl+Ins | Copy the current selection to the clipboard. |
If the control contains more text than can be shown, the actions defined above that move the cursor cause the text to be scrolled. The amount of scrolling varies from key to key, and the position of the text within the control varies for the same cursor position.
in List Boxes
The list box control window procedure responds to this message by sending it to its owner if it has not processed the key stroke. This is the most common means by which the input focus is switched around the various controls in a dialog box.
The key strokes processed by a list box control are:
Keystroke | Action |
---|---|
Down Arrow | Moves the selection down one item, scrolling the list box by one item, if necessary, to make the next item visible. When the selection reaches the bottom, the Down Arrow has no effect. |
Up Arrow | Moves the selection up one item, scrolling the list box by one item, if necessary, to make the previous item visible. When the selection reaches the top, the Up Arrow has no effect. |
Page Down | Moves the selection down one page, scrolling the list box by the number of items visible in the list box. For example, if the list box displays seven items and item 1 is selected and positioned at the top of the list box, pressing the Page Down key causes item 8 to be selected and displayed at the top of the list box. Pressing Page Down when the last item is selected has no effect. |
Page Up | Moves the selection up one page, scrolling the list box by the number of items visible in the list box. For example, if the list box displays seven items and item 8 is selected and positioned at the top of the list box, pressing the Page Up key causes item 1 to be selected and displayed at the top of the list box. Pressing the Page Up key when the first item is selected has no effect. |
in Multiline Entry Fields
The behavior of the MLE, when typing, depends on whether it is in insert or overtype mode, and whether the selection is empty or not. The selection is defined to be empty when the cursor point is equal to the anchor point.
When a character is typed, it replaces the current selection. If the selection is empty, the character is viewed as replacing nothing, so the character is effectively inserted into the text. If one or more characters are selected, those characters are deleted from the text and replaced by the typed character.
If the MLE is in insert mode, the cursor and anchor points are moved to immediately follow the newly typed character.
If the MLE is in overtype mode, the cursor is moved to immediately follow the newly typed character. If there is no character after the cursor (the new character is at the end of the text) or if the character after the cursor is a line-break character, the anchor is set to be equal to the cursor point. In any other case, the anchor is extended one character past the cursor point, defining the next character as the current selection.
If the typing causes the cursor to go off the screen in any direction, the display is automatically scrolled. If word-wrap is on, text continues on a new line, otherwise, the screen is scrolled horizontally.
Scrolling of the text in the window is independent of cursor movement. The cursor and selection remain unaltered at the same location within the text during all scrolling but the converse is not true. Any movement of the cursor causes auto-scrolling, if necessary, to ensure that the text location of the cursor is visible within the window.
Tabs
Tabs are represented as a single character in the text model, and are displayed as enough white-space to reach the next tab stop. Tab stops are set at pel intervals, starting with zero and occurring every n pels, where n is a value set by the MLM_SETTABSTOP message, and defaulting to eight times the average character width of the system font. When a tab is drawn, it uses the number of pels defined by the following formula: $$pelWidth = pelTab - (pelDraw \mod pelTab))$$ where $pelTab$ is the tab interval, in pels, and $pelDraw$ is the pel at which drawing is to begin.
Return
Return (ASCII newline) causes a hard line-break, and the following text begins on a new line. A line-break character is inserted in the text, which is drawn as a few pels of white-space (for selection purposes).
Keystroke commands
For all the following keys, unless otherwise noted, the display is scrolled, if necessary, to keep the cursor point visible. Where noted, the cursor setting behaves differently in insert mode than in overtype mode. This is subject to the boundary conditions noted above.
Keystroke | Action |
---|---|
Del | Causes the contents of the selection region to be deleted. If the selection region contains no text, it causes the character to the right of the cursor to be deleted. |
Shift+Del | Causes the contents of the selection region to be cut to the clipboard. |
Insert | Toggles between insert and overtype mode. The MLE ignores the Insert key when it occurs without a modifier. |
Shift+Ins | Causes the contents of the clipboard to replace the selection region. |
Ctrl+Ins | Causes the selection region to be copied to the clipboard. The selection region is not otherwise affected. |
Backspace | Functions similar to Del. If the selection is not empty, Backspace deletes the selection. If the selection is empty, Backspace deletes the character to the left of the cursor point. If the MLE is in overtype mode, the anchor point is set, and the cursor point is moved to be one character previous in the text. If no such character exists (because the anchor is set to the beginning of the text) the cursor is set to the anchor point. If the MLE is in insert mode, the cursor and anchor points are set, as defined at the start of this chapter. |
Down Arrow | Sets the cursor point to the closest insertion point on the following line, then sets the anchor point to the cursor point (insertion mode) or one character following (overtype mode). |
Shift+Down Arrow | Causes the cursor point to be moved to the closest insertion point on the following line. The anchor point does not move. |
Up Arrow | Sets the cursor point to the closest insertion point on the preceding line, then sets the anchor point to the cursor point (insert mode) or one character following (overtype mode). |
Shift+Up | Sets the cursor point to the closest insertion point on the preceding line. The anchor point is not moved. |
Right Arrow | Sets the cursor point to the insertion point one character following the cursor point. The anchor point is set to the cursor point (insert mode) or one character following (overtype mode). |
Shift+Right | Causes the cursor point to be set to the insertion point immediately following the previous cursor point. The anchor point is not moved. |
Left or Shift+Left | Work analogously. |
Ctrl+Right | Moves the cursor point to the insertion point immediately preceding the next word in the text including trailing spaces, and sets the anchor point to be equal to (insert mode) or one character following (overtype mode) the cursor point. The EOL (hard line-break) and tab characters are treated as words. |
Ctrl+Shift+Right | Moves only the cursor point in the same way as Ctrl+Right, but leaves the anchor point unmoved. |
Ctrl+Left | Moves the cursor point to the preceding insertion point at the beginning of a word, and sets the anchor point to be equal to (insert mode) or one character following (overtype mode) the cursor point. The EOL (hard line-break) and tab characters are treated as words. |
Ctrl+Shift+Left | Moves only the cursor point in the same way as Ctrl+Left but leaves the anchor point unmoved. |
PageDown or PageUp | Cause the display to be scrolled one screen at a time in either direction. This behavior is the same as would be encountered during a page-down or page-up caused by the scroll-bar. |
Ctrl+PageDown or Ctrl+PageUp | Cause the display to be scrolled one screen at a time to the right or left respectively. This behavior is the same as would be encountered during a page-right or page-left caused by the scroll-bar. |
Home | Sets the cursor point to the insertion point at the beginning of the line containing the cursor point, and sets the anchor point equal to (insert mode) or one character following (overtype mode). |
Shift+Home | Moves the cursor point to the insertion point at the beginning of the line. The anchor point is not moved. |
End | Sets the anchor point to the insertion point at the end of the line containing the cursor point. If the last character on the line is a line-break character, the anchor is positioned just before it. The cursor is set equal to (insert mode) or one character previous to (overtype mode) the anchor. |
Shift+End | Moves the cursor point to the insertion point at the end of the line, as above. The anchor point is not moved. |
Ctrl+Home | Moves the cursor point to the insertion point at the beginning of the document. The anchor point is set equal to (insert mode) or one character following it (overtype mode). |
Ctrl+End | Moves the anchor point to the insertion point at the end of the document. The cursor point is set to be equal to the anchor point (insert mode) or one character preceding it (overtype mode). |
Ctrl+Shift+Home | Moves the cursor point in the same way as Ctrl+Home, but leaves the anchor point unmoved. |
Ctrl+Shift+End | Moves the cursor point in the same way as Ctrl+End, but leaves the anchor point unmoved. |
in Notebook Controls
If the application page window has the focus (for example, the cursor is on a control within the top page dialog), the notebook handles the following keyboard interaction:
- Alt+Up Arrow: Sets the focus to the notebook window.
If the notebook control has the focus (for example, the cursor is on the major tab, minor tab or page turning button), the notebook handles the following keyboard interactions:
Keystroke | Action |
---|---|
Alt+Down Arrow | Sets the focus to the application page window. |
Tab | Moves the selection cursor to the next position or control. |
Shift+Tab | Moves the selection cursor to the previous position or control. |
Down Arrow or Right Arrow | Moves the selection cursor to the next major or minor tab. If either of these keys is pressed while the selection cursor is on a major tab, the cursor moves to the next major tab. If either of these keys is pressed while the selection cursor is on a minor tab, the cursor moves to the next minor tab. If the next tab is not visible, the tabs are scrolled to bring the next tab into view. If the end of the tabs is reached, scrolling ends. |
Up Arrow or Left Arrow | Moves the selection cursor to the previous major or minor tab. If either of these keys is pressed while the selection cursor is on a major tab, the cursor moves to the previous major tab. If either of these keys is pressed while the selection cursor is on a minor tab, the cursor moves to the previous minor tab. If the previous tab is not visible, the tabs are scrolled to bring the previous tab into view. If the beginning of the tabs is reached, scrolling ends. |
Enter or Spacebar | The cursored tab page becomes the top page of the notebook. |
Mnemonics | Brings the page whose tab contains the mnemonic character to the top of the notebook whenever the user presses the mnemonic key. Mnemonic key definition is provided by using the BKM_SETTABTEXT message. Coding a mnemonic character (~) before a text character in the BKM_SETTABTEXT message causes that character to be underlined in the tab's text string and activates it as a mnemonic selection character. The mnemonic key pressing is not case-sensitive, so the user can type the mnemonic character in either upper or lower case. |
PgDn or Alt+PgDn | Brings the next page to the top of the notebook and sets the selection cursor on the associated tab, if there is one. |
PgUp or Alt+PgUp | Brings the previous page to the top of the notebook and sets the selection cursor on the associated tab, if there is one. |
Home | Brings the first page of the notebook to the top and sets the selection cursor on the associated tab, if there is one. |
End | Brings the last page of the notebook to the top and sets the selection cursor on the associated tab, if there is one. |
in Value Set Controls
The value set control window procedure responds to this message by sending it to its owner if it has not processed the key stroke. This is the most common means by which the focus is switched from one control to another in a value set window.
The keystrokes processed by a value set control are:
Key Name | Action Performed |
---|---|
Down Arrow | Moves the selection cursor down one item. When the selection cursor reaches the bottom, the Down Arrow has no effect. |
Up Arrow | Moves the selection cursor up one item. When the selection cursor reaches the top, the Up Arrow has no effect. |
Left Arrow | Moves the selection cursor left one item. When the selection cursor reaches the leftmost column, the Left Arrow has no effect. |
Right Arrow | Moves the selection cursor right one item. When the selection cursor reaches the rightmost column, the Right Arrow has no effect. |
Home | Moves the selection cursor to the leftmost column of the value set control (NLS dependent). Pressing the Home key when the leftmost column is selected has no effect. The row index does not change. |
End | Moves the selection cursor to the rightmost column of the value set control (NLS dependent). Pressing the End key when the rightmost column is selected has no effect. The row index does not change. |
PgDn | Moves the selection cursor to the bottom row of the value set control. Pressing the Page Down key when the bottom row is selected has no effect. The column index does not change. |
PgUp | Moves the selection cursor to the top row of the value set control. Pressing the Page Up key when the top row is selected has no effect. The column index does not change. |
Ctrl+Home | Moves the selection cursor to the item in the top row and leftmost column of the value set control (NLS dependent). Pressing the Ctrl+Home keys when the top row and leftmost column is selected has no effect. |
Ctrl+End | Moves the selection cursor to the bottom row and rightmost column of the value set control (NLS dependent). Pressing the Ctrl+End keys when the bottom row and rightmost column is selected has no effect. |
Enter | Sends a VN_ENTER notification code to the owner of the value set with the row and column indices of the selected item. |
(Mnemonic) | If the VS_TEXT style bit is set for the value set, any mnemonics specified can be used to select an item. |
Default Processing
The default window procedure sends the message to the owner window if it exists, otherwise it takes no action on this message other than to set rc to FALSE.
- Default Dialogs
If KC_CHAR is the mnemonic for a button that already has the focus, a BM_CLICK is sent to that button and rc is set to TRUE. If the button does not have the focus, it receives the focus and rc is set to TRUE.
If usvk contains the value VK_TAB, the focus is set to the next tab item in the dialog. rc is set to TRUE.
If usvk contains the value VK_BACKTAB, the focus is set to the previous tab item in the dialog. rc is set to TRUE.
If usvk contains the value VK_LEFT or VK_UP, the focus is set to the previous item in the group. rc is set to TRUE.
If usvk contains the value VK_RIGHT or VK_BOTTOM, the focus is set to the next item in the group. rc is set to TRUE.
If usvk contains the value VK_ENTER or VK_NEWLINE, and a push button has the focus, a BM_CLICK is sent to the button and rc is set to TRUE. If another control in the dialog has the focus the dialog is searched for a push button with style BS_DEFAULT. If a push button of this style is found, a BM_CLICK is sent to that button and rc is set to TRUE.
If usvk contains the value VK_ESC, WM_COMMAND is posted, with ussource is set to CMDSRC_PUSHBUTTON and uscmd is set to DID_CANCEL. rc is set to TRUE.
In other instances, if an owner exists the message is sent to the owner, otherwise rc is set to FALSE.
- in Entry Fields
The default window procedure sends the message to the owner window if it exists, otherwise it takes no action on this message other than to set rc to FALSE.
- in Frame Controls
The frame control window procedure responds to this message as follows:
- If the message contains a valid VK_ value, that value is processed before any valid character in the message.
- If the character matches a mnemonic in the text of a button or static control child window, the focus is set to that window.
- If the character is Tab or Backtab, the focus is set to the next or previous tabstop window.
- If the character is Up or Left Arrow, the focus is set to the previous item in the group.
- If the character is Down or Right Arrow, the focus is set to the next item in the group.
- If the Enter key is pressed, a WM_COMMAND message is posted to itself, containing the identity of the button with the focus, or, if none, the identity of the default push button.
- If the Escape key is pressed, a WM_COMMAND message is posted to itself with the command value DID_CANCEL.
- in List Boxes
The default window procedure takes no action on this message, other than to set rc to FALSE.
- in Multiline Entry Fields
The default window procedure takes no action on this message, other than to set rc to FALSE.
- in Slider Controls
The slider control window procedure responds to this message by sending it to its owner if it has not processed the key stroke. This is the most common means by which the input focus is switched around the various controls in a dialog box.
The keystrokes processed by a linear slider control are:
- Down Arrow: Moves the slider arm down one increment. When the slider arm reaches the bottom of the slider shaft or when a horizontal slider is being used, the Down Arrow key has no effect.
- Up Arrow: Moves the slider arm up one increment. When the slider arm reaches the top of the slider shaft or when a horizontal slider is being used, the Up Arrow key has no effect.
- Left Arrow: Moves the slider arm left one increment. When the slider arm reaches the leftmost edge or when a vertical slider is being used, the Left Arrow key has no effect.
- Right Arrow: Moves the slider arm right one increment. When the slider arm reaches the rightmost edge or when a vertical slider is being used, the Right Arrow key has no effect.
- Shift+Down Arrow: Moves the slider arm to the next detent below the current position. If there are no more detents or if a horizontal slider is being used, the Shift+Down Arrow key combination has no effect.
- Shift+Up Arrow: Moves the slider arm to the next detent above the current position. If there are no more detents or if a horizontal slider is being used, the Shift+Up Arrow key combination has no effect.
- Shift+Left Arrow: Moves the slider arm to the next detent left of the current position. If there are no more detents or if a vertical slider is being used, the Shift+Left Arrow key combination has no effect.
- Shift+Right Arrow: Moves the slider arm to the next detent right of the current position. If there are no more detents or if a vertical slider is being used, the Shift+Right Arrow key combination has no effect.
- Home, Ctrl+Home: Moves the slider arm to the home position of the slider. Pressing the Home key or the Ctrl+Home key combination when the slider arm is at the home position has no effect. The default home position for a slider is the leftmost edge for horizontal sliders and the bottom edge for vertical sliders.
- End, Ctrl+End: Moves the slider arm to the end position of the slider. Pressing the End key or the Ctrl+End key combination when the slider arm is at the end position has no effect. The default end position for a slider is the rightmost edge for horizontal sliders and the top edge for vertical sliders.
A circular slider control only processes left and right arrow keystrokes. These keys move the slider arm one increment to the left or right.
Related Messages
- WM_CHAR (Default Dialogs)
- WM_CHAR (in Entry Fields)
- WM_CHAR (in Frame Controls)
- WM_CHAR (in List Boxes)
- WM_CHAR (in Multiline Entry Fields)
Examples
This example uses the CHARMSG macro to process a WM_CHAR message. It first uses the macro to determine if a key was released. It then uses the macro to generate a switch statement based on the character received.
MRESULT CALLBACK GenericWndProc(hwnd, usMessage, mp1, mp2) HWND hwnd; USHORT usMessage; MPARAM mp1; MPARAM mp2; { switch (usMessage) { case WM_CHAR: if (CHARMSG(&usMessage)->fs & KC_KEYUP) { switch (CHARMSG(&usMessage)->chr) {