Canvas gadget keyboard handling?

Just starting out? Need help? Post your questions and find answers here.
User avatar
J@ckWhiteIII
Enthusiast
Enthusiast
Posts: 183
Joined: Fri May 25, 2012 7:39 pm

Canvas gadget keyboard handling?

Post 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
User avatar
kenmo
Addict
Addict
Posts: 2069
Joined: Tue Dec 23, 2003 3:54 am

Re: Canvas gadget keyboard handling?

Post 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. 
User avatar
Danilo
Addict
Addict
Posts: 3036
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: Canvas gadget keyboard handling?

Post 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
User avatar
J@ckWhiteIII
Enthusiast
Enthusiast
Posts: 183
Joined: Fri May 25, 2012 7:39 pm

Re: Canvas gadget keyboard handling?

Post 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? :/
User avatar
J@ckWhiteIII
Enthusiast
Enthusiast
Posts: 183
Joined: Fri May 25, 2012 7:39 pm

Re: Canvas gadget keyboard handling?

Post 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
User avatar
kenmo
Addict
Addict
Posts: 2069
Joined: Tue Dec 23, 2003 3:54 am

Re: Canvas gadget keyboard handling?

Post 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).
User avatar
J@ckWhiteIII
Enthusiast
Enthusiast
Posts: 183
Joined: Fri May 25, 2012 7:39 pm

Re: Canvas gadget keyboard handling?

Post 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
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Canvas gadget keyboard handling?

Post by IdeasVacuum »

Add SetActiveGadget(1) after CanvasGadget(1,....)
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
User avatar
J@ckWhiteIII
Enthusiast
Enthusiast
Posts: 183
Joined: Fri May 25, 2012 7:39 pm

Re: Canvas gadget keyboard handling?

Post 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 :shock:

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 :/
IdeasVacuum
Always Here
Always Here
Posts: 6426
Joined: Fri Oct 23, 2009 2:33 am
Location: Wales, UK
Contact:

Re: Canvas gadget keyboard handling?

Post 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.
IdeasVacuum
If it sounds simple, you have not grasped the complexity.
Polo
Addict
Addict
Posts: 2422
Joined: Tue May 06, 2003 5:07 pm
Location: UK

Re: Canvas gadget keyboard handling?

Post 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.
User avatar
J@ckWhiteIII
Enthusiast
Enthusiast
Posts: 183
Joined: Fri May 25, 2012 7:39 pm

Re: Canvas gadget keyboard handling?

Post 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?
User avatar
kenmo
Addict
Addict
Posts: 2069
Joined: Tue Dec 23, 2003 3:54 am

Re: Canvas gadget keyboard handling?

Post 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.
User avatar
J@ckWhiteIII
Enthusiast
Enthusiast
Posts: 183
Joined: Fri May 25, 2012 7:39 pm

Re: Canvas gadget keyboard handling?

Post 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 :)
User avatar
BasicallyPure
Enthusiast
Enthusiast
Posts: 539
Joined: Thu Mar 24, 2011 12:40 am
Location: Iowa, USA

Re: Canvas gadget keyboard handling?

Post 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.
BasicallyPure
Until you know everything you know nothing, all you have is what you believe.
Post Reply