Page 1 of 2
Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 1:58 pm
by J@ckWhiteIII
Hey,
Somehow I haven't seen an example for the canvas gadget that uses its keyboard constants or anything. From the help I don't really get information about how it works. Yep, I have to create the gadget with #PB_Canvas_Keyboard flag. When an event from the canvas gadget is sent and it's e.g. #PB_Eventtype_KeyUp.....Then how do I determine WHAT key has been pressed?
Thanks in advance
Re: Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 2:11 pm
by kenmo
Use GetGadgetAttribute() and one of these:
Code: Select all
#PB_Canvas_Key
Returns the key that was pressed or released in a #PB_EventType_KeyDown or #PB_EventType_KeyUp event. The returned value is one of the #PB_Shortcut_... values used by the AddKeyboardShortcut() function. This attribute returns raw key presses. To get text input for the gadget, it is better to watch for #PB_EventType_Input events and use the #PB_Canvas_Input attribute because it contains the text input from multiple key presses such as shift or dead keys combined.
#PB_Canvas_Input
Returns the input character that was generated by one or more key presses. This attribute is only present after a #PB_EventType_Input event. The returned character value can be converted into a string using the Chr() function.
Re: Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 2:18 pm
by Danilo
Code: Select all
If OpenWindow(0, 0, 0, 220, 220, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
CanvasGadget(0, 10, 10, 200, 200,#PB_Canvas_Keyboard)
SetActiveGadget(0)
Repeat
Event = WaitWindowEvent()
If Event = #PB_Event_Gadget And EventGadget() = 0
If EventType() = #PB_EventType_KeyUp
key = GetGadgetAttribute(0,#PB_Canvas_Key)
Debug key
EndIf
EndIf
Until Event = #PB_Event_CloseWindow
EndIf
Re: Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 2:20 pm
by J@ckWhiteIII
Just an example code someone made for me:
Code: Select all
;---------------------------------------------------------------------------------------------------
;- GLOBALS
;---------------------------------------------------------------------------------------------------
Global Game_Window_Event.i
Global MousePosX.w
Global MousePosY.w
Global GameTextWidth.w
Global GameTextHeight.w
Global GameText.s
Global GameTextFont.i = 4
Global GameBackgroundImage.i = 5
Global GameTextImage.i = 6
;---------------------------------------------------------------------------------------------------
;- LOAD FONTS
;---------------------------------------------------------------------------------------------------
LoadFont(GameTextFont, "Arial", 48, #PB_Font_HighQuality)
;---------------------------------------------------------------------------------------------------
;- PRECREATE IMAGE
;---------------------------------------------------------------------------------------------------
CreateImage(GameBackgroundImage, 800, 600, 32)
StartDrawing(ImageOutput(GameBackgroundImage))
DrawingMode(#PB_2DDrawing_Default)
Box(0, 0, 800, 600, RGB(43, 144, 232))
DrawingMode(#PB_2DDrawing_Transparent)
DrawingFont(FontID(GameTextFont))
DrawText(100, 100, "PVG Canvas Test", RGB(255, 255, 255))
StopDrawing()
;---------------------------------------------------------------------------------------------------
CreateImage(GameTextImage, 600, 100, 32)
StartDrawing(ImageOutput(GameTextImage))
DrawingFont(FontID(GameTextFont))
GameText = "PVG Canvas Test"
GameTextWidth = TextWidth(GameText) + 10
GameTextHeight = TextHeight(GameText) + 10
DrawingMode(#PB_2DDrawing_Default)
Box(0, 0, GameTextWidth, GameTextHeight, RGB(0, 0, 0))
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(5, 5, GameText, RGB(255, 255, 255))
;- FOR FULLY TRANSPARENT TEXT (CUT OUT) USE THIS
; DrawingMode(#PB_2DDrawing_AlphaChannel)
; DrawText(5, 5, GameText, RGBA(0, 0, 0, 0))
StopDrawing()
;---------------------------------------------------------------------------------------------------
;- CREATE CANVAS GAMING WINDOW
;---------------------------------------------------------------------------------------------------
If OpenWindow(0, 0, 0, 800, 600, "PVG - Canvas Game Test - v001", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
CanvasGadget(1, 0, 0, 800, 600, #PB_Canvas_Keyboard)
;---------------------------------------------------------------------------------------------------
;- DO LOOP
;---------------------------------------------------------------------------------------------------
Repeat
Game_Window_Event = WindowEvent()
Select Game_Window_Event
Case #PB_Event_Gadget
Select EventGadget()
Case 1 ; Canvas gadget
Select EventType()
Case #PB_EventType_LeftButtonDown
If StartDrawing(ImageOutput(GameBackgroundImage))
DrawingMode(#PB_2DDrawing_Default)
DrawAlphaImage(ImageID(GameTextImage), MousePosX, MousePosY, 50)
StopDrawing()
EndIf
Case #PB_EventType_MouseMove
If StartDrawing(CanvasOutput(1))
DrawingMode(#PB_2DDrawing_Default)
; Box(0, 0, 800, 600, RGB(43, 144, 232))
DrawImage(ImageID(GameBackgroundImage), 0, 0, 800, 600)
MousePosX = GetGadgetAttribute(1, #PB_Canvas_MouseX)
MousePosY = GetGadgetAttribute(1, #PB_Canvas_MouseY)
DrawingMode(#PB_2DDrawing_AlphaBlend)
; Circle(MousePosX, MousePosY, 10, RGB(100, 100, 100))
DrawAlphaImage(ImageID(GameTextImage), MousePosX, MousePosY, 50) ;255) ;100)
StopDrawing()
EndIf
Case #PB_EventType_KeyUp
If GetGadgetAttribute (1,#PB_Canvas_Key) = #PB_Key_D
Debug "Works"
EndIf
EndSelect
EndSelect
EndSelect
Until Game_Window_Event = #PB_Event_CloseWindow
EndIf
;---------------------------------------------------------------------------------------------------
Einde:
End
;---------------------------------------------------------------------------------------------------
I added the keyboard part.......But it doesn't work for me. What am I doing wrong there? :/
Re: Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 2:47 pm
by J@ckWhiteIII
Danilo, your code helped me and showed me how to do it

Now I've tried to implement it here:
Code: Select all
If we = #PB_Event_Gadget And EventGadget() = 0
If EventType() = #PB_EventType_KeyDown
key = GetGadgetAttribute(0,#PB_Canvas_Key)
If key = 38
If Not Players.Player(0)\y = 32
yValn = -1
Players.Player(0)\Direction = #Up
Break
EndIf
ElseIf key = 39
If Not Players.Player(0)\y = 448
yValp = 1
Players.Player(0)\Direction = #Down
Break
EndIf
ElseIf key = 37
If Not Players.Player(0)\x = 0
xValn = -1
Players.Player(0)\Direction = #Left
Break
EndIf
ElseIf key = 40
If Not Players.Player(0)\x = 608
xValp = 1
Players.Player(0)\Direction = #Right
Break
EndIf
ElseIf key = 1
End
EndIf
EndIf
EndIf
ForEver
^This is just the keyboard part now. Before, I'm using we = WindowEvent ()
But as soon as i press a key, the whole thing just freezes ("loading" cursor, not responding window etc)
But i haven't really changed anything in the next repeat loop because it's only an animation, but somehow..that thing is played over and over again and the window events aren't handeled or anything o.O
Re: Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 2:50 pm
by kenmo
Not sure about the freezing (like you said, it must be stuck in a loop that's not reading WindowEvent()),
but for the key constants use #PB_Shortcut_D and similar (these are for windows/gadget/menu stuff) instead of #PB_Key_D and similar (these are just for the Keyboard library, I think).
Re: Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 2:54 pm
by J@ckWhiteIII
Hm, I thought #PB_Canvas_Key returned the raw code? "Dieses Attribut gibt "rohe" (raw) Tastendrücke zurück." - "This attribute returns the raw key code."
^woops, you were talking abou the example code! sorry for that. Yeah, I think I know what you mean. Will be useful for apps if I ever do one that uses menus
As it's for a game, I don't have any keyboard shortcuts in there
Re: Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 3:10 pm
by IdeasVacuum
Add SetActiveGadget(1) after CanvasGadget(1,....)
Re: Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 3:13 pm
by J@ckWhiteIII
HAHA, the fucking canvas gadget must be fucking slow!!!
H is debugged 2!!!! times per SECOND....windowed screen was thousands of times faster
Code: Select all
Repeat
X = (ElapsedMilliseconds () - StartTime) / 1000
we = WindowEvent ():If we = #PB_Event_CloseWindow:End:EndIf
If we = #PB_Event_Gadget And EventGadget() = 0
If EventType() = #PB_EventType_KeyDown
key = GetGadgetAttribute(0,#PB_Canvas_Key)
If key = 1
End
EndIf
EndIf
EndIf
ForEach Blocks()
we = WindowEvent ():If we = #PB_Event_CloseWindow:End:EndIf
With Blocks()
StartDrawing (CanvasOutput(0))
DrawImage (ImageID(\type),\x,\y)
StopDrawing ()
If Players.Player(0)\x = \x And Players.Player(0)\y = \y
If ListIndex (Blocks()) < ListSize (Blocks()) - 1
SelectElement (Blocks(),ListIndex(Blocks()) + 1)
If \type = 5
xValp = 0
EndIf
SelectElement (Blocks(),ListIndex(Blocks())-1)
EndIf
If Not ListIndex (Blocks()) = 0
SelectElement (Blocks(),ListIndex(Blocks()) - 1)
If \type = 5
xValn = 0
EndIf
SelectElement (Blocks(),ListIndex(Blocks())+1)
EndIf
If ListIndex (Blocks()) < 280
SelectElement (Blocks(),ListIndex(Blocks()) + 20)
If \type = 5
yValp = 0
EndIf
SelectElement (Blocks(),ListIndex(Blocks())-20)
EndIf
If ListIndex (Blocks()) > 20
SelectElement (Blocks(),ListIndex(Blocks()) - 20)
If \type = 5
yValn = 0
EndIf
SelectElement (Blocks(),ListIndex(Blocks())+20)
EndIf
EndIf
EndWith
Next
With Players.Player(0)
\x + xValp
\y + yValp
\x + xValn
\y + yValn
If H > 16
Select \Direction
Case #Up
\Picture = #RFUp
Case #Down
\Picture = #RFDown
Case #Left
\Picture = #RFLeft
Case #Right
\Picture = #RFRight
EndSelect
Else
Select \Direction
Case #Up
\Picture = #LFUp
Case #Down
\Picture = #LFDown
Case #Left
\Picture = #LFLeft
Case #Right
\Picture = #LFRight
EndSelect
EndIf
EndWith
StartDrawing (CanvasOutput (0))
DrawImage (ImageID(Players.Player(0)\Picture),Players.Player(0)\x,Players.Player(0)\y)
DrawText (0,0,Str(X) + " seconds",255,0)
StopDrawing()
H + 1
Debug Str(H)
Until H = 32
This animation kills the speed of the game...so this means I'll have to go back to WindowedScreen, rewrite all the stuff, catch sprites instead of images....I wish I had known that before. Oh well..
@IdeasVacuum: Did that already, didn't help in any way, unfortunately :/
Re: Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 3:26 pm
by IdeasVacuum
@IdeasVacuum: Did that already, didn't help in any way, unfortunately :/
It does work with the code that you posted when asking the question.
Surprised that the Canvas Gadget is slow - it's always been instantaneous in my apps, but I don't write games.
Re: Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 4:06 pm
by Polo
The idea of writing games on the Canvas gadget is beyond me... Why would you write a game without using hardware acceleration?
Canvas gadget is clearly to create a GUI control, not a game - the keyboard events on the canvas are not suitable for games as well.
Re: Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 4:11 pm
by J@ckWhiteIII
But..For a nice looking menu I'd need like 30 different spritecollision examinations, plus a procedure that only enables the mouse while the mouse is on the screen. So...There really is no EASY way to have a nice graphical menu in PureBasic?
Re: Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 4:41 pm
by kenmo
OK some notes...
1. About #PB_Canvas_Key, read the Help file again. Yes it says "This attribute returns raw key presses." but the sentence directly before that is "The returned value is one of the #PB_Shortcut_... values used by the AddKeyboardShortcut() function." You should use these constants, it doesn't matter if you're actually using menus or shortcuts or not.
2. Polo is right... the CanvasGadget should not be used for games, except maybe point-and-click games or turn-based games (not 60 FPS action games). Screens and Sprites will always be faster, they are optimized for fast graphical games.
3. In your last code, you are breaking a fundamental rule of StartDrawing/StopDrawing... you should only call these once per loop and draw everything together, don't open a StartDrawing() for every object! This is guaranteed to slow your code down, because it has to copy (or at least re-create) a graphics buffer each time.
4. For a menu within a Screen, maybe try the Window3D library (although I've never used it) or write your own... it's not too hard and it's good practice.
Re: Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 4:49 pm
by J@ckWhiteIII
So, decided on Windowed Screen now. Problems: For a Window3D I need engine3D which disables ScreenOutput then. Also, you can't display a Window3D in front of sprites because sprites must be displayed AFTER RenderWorld(). So you really think I should display 30 sprites for a menu? and examine if they're being clicked on...and examine whether the desktop mouse is on the screen or not. Wow that's gonna be a ridiculously high amount od effort I'll have to put in there...Na, just with keys it'd be better. The arrows, return and ESC are all I'm gonna need then...Okay, Trying it now! thanks for all the helpful replies

Re: Canvas gadget keyboard handling?
Posted: Sat Sep 29, 2012 4:57 pm
by BasicallyPure
HI,
I worked on one of the canvas codes posted above and I think it works better now.
Give it a try.
Code: Select all
;---------------------------------------------------------------------------------------------------
;- GLOBALS
;---------------------------------------------------------------------------------------------------
Global Game_Window_Event.i
Global MousePosX.w
Global MousePosY.w
Global GameTextWidth.w
Global GameTextHeight.w
Global GameText.s
Global GameTextFont.i = 4
Global GameBackgroundImage.i = 5
Global GameTextImage.i = 6
;---------------------------------------------------------------------------------------------------
;- LOAD FONTS
;---------------------------------------------------------------------------------------------------
LoadFont(GameTextFont, "Arial", 48, #PB_Font_HighQuality)
;---------------------------------------------------------------------------------------------------
;- PRECREATE IMAGE
;---------------------------------------------------------------------------------------------------
CreateImage(GameBackgroundImage, 800, 600, 32)
StartDrawing(ImageOutput(GameBackgroundImage))
DrawingMode(#PB_2DDrawing_Default)
Box(0, 0, 800, 600, RGB(43, 144, 232))
DrawingMode(#PB_2DDrawing_Transparent)
DrawingFont(FontID(GameTextFont))
DrawText(100, 100, "PVG Canvas Test", RGB(255, 255, 255))
StopDrawing()
;---------------------------------------------------------------------------------------------------
CreateImage(GameTextImage, 600, 100, 32)
StartDrawing(ImageOutput(GameTextImage))
DrawingFont(FontID(GameTextFont))
GameText = "PVG Canvas Test"
GameTextWidth = TextWidth(GameText) + 10
GameTextHeight = TextHeight(GameText) + 10
DrawingMode(#PB_2DDrawing_Default)
Box(0, 0, GameTextWidth, GameTextHeight, RGB(0, 0, 0))
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(5, 5, GameText, RGB(255, 255, 255))
;- FOR FULLY TRANSPARENT TEXT (CUT OUT) USE THIS
; DrawingMode(#PB_2DDrawing_AlphaChannel)
; DrawText(5, 5, GameText, RGBA(0, 0, 0, 0))
StopDrawing()
;---------------------------------------------------------------------------------------------------
;- CREATE CANVAS GAMING WINDOW
;---------------------------------------------------------------------------------------------------
If OpenWindow(0, 0, 0, 800, 600, "PVG - Canvas Game Test - v001", #PB_Window_ScreenCentered | #PB_Window_SystemMenu)
CanvasGadget(1, 0, 0, 800, 600, #PB_Canvas_Keyboard)
;---------------------------------------------------------------------------------------------------
;- DO LOOP
;---------------------------------------------------------------------------------------------------
Repeat
Game_Window_Event = WindowEvent()
Select Game_Window_Event
Case #PB_Event_Gadget
Select EventGadget()
Case 1 ; Canvas gadget
Select EventType()
Case #PB_EventType_LeftButtonDown
If StartDrawing(ImageOutput(GameBackgroundImage))
DrawingMode(#PB_2DDrawing_Default)
DrawAlphaImage(ImageID(GameTextImage), MousePosX, MousePosY, 50)
StopDrawing()
EndIf
Case #PB_EventType_MouseMove
If StartDrawing(CanvasOutput(1))
DrawingMode(#PB_2DDrawing_Default)
DrawImage(ImageID(GameBackgroundImage), 0, 0, 800, 600)
MousePosX = GetGadgetAttribute(1, #PB_Canvas_MouseX)
MousePosY = GetGadgetAttribute(1, #PB_Canvas_MouseY)
DrawingMode(#PB_2DDrawing_AlphaBlend)
DrawAlphaImage(ImageID(GameTextImage), MousePosX, MousePosY, 50)
StopDrawing()
EndIf
Case #PB_EventType_KeyUp
If GetGadgetAttribute (1,#PB_Canvas_Key) = #PB_Key_D
Debug "Works"
SetActiveWindow(0) ; <--- B.P. added this
EndIf
EndSelect
EndSelect
EndSelect
While WindowEvent() : Wend ; <---- B.P. added this
SetActiveGadget(1) ; <---- B.P. added this
Delay(1) ; <---- B.P. added this
Until Game_Window_Event = #PB_Event_CloseWindow
EndIf
;---------------------------------------------------------------------------------------------------
End
;---------------------------------------------------------------------------------------------------
B.P.