Part VI
Adding Keyboard Control
We will add keyboard event support by using the arrow keys and the PgUp, PgDn, and Shift keys. The arrow keys will move the currently selected date one day/week forwards or backwards. The PgUp/PgDn keys will select the next/previous month. And finally, the Shift-PgUp/Shift-PgDn combinations will select the next/previous year.
Responding to #TextEvent Messages
In order for our grid function to be able to respond
to keyboard text events created by our day PressButton grids, we need to set
up a SUB for this message. In SUB Initialize we must first add the
following line:
Sub[#TextEvent] = SUBADDRESS(TextEvent)
This will register our TextEvent Subroutine address with the array of messages for our grid.
Set Keyboard Focus Kid Grid
Unless we set the keyboard focus to the currently
selected day PressButton kid grids, we won't receive any textevent
callbacks. So, in SUB HighlightCurrentDay we add:
XuiSetKeyboardFocusGrid (grid, #SetKeyboardFocusGrid, 0, 0, 0, 0, curDayGrid, 0 )
where the kid argument curDayGrid is set to our currently selected day grid.
In the SUB Initialize, I now can comment out or delete the line which sets the starting focusKid as the $MonthLeftArrowPressB (month left arrow press button).
' XuiSetGridTypeProperty (gridType, @"focusKid", $MonthLeftArrowPressB)
Add our SUB TextEvent
Now we can add our SUB TextEvent to handle all of
our keyboard events. This part is actually quite easy since we can make use
of the current subroutines which handle selecting days, months, and years.
SUB TextEvent
'PRINT "text event", "v2="; v2, " r0="; r0
IF r0 < $Day1 || r0 > $Day42 THEN EXIT SUB
'capture shift+PgUp or shift+PgDn for next year, previous year selection
IF v2 AND $$ShiftBit THEN
SELECT CASE v2{$$VirtualKey}
CASE $$KeyPageUp : r0 = $YearLeftArrowPressB
GOSUB Selection
CASE $$KeyPageDown : r0 = $YearRightArrowPressB
GOSUB Selection
END SELECT
ELSE
'User arrows to select day, PgUp for previous month, PgDn for next month
SELECT CASE v2{$$VirtualKey}
CASE $$KeyDownArrow : IF r0 < $Day36 THEN
r0 = r0 + 7
GOSUB DaySelection
END IF
CASE $$KeyUpArrow : IF r0 > $Day7 THEN
r0 = r0 - 7
GOSUB DaySelection
END IF
CASE $$KeyRightArrow: INC r0
IF r0 > $Day42 THEN
r0 = $Day42
EXIT SUB
ELSE
GOSUB DaySelection
END IF
CASE $$KeyLeftArrow : DEC r0
IF r0 < $Day1 THEN
r0 = $Day1
EXIT SUB
ELSE
GOSUB DaySelection
END IF
CASE $$KeyPageUp : r0 = $MonthLeftArrowPressB
GOSUB Selection
CASE $$KeyPageDown : r0 = $MonthRightArrowPressB
GOSUB Selection
END SELECT
END IF
END SUB
SUB TextEvent Discussion - state v2 and kid r0
There are two SELECT CASE statements in this subroutine.
The first one checks whether the user has pressed the Shift key and then handles
the PgUp or PgDn key events. If the Shift key has not been pressed, then the
second SELECT CASE statement takes care of all of the arrow key events and the
normal PgUp/PgDn key events.
You should also note that a text event callback provides the kid grid that sent the callback in r0 and the keyboard state in argument v2.
In addition, we are mostly interested in looking at two just two parts of the state argument v2, the Virtual Key Code in Bits 24-31 and the Shift Key Bit 16. From the docs you see them defined as:
state (v2)
state contains the state of the keyboard when the keyboard event was detected,
and reflects the new state of the keyboard.
Bit 24 - 31 : Virtual Key Code
Bit 16 = 1 : Shift key was down when the keyboard event occured.
Using Brace Notation to extract bit fields
Xbasic provides a way to extract any bit from a 32 bit integer
variable using Brace Notation {}. The first argument inside the braces is the
number of bits to be extracted. The second argument is the starting bit to begin
the extraction. So, to extract the Virtual Key Code from v2 we want to extract
8 bits starting with bit number 24.
vkc = v2{8,24} '8 bits 24-31
Fortunately, there are Virtual Key Code constants that can be used instead of trying to remember bit positions and lengths. The Graphics Library Instant Help file shows these Virtual Key Code constants for every keyboard key. It also has a constant for extracting the correct Virtual Key bitfield from v2:
$$VirtualKey = BITFIELD (8,24)
Thus we can get our virtual key code more simply using:
vkc = v2{VirtualKey}
We then can compare the value from the Virtual Key Code against various key code constants to see which key event occurred. Below are listed the Key constants used in our SELECT CASE statement:
$$KeyDownArrow
$$KeyUpArrow
$$KeyRightArrow
$$KeyLeftArrow
$$KeyPageUpArrow
$$KeyPageDownArrow
Thus, by using Brace Notation and Key Code Constants, we are able to capture any combination of user key events. In addition, it makes it much easier to understand our code since we are using easily read and understood constants rather than numbers. The current stage of our program is given in calendar5.x.
In Part VII...
(c) 2000 David SZAFRANSKI