Older Version Newer Version

Alyce Alyce Sep 21, 2011

=Trapping Mouse and Keyboard Events in Graphics= [[toc]] //Some information and code in this article are taken from the Liberty BASIC helpfile.// ==Box or Window?== The event trapping information given below works in the same way for graphicbox controls and for windows opened for graphics. WARNING: graphicboxes in dialog-type windows do not properly accept the input focus for keyboard events. If a program needs graphicboxes that trap keyboard events, use a window of type "window". ==Focus== Keyboard events are only trapped when a graphicbox or graphics window has the input focus. For example, to cause focus to be directed to a graphicbox, issue a SETFOCUS command. [[code format="lb"]] #main.graphicbox "setfocus" [[code]] ==When Event== The only way to trap mouse events and keyboard events in a Liberty BASIC program is within a graphicbox or graphics window. This is done with the "when event" command. The synax is as follows: [[code format="lb"]] #graphicsHandle "when event eventHandler" [[code]] Mouse events consist of left button mouse single-clicks, double-clicks, and drags, right button single-clicks, double-clicks and drags, middle button single-clicks, double-clicks and drags, and mouse moves when no button has been clicked. Keyboard events are triggered when the user presses a key on the keyboard. The eventHandler for the "when event" command can be a valid branch label or the name of a subroutine. ==List of Events== Most commands are not case sensitive. That is not true of the "when event" commands. The event names **are** case sensitive. The capitalization scheme is different than other case sensitive keywords, where the first letter is usually upper case. The first letter in "when event" commands is lower case. "LeftButtonDown" is not correct and will not work. "leftButtonDown" is correct and will work. **Case Counts!** ||leftButtonDown ||the left mouse button has been pressed || ||leftButtonUp ||the left mouse button has been released || ||leftButtonMove ||the mouse moved while the left button was down || ||leftButtonDouble ||the left mouse button has been double-clicked || ||rightButtonDown ||the right mouse button has been pressed|| ||rightButtonUp ||the right mouse button has been released|| ||rightButtonMove ||the mouse moved while the right button was down|| ||rightButtonDouble ||the right mouse button has been double-clicked|| ||middleButtonDown ||the middle mouse button has been pressed|| ||middleButtonUp ||the middle mouse button has been released|| ||middleButtonMove||the mouse moved while the middle button was down|| ||middleButtonDouble ||the middle mouse button has been double-clicked|| ||mouseMove ||the mouse moved when no button was down|| ||characterInput ||a key was pressed while the graphics window has input focus|| ==Turning Off Event Trapping== To stop trapping an event, issue the "when event" command without a sub or branch label, like this: [[code format="lb"]] #main.gbox "when leftButtonDown" [[code]] Trapping for any event can be turned on or off as many times as needed in the program. ==Mouse Coordinates and Keys Pressed== Whenever a mouse event is trapped, Liberty BASIC places the x and y position of the mouse in the variables MouseX, and MouseY. The values represent the mouse location as the number of pixels in x and y from the upper left corner of the graphic window display pane. The special variables "MouseX" and "MouseY" are case sensitive, as are all special variables in Liberty BASIC. Whenever a keyboard event is trapped, Liberty BASIC places the value of the key(s) pressed into the special variable, Inkey$. The special variable Inkey$ is case sensitive, as are all special variables in Liberty BASIC. ==Branch Label Event Handlers== If the event handler for the mouse or keyboard input is a branch label, Liberty BASIC will fill special variables with information. If the event is a mouse event, the location of the mouse is placed into the special variables MouseX and MouseY. These special variable names are case sensitive, so mouseX or mousex are incorrect, for instance. The values are expressed as the number of pixels from the upper left corner of the graphics area. The following small demo allows you to see the mouse coordinates when the left button is clicked and when the mouse is moved with no buttons pressed. [[code format="lb"]] graphicbox #1.g, 0,0,200,200 statictext #1.s, "Mouse Coordinates", 10,210,200,50 statictext #1.t, "Click left mouse button or move mouse.",10,260,200,50 open "Mouse Events" for window as #1 #1 "trapclose [quit]" #1.g "when leftButtonDown [leftDown]" #1.g "when mouseMove [mouseMoved]" wait [leftDown] #1.s "MouseX is ";MouseX;" MouseY is ";MouseY wait [mouseMoved] #1.s MouseX;" ";MouseY wait [quit]close #1:end nomainwin [[code]] ==Sub Event Handlers== If you use subroutines as mouse event handlers, be aware that branch labels elsewhere in the program are not visible inside of subs. If the program attempts to handle other events while processing a mouse event and it attempts to access a branch lable in the main program, the program will crash. It's best to use subs for all other routines that handle user events when using subs for mouse event handlers. Be sure to turn off mouse handling events when they are not needed, or when the event triggers a complex code block. Events can stack up while waiting for code to finish executing and unexpected errors can occur. [[code format="lb"]] graphicbox #1.g, 0,0,200,200 statictext #1.s, "Mouse Coordinates", 10,210,200,50 statictext #1.t, "Click left mouse button or move mouse.",10,260,200,50 open "Mouse Events" for window as #1 #1 "trapclose Quit" #1.g "when leftButtonDown leftDown" #1.g "when mouseMove mouseMoved" wait sub leftDown hndle$, mx, my #1.s "MouseX is ";mx;" MouseY is ";my end sub sub mouseMoved hndle$, mx, my #1.s mx;" ";my end sub sub Quit hndle$ close #hndle$:end end sub nomainwin [[code]] ==Reading Keystrokes== Keyboard input can only be trapped in graphics windows or graphicboxes that have the input focus. When a key is pressed, the information is stored in the special variable Inkey$. The name Inkey$ is case sensitive, as are all variable names in Liberty BASIC. This special variable holds either a single typed character or multiple characters including a Windows virtual key code. The virtual key codes are standard Windows constants, and include arrow keys, function keys, the ALT, SHIFT, and CTRL keys, etc. If Inkey$ is a single character, that character will be the key pressed. If the length of Inkey$ is more than 1, it holds multiple key information:. If Inkey$ holds more than one character, the first character will indicate whether the Shift, Ctrl, or Alt keys was depressed when the key was pressed. These keys have the following values: Shift = 4 Ctrl = 8 Alt = 16 They can be used in any combination. If Inkey$ contains more than one character, you can check to see which (if any) of the three special keys was also pressed by using the bitwise AND operator. If shift alone was pressed, then the value of the first character will be 4. If Shift and Alt were both pressed, then the value of the first character will be 20, and so on. Special keys trigger a new value for Inkey$ when they are pressed and again when they are released. Here is an example that uses bitwise AND to determine which special keys were pressed. [[code format="lb"]] open "Inkey$ with Shift" for graphics_nf_nsb as #1 #1 "setfocus; when characterInput [check]" #1 "down; place 10 30" #1 "\Make the mainwindow visible," #1 "\then click this window and" #1 "\begin pressing key combinations." #1 "\Watch the printout in the mainwindow." #1 "flush" #1 "trapclose [quit]" wait [check] shift=4 ctrl=8 alt=16 a=asc(left$(Inkey$,1)) if len(Inkey$)>1 then m$="" if a and shift then m$="shift " if a and ctrl then m$=m$+"ctrl " if a and alt then m$=m$+"alt " print "Special keys pressed: " + m$ else print "Key pressed: " + Inkey$ end if wait [quit] close #1 end [[code]] ==Virtual-Key Codes== Liberty BASIC has a library of Virtual-Key codes that it understands, such as _VK_NUMPAD2 [[code format="lb"]] 'Alpha-numeric keys are expressed as ASCII values: PRINT ASC("A") PRINT ASC("a") 'Special keys use Virtual Key Constant values: PRINT _VK_NUMPAD2 PRINT _VK_APPS PRINT _VK_F7 PRINT _VK_RSHIFT PRINT _VK_F24 [[code]] If you attempt to use an unknown Virtual-Key code, you'll get an error message from Liberty BASIC. In that case, use the value of the Virtual-Key constant. You can find the values online: Here is a list of Virtual-Key Codes from the Microsoft Developer's Network Library: [[http://msdn.microsoft.com/en-us/library/ms645540%28VS.85%29.aspx|Virtual-Key Codes]] The values are given in hexadecimal form. Use HexDec() to find the decimal value. The 0x at the beginning of hexadecimal numbers simply signals the format in some languages. Omit that part in Liberty BASIC. Here is an example. [[code format="lb"]] 'VK_LAUNCH_APP2 (0xB7) print hexdec("B7") [[code]] ==Key Up and Key Down== Special keys trigger a new value for Inkey$ when they are pressed and again when they are released. A virtual key is the key that is actually pressed on the keyboard. The VK value for a lower case letter is the same as the value for the same letter in upper case because it refers to the key pressed on the keyboard, not to the ASCII value of the input. Most keys have a graphical representation. You can see letters, numbers and symbols in a texteditor as they are typed, for instance. There are some keys that do not have a graphical representation. You must use Virtual Key Codes to discover which of these keys has been pressed. They include the arrow keys, the F-keys, Shift, Ctrl, Alt, Del, etc. Here is a program that gives a quick example: [[code format="lb"]] 'Inkey$ example, part two ctrl$ = chr$(_VK_CONTROL) print "Keys pressed:" open "Inkey$ example" for graphics as #graph print #graph, "when characterInput [keyPressed]" print #graph, "trapclose [quit]" [loopHere] 'make sure #graph has input focus print #graph, "setfocus" 'scan for events scan goto [loopHere] [keyPressed] key$ = left$(Inkey$, 2) if len(key$) < 2 then print "pressed: "; key$ else if right$(key$, 1) = ctrl$ then print "CTRL was pressed" else print "Unhandled special key" end if end if goto [loopHere] [quit] print "Quitting" close #graph end [[code]] ---- [[toc]]