sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    OnKeyDown: getting the charcater value from key

    Scheduled Pinned Locked Moved Developers' Forum
    32 Posts 7 Posters 1.7k Views 7 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • fredo6F Offline
      fredo6
      last edited by

      @dan rathbun said:

      This kind of thing was discussed years ago, in a topic that Jim posted his key inspector tool.

      Dan,

      I had already browsed some of these threads. Thanks.

      I think for tracking Shoft, Ctrl and arrows, it is clear.

      But what I am trying to do is simplyget a natural character(like the digits [0-9)) and I really do not understand the logic.

      • the key seems to be the ascii value, but only on main keyboard and for the main key (i.e. ignoring the Shift state)
      • the flag value is for me totally cryptic (in addition it is very different on keydown and keyup for the same key).

      I guess there must be some logic encoded Under the Hood and that's what I am trying to understand.

      Fredo

      1 Reply Last reply Reply Quote 0
      • Dan RathbunD Offline
        Dan Rathbun
        last edited by

        @fredo6 said:

        • the flag value is for me totally cryptic (in addition it is very different on keydown and keyup for the same key).

        Oh yes it is quite clear that there are issues, and it IS a pain in the butt.

        I remember vaguely someone explaining how the flag bit masks worked, and how to | and & them properly.

        It would be nicve if the API creates a KeyFlag subclass of integer with methods like:
        .shift? .control? .command? .alt?
        ... etc.

        I'm not here much anymore.

        1 Reply Last reply Reply Quote 0
        • A Offline
          Anton_S
          last edited by

          @fredo6 said:

          But what I am trying to do is simplyget a natural character(like the digits [0-9)) and I really do not understand the logic.

          @fredo6 said:

          My goal was to see if the keys could be transformed into characters in order to trap the 0-9, =, +, -, *, / characters.

          The tool onKeyDown method returns virtual key constant value, key repeat, key flags, and view instance.

          Here is the list of Virtual Key Codes on Windows: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx

          key.chr will return the character of the value.
          for instance 87.chr returns 'W'

          You can filter the keys like this:

          def onKeyDown(key, repeat, flags, view)
            if %w(1 2 3 4 5 6 7 8 9 0 = + - * /).include?(key.chr)
              # process code here
            else
              return
            end
          end
          

          How to convert numeric decimal to hexadecimal:
          87.to_s(16) # => '57' or 0x57 which can be found in the virtual key codes list.

          When viewing flags you might first want to convert them to hexadecimal.
          The flags don't give you anything special about the key.
          Here is what they give: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646267(v=vs.85).aspx#_win32_Keystroke_Message_Flags

          1 Reply Last reply Reply Quote 0
          • A Offline
            Anton_S
            last edited by

            Apparently key.chr doesn't return proper characters for all values. For that, we might want to sett up a hash of values and characters.

            CHARS = {
            # Standard keys
            0x30 => '0'
            0x31 => '1'
            0x32 => '2'
            0x33 => '3'
            0x34 => '4'
            0x35 => '5'
            0x36 => '6'
            0x37 => '7'
            0x38 => '8'
            0x39 => '9'
            0xBD => '-'
            0xBB => '+'
            0x0D => '=' # use enter key for =
            # Numpads
            0x60 => '0'
            0x61 => '1'
            0x62 => '2'
            0x63 => '3'
            0x64 => '4'
            0x65 => '5'
            0x66 => '6'
            0x67 => '7'
            0x68 => '8'
            0x69 => '9'
            0x6B => '+'
            0x6D => '-'
            0x6A => '*'
            0x6F => '/'
            }
            

            So the filter set up would look like this now.

            def onKeyDown(key, repeat, flags, view)
              key_char = CHARS[key]
              return unless key_char
              # process
            end
            

            This technique should work on Windows. I don't know about Macs though.

            1 Reply Last reply Reply Quote 0
            • fredo6F Offline
              fredo6
              last edited by

              Anton,

              Thanks very much.
              I have the virtual keycodes on Mac too.

              The main issue is that these map physical keys, so it will be very difficult to have a reliable result for non-US keyboards for the the digits for instance, which may require a Shift (like on French keyboard).

              And you are right that flags does not bring much info.

              Fredo

              1 Reply Last reply Reply Quote 0
              • tt_suT Offline
                tt_su
                last edited by

                Yea, the Tool class return key codes, not character codes. And they are system dependant.

                I'm not sure how you'd get the resulting character that would be produced, though should think there should be some system API for this. I'd have to search for that.

                1 Reply Last reply Reply Quote 0
                • Dan RathbunD Offline
                  Dan Rathbun
                  last edited by

                  @Anton: Would using ToUnicode() be better than ToAscii() ?

                  I'm not here much anymore.

                  1 Reply Last reply Reply Quote 0
                  • A Offline
                    Anton_S
                    last edited by

                    @dan rathbun said:

                    @Anton: Would using ToUnicode() be better than ToAscii() ?

                    I just tested and seen no difference. I think it doesn't matter much.

                    1 Reply Last reply Reply Quote 0
                    • tt_suT Offline
                      tt_su
                      last edited by

                      @dan rathbun said:

                      @Anton: Would using ToUnicode() be better than ToAscii() ?

                      Indeed this appear to be the correct function to use:
                      http://msdn.microsoft.com/en-us/library/windows/desktop/ms646320(v=vs.85.aspx

                      @unknownuser said:

                      Translates the specified virtual-key code and keyboard state to the corresponding Unicode character or characters.

                      Though, it probably produce a UTF-16LE string, transposing to UTF-8 would probably be best for interoperability with the rest of the SketchUp environment.

                      1 Reply Last reply Reply Quote 0
                      • A Offline
                        Anton_S
                        last edited by

                        Nah, both of them are encoded in US-ASCII. 😕
                        adding char.force_encoding('UTF-8') should do the tick, aint it?

                        1 Reply Last reply Reply Quote 0
                        • tt_suT Offline
                          tt_su
                          last edited by

                          @anton_s said:

                          Nah, both of them are encoded in US-ASCII. 😕

                          You're talking about ToAscii?
                          I was looking at ToUnicode.

                          @anton_s said:

                          adding char.force_encoding('UTF-8') should do the tick, aint it?

                          I'd be careful with force_encoding - it should only be used if you have raw binary data representing a string or if you know the string is incorrectly encoded. Otherwise one should transpose the en encoding.
                          foo = bar.encode("UTF-8")

                          1 Reply Last reply Reply Quote 0
                          • A Offline
                            Anton_S
                            last edited by

                            @tt_su said:

                            You're talking about ToAscii?
                            I was looking at ToUnicode.

                            Yes, the ToUnicode and ToAscii both return same formatted Ruby strings, but on the actual approach they don't. When I initially created a buffer char = 0.chr*2 it was already formatted in US-ASCII. The ToUnicodeand ToAscii simply fills the the specified buffer with ascii/unicode characters without changing the format of the Ruby string.

                            Changing char = 0.chr*2 to char= ' ' will initially create a UTF-8 formatted string, rather than the US-ASCII. The format remains unchanged when the ToUnicode/ToAscii functions fills the char string.

                            @tt_su said:

                            I'd be careful with force_encoding...

                            For some reason force_encoding even managed to crash SketchUp at some points when testing key_test.

                            1 Reply Last reply Reply Quote 0
                            • Dan RathbunD Offline
                              Dan Rathbun
                              last edited by

                              Ya'all need to be careful where testing string encoding, until MR1 comes out.
                              The correct default encoding is not properly set in MR0.

                              I'm not here much anymore.

                              1 Reply Last reply Reply Quote 0
                              • D Offline
                                driven
                                last edited by

                                @dan rathbun said:

                                The correct default encoding is not properly set in MR0.

                                if anyones prepared to admit it...

                                the other issue is why these things are so difficult on a mac...

                                apple doesn't support key logging and goes out of it's way to prevent it occurring...

                                apple does allow it IF it's for assistive devices to aid those with disabilities...

                                if you want to use 'assistive devices api' to do ordinary tasks, you need to connivence the 'admin' user to turn it on.

                                mac folk are reluctant to do this as it's system wide, and would enable malicious 'key loggers' to, key-log...

                                john

                                learn from the mistakes of others, you may not live long enough to make them all yourself...

                                1 Reply Last reply Reply Quote 0
                                • Dan RathbunD Offline
                                  Dan Rathbun
                                  last edited by

                                  Err.. found a Ruby Core bug.
                                  Even after setting Encoding::default_internal="UTF-8"
                                  the Integer#chr() method does not return a string in the default internal encoding.

                                  .. however there is a workaround. Ruby 2.0's Integer#chr() method now takes an encoding argument, so, this:
                                  char = 0.chr(Encoding::default_internal)*2
                                  or this:
                                  char = 0.chr("UTF-8")*2
                                  WILL work.

                                  I'm not here much anymore.

                                  1 Reply Last reply Reply Quote 0
                                  • A Offline
                                    Anton_S
                                    last edited by

                                    @dan rathbun said:

                                    char = 0.chr("UTF-8")*2

                                    Nice find Dan 👍 I re-edited the Ruby code above.

                                    1 Reply Last reply Reply Quote 0
                                    • Dan RathbunD Offline
                                      Dan Rathbun
                                      last edited by

                                      @anton_s said:

                                      @dan rathbun said:

                                      char = 0.chr("UTF-8")*2

                                      Nice find Dan 👍 I re-edited the Ruby code above.

                                      But you did not enclosed the encoding nickname string in quotes. That'll raise a NameError exception ("uninitialized constant UTF".)

                                      I'm not here much anymore.

                                      1 Reply Last reply Reply Quote 0
                                      • A Offline
                                        Anton_S
                                        last edited by

                                        Okay, I figured a way to get key via the Windows API. The code below will give you the key code of the exact character that your pressing. For instance,

                                        • Pressing 1 yields 1; Pressing Shift-1 returns !.
                                        • Pressing w yields w; Pressing Shift-w returns W.

                                        I guess it should work properly on the Français keyboard as well. Test it out.

                                        require 'Win32API'
                                        
                                        class KeyTest
                                        
                                          GetKeyboardState = Win32API.new('User32', 'GetKeyboardState', 'P', 'L')
                                          ToAscii          = Win32API.new('User32', 'ToAscii', 'LLPPL', 'L')
                                          ToUnicode        = Win32API.new('User32', 'ToUnicode', 'LLPPLL', 'L')
                                        
                                          def onKeyDown(key, repeat, flags, view)
                                            buffer = 0.chr*256
                                            char = 0.chr('UTF-8')*2 # maintain UTF-8 encoding
                                            GetKeyboardState.call(buffer)
                                            res = ToUnicode.call(key, repeat, buffer, char, char.size, 0)
                                            #res = ToAscii.call(key, repeat, buffer, char, 0)
                                            return if res == 0
                                            char.strip!
                                            p char
                                            # process
                                          end
                                        
                                        end
                                        
                                        unless file_loaded?(__FILE__)
                                          UI.menu('Plugins').add_item('Key Test'){
                                            Sketchup.active_model.select_tool(KeyTest.new)
                                          }
                                        end
                                        
                                        
                                        

                                        You need Win32API.so for SU2013 and below though.


                                        Place in the Plugins folder. Access: Plugins > Key Test

                                        1 Reply Last reply Reply Quote 0
                                        • A Offline
                                          Anton_S
                                          last edited by

                                          @dan rathbun said:

                                          . That'll raise a NameError exception ("uninitialized constant UTF".)

                                          Oh 😆 Fixed

                                          1 Reply Last reply Reply Quote 0
                                          • tt_suT Offline
                                            tt_su
                                            last edited by

                                            @dan rathbun said:

                                            Err.. found a Ruby Core bug.
                                            Even after setting Encoding::default_internal="UTF-8"
                                            the Integer#chr() method does not return a string in the default internal encoding.

                                            sigh "Unicode support" grumble kicks Ruby on the shin

                                            1 Reply Last reply Reply Quote 0
                                            • 1
                                            • 2
                                            • 2 / 2
                                            • First post
                                              Last post
                                            Buy SketchPlus
                                            Buy SUbD
                                            Buy WrapR
                                            Buy eBook
                                            Buy Modelur
                                            Buy Vertex Tools
                                            Buy SketchCuisine
                                            Buy FormFonts

                                            Advertisement