Mouse and keyboard
From EuWiki
The mouse and keyboar are the major source of input for any Windows program. As such, they are expected to be linked to a number of events. The library allows ou to trap most of what happens to the mouse and keyboard - even though keyboard habdling could be beefed up -.
Contents |
Reporting raw mouse events
They all come through the w32HMouse event. The parameter sequence the handler receives is made of:
- an event code, among the following:
- MouseMove: the mouse was moved
- LeftDown: the left mouse button was pressed
- RightDown: the right mouse button was pressed
- LeftUp: the left mouse button was released
- RightUp: the right mouse button was released
- LeftDoubleClick: the left mouse button was double clicked
- RightDoubleClick: the right mouse button was double clicked
- WheelMove: The mouse wheel has moved.
- x position, in client coordinates relative to the control that received the event.
- y position, in client coordinates relative to the control that received the event.
- A shift state, combining the following flags:
- ShiftMask --> Left and/or Right Shift key down
- ControlMask --> Left and/or Right Control key down
- AltMask --> Left and/or Right Alt key down
- KeyMask --> Any of the Shift/Control/Alt keys down.
- LeftBtnMask --> Left mouse button down.
- RightBtnMask --> Right mouse button down.
- MiddleBtnMask --> Middle mouse down.
- BtnMask --> Any mouse button down.
- a wheel move integer. This is 0 if no move occurred, greater than zero if wheel was spinned away from the user, and less than zero if it was spinned towards the user. The absolute value of the parameter is the number of "notches". You may call getWheelScrollLines() to know about how the user wishes the translation be made.
If the return value of the handler chain is set, the event is not passed to Windows for further processing.
Many demos show useful techniques of intercepting mouse events: BIGDOTS.exw, child3.exw, click.exw, rclick.exw, rtclick.exw.
When a child window gets a mouse click, all its ancestors receive a special message, WM_PARENTNOTIFY, unless the child window has the WS_EX_NOPARENTNOTIFY extended style flag. This can be useful, but would do double duty with the regular mouse messages, so that the library doesn't take action on them. But of course you can.
Mouse parameters
Reporting
- getPointerPos()
- Returns {x,y} screen coordinates of the mouse pointer. See the child2.exw demo program.
- getPointerRelPos(control_id)
- Returns {x,y} coordinates of mouse pointer relative to the client area of control_id.
Setting
Mouse pointer
- setMousePointer(control_id,new_value)
- Sets the mouse pointer shape for control_id (either a single one or a sequence). The new_value is either
- a file name for a .cur or .ani file;
- a system pointer string identifier;
- a system pointer atom identifier;
- an identifier you created;
- 0;
- -1.
- The previous shape is saved and can be restored using the 0 value. -1 zaps all the saved shapes and sets the mouse pointer to its system default.
- For examples of setting the mouse pointer, see the colorlbl.exw program.
- restoreMousePointer()
- Pops the stack of saved shapes.
- createMousePonter(hot_spot_X,hot_spot_Y,image_text)
- Creates a monochrome bitmap from image, and sets it as mouse pointer setting the hot spot at the supplied positions. image_text is a sequence of strings, each of which is a line of pixels. The encoding is as follows:
- '.' = white
- 'x' = black
- ' ' = transparent
- The returned value is a cursor handle, which is a tracked GDI resource.
- setDragPointer(style)
- sets the pointer(s) to display when dragging an object. style is either an atom or a 4 element sequence; if an atom, a, this is a shorthand for repeat(a,4).
- The atom or sequence elements are cursor handles, no matter how they were obtained.
- The four positions correspond to:
- no shift key
- Shift key pressed
- Control key pressed
- Alt key pressed
- If two or more shifts are used while dragging, Shift prevails over Control, which prevails over Alt.
See the setmouse.exw demo program for examples of dynamically setting the mouse pointer.
Simulating events
- clickPointerLeft()
- Performs a left click at the curent position.
- setPointerPos({x,y})
- Positions the cursor hot spot at screen coordinates (x,y).
- dragPointerTo({x,y})
- Drags mouse, with the left button down, to position (x,y) in screen coordinates.
- Simulated right button down dragging is not supported.
Other
- setMouseClick(tDelta,xDelta,yDelta)
- Sets the tolerance in terms of time,x,y, for click detection. A click is detected when a mouse down and mouse up events are detected and the time,x and y differences are all below these tolerances.
- There is no setting for double clicks. The Windows API can tune the time threshold for double clicks, but system wide only.
Reporting
Grabbing the mouse
You can instruct Windows to send all mouse events to a given control, and stop this behaviour:
- captureMouse(control_id) starts the capture relative to control_id, or changes the capturing control.
- releaseMouse() stops any capture.
Trapping the mouse
The library supports mouse traps, aka event boxes on other systems. When a mouse event occurs inside a mouse trap, and if the mouse trap is enabled for this event, a w32HMouseTrap event is generated.
The parameter sequence for the w32HMouseTrap event is as follows:
- An event code
- x position
- y position
- WheelMove parameter
- A list of the traps that were triggered;
- The id of the control that received the event, Screen if none.
- The state of the shift keys
The trap sequence is a sequence of complete mouse trap information. Each element is a record made as follows:
- integer: zorder, the higher numbers are further in the background. # # integer: left, the leftmost position of the mousetrap area
- integer: top, the topmost position of the mousetrap area
- integer: right, the rightmost position of the mousetrap area
- integer: bottom, the bottommost position of the mousetrap area
- integer: id, the id of this mousetrap area.
- object: userdata, the data set by calling setTagMouseTrap(). This is never used by win32lib and is intended for use by the user for anything.
- sequence: filters, a list of zero or more mouse event codes that are used to filter in this mousetrap.
See the mousetrap.exw demo program for examples.
Mouse trap management
- createMouseTrap(control_id,rectangle)
- Returns the id for the newly created mouse trap, which is attached to control_id.
- rectangle is either
- an id of a child window of control_id: then the rectangle is the whole area (???) of the child;
- a {left,top,right,bottom} rectangle in client coordinates.
- The initial z-order is set to 0 (topmost);
- The only event initially trapped is LeftDown;
- The newly created mouse trap is enabled.
- deleteMouseTrap(control_id,trap_id)
- Deletes the designated trap. If trap_id is zero or less, all traps for control_id are removed.
- enableMouseTrap(control_id,trap_id,flag)
- Sets the sate of designated mouse trap to enabled (flag=w32True) or disabled (w32False). A disabled trap never send w32HMouseTrap events; an enabled trap send w32HMouseTrap for every mouse event it filters in.
Rectangles move with the (child) window they are attached to, unless the bounding control is Screen.
Tuning mouse traps
- updateMouseTrap(control_id,trap_id,rectangle)
- Changes the rectangle for designated mouse trap.
- zorderMouseTrap(control_id,trap_id,depth)
- sets the depth of the mouse trap. This impacts the order in which hit mouse traps are returned.
- Note that mouse traps do not screen one another out; the zorder parameter only affects the order in which hit mousetraps are returned.
- filterMouseTrap(control_id,trap_id,events)
- Sets the events the designated mouse trap(s) react(s). It can be a sequence of codes or a single one. Codes are the same as for w32HMouse.
- setTagMouseTrap(control_id,trap_id,tag)
- Sets the data field of designated mouse trap(s) to tag.
Getting information
- getTagMouseTrap(control_id,trap_id)
- Gets the data field for designated mouse trap.
- getMouseTrap(control_id,trap_id)
- Returns the full information record for designated mouse trap, as described in the createMouseTrap() entry.
- hitMouseTrap(control_id,event,x,y)
- Returns a list of mouse trap full information records. Reported mouse traps are those which contain the =designated point, are attached to control_id, are enabled and filter the supplied event in. The traps are returned topmost first.
Dragging and dropping items
ListView or TreeView items, but also files, can be dropped onto controls. When this happens, the target control receives the w32HDragAndDrop event.
The parameter sequence for this event is made of an integer and an object:
- If the integer is nonzero and is not the receiving id, it is a library id identifying the control from which items are being dragged. The second element is the list of the ids of these items.
NOTE: so the event does not fire when items from a List/TreeView the library didn't create are dropped.
- If the integer equals the receiving id, then this event is triggered when dragged items from the control ends. The data object is the list of the currently selected items in the control;
- If the integer is 0, some files are being dragged to the control:
- if the data object is an integer, this is the number of files passed in subsequent events. The handler may abort operation by setting the return value;
- If it is a nonempty sequence, that sequence is a file name being passed to the target control. If n is the integer data in the descripton above, this sort of event will fire n times. The handler may set the return value to stop file dropping there;
- If it is an empty sequence, then all files were transmitted. This ends the series of events which translated a single file drag and drop from user.
You can see drag and drop in action in the ListTreeView.exw demo program.
Keyboard handling
The library records and relays pushed and released keys using the w32HKeyDown, w32HKeyUp, w32HKeyPress and w32HKeyboard events. For the former two, the parameter sequence is made of {key_code,shifts}. For w32HKeyPress, this extends to {key_code,shift,is_key_released}. For the w32HKeyboard event, the parameter sequence is:
- the list of virtual keycodes for the keys being depressed;
- the list of corresponding extended key flags;
- the list of raw scan codes for these keys;
- the list of repeat counts for them.
See the ctrlq.exw or F1key.exw demo programs for an example.
key_code is one of the logical keys Windows knows about. The list of known identifiers can be found in w32Keys.e.
shift is a combination of ShiftMask, ControlMask and AltMask.
The w32HKeyPress only reports printable keys. This event is triggered in addition to the generating key down event(s). Windows "produces WM_CHAR messages [which trigger w32HKeyPress] only for keys that are mapped to ASCII characters by the keyboard driver"
On some systems, the w32HKeyUp event is not fired when an Alt-non printale key is pressed. Windows may indeed send the WM_NULL message instead of the WM_SYSKEYUP one.
Specialised events are also riggered:
- w32HPause, when the Pause key is depressed (any shifts???? it looks like Ctrl-Pause might generate w32HBreak))
- w32HBreak, when the Ctrl-Break key combo is entered (any other shifts)
If you process the WM_KEYDOWN raw message (this won't work with WM_SYSKEYDOWN), the special return value {w32KH_SetFocus,control_id} from the message handler will cause focus to be set:
- on the specified control, if the key code is not a tab key;
- after or before the specified control if the key code is a tabbing key, according to whether any shift key is depressed at the time of the event.
Setting the return value in any keyboard handler will cause the event to be ignored by Windows. This is useful when your handler replaces the default action rather than supplementing it. See for instance the biglistview.exw demo.
The w32HKeyboard event fires when either:
- zero or more shifts are depressed, and a non shift key is depressed;
- one or more shifts are depressed, no non shift is and one of the shifts is being released.
By "shift key", any Shift, Control, Alt or Windows key is meant.
The getKeyState(key_code) function returns w32True if the key is being depressed, else w32False.
You can now retrieve the state of the three standard keyboard LEDs using the getLEDs() function.
Keyboard issues
- Logical hotkeys are not processed by the library, nor does it wrap the HotKey control used to configure them.
- Invalid key combinations, like pressing the caret key and then a consonant, report as dead characters. The library doesn't provide any mechanism to trap them; this is a rare need for english-speaking environments indeed. Just trap and process the WM_DEADCHAR message.
- Windows supports keyboard accelerators which may override menu shortcuts. The library doesn't support this mechanism, which would entail setting up your own event loop.
