Announcement

Collapse
No announcement yet.

Latest GetKeyState declaration..

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Latest GetKeyState declaration..

    Latest Win32api.inc declares GetKeyState function as INTEGER. Should
    be LONG. I know Win32.hlp says "SHORT", but the function returns the
    states as LOWRD/HIWRD, not LOBYT/HIBYT, so Win32.hlp is wrong there.

    Tried with the new declare, but get same value back in both LOBYT/HIBYT.
    Changed back to old declaration and get correct values in LOWRD/HIWRD.
    So I think it should be:
    Code:
    DECLARE FUNCTION GetKeyState LIB "USER32.DLL" ALIAS "GetKeyState" (BYVAL nVirtKey AS LONG) AS LONG
    And, in case someone else has gotten same problem: MoveMemory is now a sub,
    declared with BYREF addresses "AS ANY". Has broken a lot of my code, but
    found that one can use "BYVAL (x + y)", instead of previous simple "x + y".

    Now all I have to do is to encapsulate the addresses with BYVAL(address) in
    a couple of hundred places, where I have used MoveMemory ..


    ------------------

  • #2
    Borje --
    About GetKeyState.
    Do you like LoWrd(GetKeyState(...)) AND &H8000) instead of GetKeyState(...) < 0 ?

    ------------------
    E-MAIL: [email protected]

    Comment


    • #3
      Borje --

      > I know Win32.hlp says "SHORT" (...)
      > so Win32.hlp is wrong there.

      MSDN also lists GetKeyState as returning a SHORT, so I suspect that that's correct.

      > the function returns the
      > states as LOWRD/HIWRD, not LOBYT/HIBYT,

      I don't see that in the Microsoft docs. Did you determine that experimentally, or...?

      [added later]

      I re-read your message and I see that you did perform an experiment. Hmmm...

      I don't see anything in the docs about words or bytes... just the low- and high-order bits of the return value, indicating whether or not the specified key is pressed. Can you post the code you used to test this?

      -- Eric


      ------------------
      Perfect Sync Development Tools
      Perfect Sync Web Site
      Contact Us: mailto:[email protected][email protected]</A>



      [This message has been edited by Eric Pearson (edited July 12, 2001).]
      "Not my circus, not my monkeys."

      Comment


      • #4
        MSDN shows the GetKeyState result as INTEGER, which matches the declaration
        in Microsoft's SDK. The MS Knowledgebase does not report any related bugs.
        Given that GetKeyState is a commonly-used function that has been around for
        a very long time, it seems unlikely to me that the declaration and docs are
        wrong. If you have evidence to the contrary, do let us know.

        ------------------
        Tom Hanlin
        PowerBASIC Staff

        Comment


        • #5
          Declared as INTEGER, following test shows all members returns 0 or 1,
          indicating toggled state for CTRL. Following the docs, HIBYT indicates
          UP/DOWN and LOBYT toggled state. I cannot get this to work properly if
          function is declared as INTEGER, but works fine when declared as LONG.

          Declared as LONG, like it used to be, you get proper, useful values
          for toggled state plus up/down state. If GetKeyState really returns
          INTEGER, HIWRD wouldn't work at all, right? So it must return a 4-byte
          value. Think Win32.hlp is wrong. Seems like the HIWRD member also
          contains useful info when combined keys, Ctrl+key is pressed.

          Or maybe I'm using it wrong? In any event, declared as INTEGER it breaks
          all my code and I cannot get it to work with up/down state. As LONG, all
          works fine..
          Code:
          '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
          ' Declares
          '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
          #COMPILE EXE
          #INCLUDE "WIN32API.INC"
          DECLARE CALLBACK FUNCTION DlgProc() AS LONG
           
          '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
          ' Create dialog and controls, etc
          '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
          FUNCTION PBMAIN () AS LONG
           LOCAL hDlg AS LONG
            DIALOG NEW 0, "GetKeyState test",,, 195, 50, %WS_CAPTION OR %WS_SYSMENU, 0 TO hDlg
            CONTROL ADD BUTTON, hDlg, 10, "Toggle CTRL and then press me",   4,  4, 180, 14, %WS_TABSTOP
            DIALOG SHOW MODAL hDlg CALL DlgProc
          END FUNCTION
           
          '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
          ' Main callback
          '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
          CALLBACK FUNCTION DlgProc() AS LONG
            IF CBMSG = %WM_COMMAND THEN
               IF CBCTL = 10 THEN _
                  MSGBOX "HIBYT: " + STR$(HIBYT(GetKeyState(%VK_CONTROL))) + $CRLF + _
                         "LOBYT: " + STR$(LOBYT(GetKeyState(%VK_CONTROL))) + $CRLF + _
                         "HIWRD: " + STR$(HIWRD(GetKeyState(%VK_CONTROL))) + $CRLF + _
                         "LOWRD: " + STR$(LOWRD(GetKeyState(%VK_CONTROL)))
            END IF
          END FUNCTION

          ------------------

          Comment


          • #6
            In current MSDN http://msdn.microsoft.com/library/de...binpt_4z51.asp
            SHORT GetKeyState(
            int nVirtKey // virtual-key code
            );

            WinUser.h

            SHORT WINAPI GetKeyState(int nVirtKey);
            SHORT WINAPI GetAsyncKeyState(int vKey);

            Vb6:
            Public Declare Function GetKeyState Lib "user32" Alias "GetKeyState" (ByVal nVirtKey As Long) As Integer

            Old Win32.hlp
            SHORT GetKeyState(int nVirtKey // virtual-key code
            );

            SHORT GetAsyncKeyState(int vKey // virtual-key code
            );

            [This message has been edited by Semen Matusovski (edited July 12, 2001).]

            Comment


            • #7
              Okay, so I tested. When declared as WORD, it works like expected
              and I get up/down plus toggled state propely. The usual mess with
              integers. In other words - it looks like it should be:
              Code:
              DECLARE FUNCTION GetKeyState LIB "USER32.DLL" ALIAS "GetKeyState" (BYVAL nVirtKey AS LONG) AS WORD

              ------------------

              Comment


              • #8
                Borje --

                If you define the return value of the GetKeyState API as an integer, then using HIWRD on the return value is bound to return confusing results, because there is no "high word".

                Try displaying BIN$(GetKeyState(%VK_CONTROL),16) and you will see that using INTEGER works as documented.

                I don't know why all those other bits are changing -- I didn't look into it -- but pretty clearly the high and low bits are changing as documented.

                -- Eric


                ------------------
                Perfect Sync Development Tools
                Perfect Sync Web Site
                Contact Us: mailto:[email protected][email protected]</A>



                [This message has been edited by Eric Pearson (edited July 12, 2001).]
                "Not my circus, not my monkeys."

                Comment


                • #9
                  Borje --

                  I see that you replied while I was composing my message.

                  As far as WORD vs. INTEGER goes, we are talking about individual bits, not a numeric value, so the distinction of signed vs. unsigned is meaningless. Use whichever you like.

                  -- Eric

                  ------------------
                  Perfect Sync Development Tools
                  Perfect Sync Web Site
                  Contact Us: mailto:[email protected][email protected]</A>
                  "Not my circus, not my monkeys."

                  Comment


                  • #10
                    Test program shows different result if function is declared AS INTEGER
                    or WORD. AS INTEGER, it doesn't work properly. AS WORD, it does - I get
                    both up/down and toggled state. Same with previous declaration, AS LONG.

                    This is no problem if to write code for myself. I can change the declaration
                    here and get all working. If to share code with PB community, it's another
                    story. Previous AS LONG fooled me to use HIWRD/LOWRD, which I now see is
                    wrong, but in any case it would be nice to be able to write code that all
                    can share and use without problem.


                    ------------------

                    Comment


                    • #11
                      The return value specifies the status of the specified virtual key, as follows:

                      If the high-order bit is 1, the key is down; otherwise, it is up.
                      If the low-order bit is 1, the key is toggled. A key, such as the CAPS LOCK key,
                      is toggled if it is turned on. The key is off and untoggled if the low-order bit
                      is 0. A toggle key's indicator light (if any) on the keyboard will be on when the
                      key is toggled, and off when the key is untoggled.

                      In other words, you want to check up/down using BIT(result, 15) and "toggled"
                      using BIT(result, 0) ...

                      ------------------
                      Tom Hanlin
                      PowerBASIC Staff

                      Comment


                      • #12
                        Okay, so test now also shows I am a complete idiot..

                        Bits and bytes. One cannot use HIBYT to test a BIT, right? Right!
                        One definitely shouldn't use HIWRD. Best way is probably to use AND
                        operator. Using "IF (GetKeyState(%VK_CONTROL) AND &H10000) THEN" work
                        with all kinds of declarations for function, INTEGER, WORD or LONG.

                        Looking through many samples, I see many of us have used wrong way.
                        Think following should be correct way (works for me, anyway):
                        Code:
                        To test hi BIT:  (GetKeyState(%VK_CONTROL) AND &H10000)
                        to test low BIT: (GetKeyState(%VK_CONTROL) AND &H1)
                        Yes Tom, of course you are right. Using BIT function means one has to
                        use a variable though, so AND -way is easier, IMHO.


                        ------------------

                        Comment


                        • #13
                          Borje --

                          > &H10000

                          I believe you want &H80 not &H10000. &h80 looks like this in binary:

                          10000000

                          ...which is what I was seeing when the Ctrl-key was held down.

                          I guess in this case "high bit" means "the high bit of the first byte", although the high bit of the second byte (&h8000) also appears to change.

                          -- Eric


                          ------------------
                          Perfect Sync Development Tools
                          Perfect Sync Web Site
                          Contact Us: mailto:[email protected][email protected]</A>

                          [This message has been edited by Eric Pearson (edited July 12, 2001).]
                          "Not my circus, not my monkeys."

                          Comment


                          • #14
                            You are absolutely right, Eric - Thanks a lot! Got lost in binary
                            djungel there. So, correct way should be:
                            Code:
                            To test hi BIT:  (GetKeyState(%VK_CONTROL) AND &H80)
                            To test low BIT: (GetKeyState(%VK_CONTROL) AND &H1)
                            Looking through samples in Sorce Code forum, I see that many of us
                            need to revise our GetKeyState code "a bit"..


                            ------------------

                            Comment


                            • #15
                              Borje;

                              In my win32api.inc file the declaration is :

                              Code:
                              DECLARE FUNCTION GetKeyState LIB "USER32.DLL" ALIAS "GetKeyState" (BYVAL nVirtKey AS LONG) AS LONG
                              I don't remember if it came that way or if I changed it, but the
                              declare above works alright with my app.



                              ------------------
                              Chris Boss
                              Computer Workshop
                              Developer of "EZGUI"
                              http://cwsof.com
                              http://twitter.com/EZGUIProGuy

                              Comment


                              • #16
                                Checking out the MSDN docs, it should be SHORT (or Integer in PB, rather than Long)

                                What will happen if Long is used ?

                                I have tested out the command and I can check the flags in the return value for some reason.

                                Can using Long cause a GPF ?


                                ------------------
                                Chris Boss
                                Computer Workshop
                                Developer of "EZGUI"
                                http://cwsof.com
                                http://twitter.com/EZGUIProGuy

                                Comment


                                • #17
                                  Borje;

                                  I checked my code to see how I used GetKeyState and I did have problems
                                  with it and I added a fudge factor to get the right values back.

                                  I never noticed the return value was declared wrong in the win32api.inc
                                  file, so I was using Long instead of Integer.

                                  Here is the fudge factor I was using :

                                  Code:
                                  RV&=GetKeyState(VKey&)
                                  ROTATE LEFT RV&, 1
                                  RV&=RV& AND 3
                                  
                                  IF (RV& AND 1)=1 THEN 
                                     ' key is down
                                  ELSE
                                     ' key is down
                                  END IF
                                  This would give me a set Bit (low bit) if the key was down .

                                  I think the use of Long would allow the high bit to be correct, but the low bit
                                  (toggle flag) will be in the wrong place (not the low bit).

                                  I wasn't testing for the toggle bit, only the down key bit (high bit).




                                  ------------------
                                  Chris Boss
                                  Computer Workshop
                                  Developer of "EZGUI"
                                  http://cwsof.com
                                  http://twitter.com/EZGUIProGuy

                                  Comment


                                  • #18
                                    Originally posted by Chris Boss:
                                    What will happen if Long is used ?
                                    <snip>
                                    Can using Long cause a GPF ?
                                    As I understand it, a function that returns a LONG or INTEGER returns its result in a register (EAX I think, and not on the stack), so a GPF is unlikely or some of the folks in this thread would have been discussing a GPF.



                                    ------------------
                                    Lance
                                    PowerBASIC Support
                                    mailto:[email protected][email protected]</A>
                                    Lance
                                    mailto:[email protected]

                                    Comment


                                    • #19
                                      So, correct way should be:
                                      Code:
                                      To test hi BIT:  (GetKeyState(%VK_CONTROL) AND &H80)
                                      Umm, no. Try this:

                                      Code:
                                      To test hi BIT:  (GetKeyState(%VK_CONTROL) AND &H8000)
                                      Yes, you can get away with declaring GetKeyState AS LONG; in this specific case,
                                      it will work, it's just not the correct declaration.

                                      ------------------
                                      Tom Hanlin
                                      PowerBASIC Staff

                                      Comment


                                      • #20
                                        Tom --

                                        I agree that, according to the docs, &h8000 is the appropriate value.

                                        However, on my NT system, much more than the "high bit" is being set. The low bit toggles on and off exactly as documented, but all of the bits from &h80 to &h8000 change at the same time when the key is down.

                                        Code:
                                        0000000000000000  'key up
                                        1111111110000000  'key down
                                        That's where the &h80 came from. It's the high bit of the low byte.

                                        It works exactly the same way on my 98 and 2000 test system, but I didn't try 95.

                                        -- Eric


                                        ------------------
                                        Perfect Sync Development Tools
                                        Perfect Sync Web Site
                                        Contact Us: mailto:[email protected][email protected]</A>



                                        [This message has been edited by Eric Pearson (edited July 13, 2001).]
                                        "Not my circus, not my monkeys."

                                        Comment

                                        Working...
                                        X