Jump to content

PMGuide - Mouse and Keyboard Input

From EDM2
Revision as of 00:14, 2 May 2025 by Ak120 (talk | contribs)

An OS/2 Presentation Manager application can accept input from both a mouse (or other pointing device) and the keyboard. This chapter explains how these input events should be received and processed.

About Mouse and Keyboard Input

Only one window at a time can receive keyboard input, and only one window at a time can receive mouse input; but they do not have to be the same window. All keyboard input goes to the window with the input focus, and, normally, all mouse input goes to the window under the mouse pointer.

System Message Queue

The operating system routes all keystrokes and mouse input to the system message queue, converting these input events into messages, and posts them, one at a time, to the proper application-defined message queues. An application retrieves messages from its queue and dispatches them to the appropriate window procedures, which process the messages.

Mouse and keyboard input events in the system message queue are strictly ordered so that a new event cannot be processed until all previous events are fully processed: the system cannot determine the destination window of an input event until then. For example, if a user types a command in one window, clicks the mouse to activate another window, then types a command in the second window, the destination of the second command depends on how the application handles the mouse click. The second command would go to the second window only if that window became active as a result of the mouse click.

It is important for an application to process all messages quickly to avoid slowing user interaction with the system. A message must be responded to immediately in the current thread, but the processing it initiates should be done asynchronously in another thread that has no windows in the desktop tree.

The OS/2 operating system can display multiple windows belonging to several applications at the same time. To manage input among these windows, the system uses the concepts of window activation and keyboard focus.

Window Activation

Although the operating system can display windows from many different applications simultaneously during a PM session, the user can interact with only one application at a time-the active application. The other applications continue to run, but they cannot receive user input until they become active.

To enable the user to easily identify the active application, the system activates all frames in the tree between HWND_DESKTOP and the window with input focus. That is, the system positions the active frame window above all other top-level windows on the screen. If the active window is a standard frame window, the window's title bar and sizing border are highlighted.

The user can control which application is active by clicking on a window or by pressing the Alt+Tab or Alt+Esc key combinations. An application can set the active frame window by calling WinSetActiveWindow; it also can obtain the handle of the active frame window by using WinQueryActiveWindow.

When one window is deactivated and another activated, the system sends a WM_ACTIVATE message, first to the window being deactivated, then to the window being activated. The fActive parameter of the WM_ACTIVATE message is set to FALSE for the window being deactivated and set to TRUE for the window being activated. An application can use this message to track the activation state of a client window.

Keyboard Focus

The keyboard focus is a temporary attribute of a window; the window that has the keyboard focus receives all keyboard input until the focus changes to a different window. The system converts keyboard input events into WM_CHAR messages and posts them to the message queue of the window that has the keyboard focus.

An application can set the keyboard focus to a particular window by calling WinSetFocus. If the application does not use WinSetFocus to explicitly set the keyboard-focus window, the system sets the focus to the active frame window.

The following events occur when an application uses WinSetFocus to shift the keyboard focus from one window (the original window) to another (the new window):

  1. The system sends the original window a WM_SETFOCUS message (with the fFocus parameter set to FALSE), indicating that that window has lost the keyboard focus.
  2. The system then sends the original window a WM_SETSELECTION message, indicating that the window should remove the highlight from the current selection.
  3. If the original (frame) window is being deactivated, the system sends it a WM_ACTIVATE message (with the fActive parameter set to FALSE), indicating that the window is no longer active.
  4. The system then sends the new application a WM_ACTIVATE message (with fActive set to TRUE), indicating that the new application is now active.
  5. If the new (main) window is being activated, the system sends it a WM_ACTIVATE message (with fActive set to TRUE), indicating that the main window is now active.
  6. The system sends the new window a WM_SETSELECTION message, indicating that the window should highlight the current selection.
  7. Finally, the system sends the new window a WM_SETFOCUS message (with fFocus set to TRUE), indicating that the new window has the keyboard focus.

If, while processing a WM_SETFOCUS message, an application calls WinQueryActiveWindow, that function returns the handle of the previously-active window until the application establishes a new active window. Similarly, if the application, while processing WM_SETFOCUS, calls WinQueryFocus, that function returns the handle of the previous keyboard-focus window until the application establishes a new keyboard-focus window. In other words, even though the system has sent WM_ACTIVATE and WM_SETFOCUS messages (with the fActive and fFocus parameters set to FALSE) to the previous windows, those windows are considered the active and focus windows until the system establishes new active and focus windows.

If the application calls WinSetFocus while processing a WM_ACTIVATE message, the system does not send a WM_SETFOCUS message (with fFocus set to FALSE), because no window has the focus.

A client window receives a WM_ACTIVATE message when its parent frame window is being activated or deactivated. The activation or deactivation message usually is followed by a WM_SETFOCUS message that specifies whether the client window is gaining or losing the keyboard focus. Therefore, if the client window needs to change the keyboard focus, it should do so during the WM_SETFOCUS message, not during the WM_ACTIVATE message.

Keyboard Messages

The system sends keyboard input events as WM_CHAR messages to the message queue of the keyboard-focus window. If no window has the keyboard focus, the system posts WM_CHAR messages to the message queue of the active frame window. Following are two typical situations in which an application receives WM_CHAR messages:

  • An application has a client window or custom control window, either of which can have the keyboard focus. If the window procedure for the client or control window does not process WM_CHAR messages, it should pass them to WinDefWindowProc, which will pass them to the owner. Dialog control windows, in particular, should pass unprocessed WM_CHAR messages to the WinDefDlgProc function, because this is how the user interface implements control processing for the Tab and Arrow keys.
  • An application window owns a control window whose window procedure can handle some, but not all, WM_CHAR messages. This is common in dialog windows. If the window procedure of a control in a dialog window cannot process a WM_CHAR message, the procedure can pass the message to the WinDefDlgProc function. This function sends the message to the control window's owner, which usually is a dialog frame window. The application's dialog procedure then receives the WM_CHAR message. This also is the case when an application client window owns a control window.

A WM_CHAR message can represent a key-down or key-up transition. It might contain a character code, virtual-key code, or scan code. This message also contains information about the state of the Shift, Ctrl, and Alt keys.

Each time a user presses a key, at least two WM_CHAR messages are generated: one when the key is pressed, and one when the key is released. If the user holds down the key long enough to trigger the keyboard repeat, multiple WM_CHAR key-down messages are generated. If the keyboard repeats faster than the application can retrieve the input events from its message queue, the system combines repeating character events into one WM_CHAR message and increments a count byte that indicates the number of keystrokes represented by the message. Generally, this byte is set to 1, but an application should check each WM_CHAR message to avoid missing any keystrokes.

An application can ignore the repeat count. For example, an application might ignore the repeat count on Arrow keys to prevent the cursor from skipping characters when the system is slow.

Message Flags

Key-Down or Key-Up Events

Repeat-Count Events

Character Codes

Virtual-Key Codes

Scan Codes

Accelerator-Table Entries

Mouse Messages

Capturing Mouse Input

Button Clicks

Mouse Movement

Using the Mouse and Keyboard

Determining the Active Status of a Frame Window

Checking for a Key-Up or Key-Down Event

Responding to a Character Message

Handling Virtual-Key Codes

Handling a Scan Code