[Resolved - not a bug] Possible bug with If> statement

Technical support and scripting issues

Moderators: JRL, Dorian (MJT support)

Post Reply
User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

[Resolved - not a bug] Possible bug with If> statement

Post by jpuziano » Sun Dec 02, 2012 12:01 am

Hi Marcus,

OK, I may have a bug for you here.

Run the following script which watches for you to press a Hot Key... the ALT key and the ` key (the key below the ESC key) simultaneously.

In addition, after the key combo has been pressed, it also checks to MAKE SURE that you have released both of those keys... before initiating an action.

If you run the code below, you should find it solid... in that, once you hold down ALT and also hold down `... then as long as you KEEP holding down ALT, the Action will NOT TRIGGER... it will wait until you have released the ALT key.

Code: Select all

//Values below used for Hot Keys

//VK_SHIFT?(16) SHIFT key
Let>VK_SHIFT=16

//VK_CONTROL?(17) CTRL key
Let>VK_CONTROL=17

//VK_MENU?(18) ALT key
Let>VK_MENU=18

//VK_OEM_3?(192)
//Used for miscellaneous characters; it can vary by keyboard.
//Windows 2000/XP: For the US standard keyboard, the '`~' key
Let>VK_OEM_3=192



//app spends most of its time in this loop... waiting for something to happen
Label>Loop
Wait>0.01

//use GetKeyState for hot key instead of "RegisterHotKey" as no debounce problem
//result values will be as follows:

//SHIFT(VK_SHIFT) or ALT(VK_MENU) or CTRL(VK_CONTROL)     down: 65408 or 65409  up: 0 or 1
//so  key is down if result>1
//and key is up   if result<2

//Check if '`~' key is down
LibFunc>user32,GetKeyState,result,VK_OEM_3
If>result<0
  //Yes '`~' key is down so now check if ALT(VK_MENU) is down
  LibFunc>user32,GetKeyState,result,VK_MENU
  If>result>1
    //yes ALT was down so at this point we know hot key was pressed

    //ensure VK_USER_CHOSEN_HOTKEY is up first
    Label>wait_for_VK_USER_CHOSEN_HOTKEY_to_be_up
    LibFunc>user32,GetKeyState,result,VK_OEM_3
    If>result<0,wait_for_VK_USER_CHOSEN_HOTKEY_to_be_up

    //finally wait for ALT key to be up
    Label>wait_for_ALT_to_be_up
    LibFunc>user32,GetKeyState,result,VK_MENU
    //following line does not work consistantly
    //If>result>1,wait_for_ALT_to_be_up
    //following line does not work consistantly
    //If>result>65407,wait_for_ALT_to_be_up
    //Only the following line works consistantly
    If>{(%result%<>0) AND (%result%<>1)},wait_for_ALT_to_be_up
    //so now initiate Action
    GoSub>Action
  EndIf
EndIf
Goto>Loop


SRT>Action
  MDL>You pressed and released ALT + `
  Exit>0
END>Action
//following line does not work consistantly
//If>result>1,wait_for_ALT_to_be_up
//following line does not work consustantly
//If>result>65407,wait_for_ALT_to_be_up
//Only the following line works consistantly
If>{(%result%0) AND (%result%1)},wait_for_ALT_to_be_up

While I am glad the green line above does work... I don't understand why the red lines do not.

Please comment out the green line and uncomment one of the red lines and test it.

You can press the Hot Key... and even though you KEEP holding the ALT key down... if you alternately press and release the ` key... you can get it to trigger the Action... without ever releasing the ALT key.

This drove me insane until I found a solution... and I have been meaning to post about this for a long time... so here it is.

Why does it behave like this Marcus? Is there some kind of edge case bug with the If> statement?
Last edited by jpuziano on Thu Dec 06, 2012 3:57 pm, edited 3 times in total.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
Rain
Automation Wizard
Posts: 550
Joined: Tue Aug 09, 2005 5:02 pm
Contact:

Post by Rain » Sun Dec 02, 2012 1:28 am

I can confirm this behavior on my Windows 7 Ultimate machine running MS 13.2.4.

User avatar
Marcus Tettmar
Site Admin
Posts: 7395
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Wed Dec 05, 2012 8:17 pm

On my keyboard the ` key by Esc didn't have any effect on your code, so I guess my keyboard is different for OEM_3. So I used a different key instead - I set it to use F11.

I was unable to replicate.

In any case you are not comparing apples with apples. Your first two lines equate to an OR condition

If>result>1,dothing
If>result>65407,dothing

Equates to:

if (result>1) OR (result >654067)

Which of course would resolve true for any value greater than 1.

2 would match
3 would match
...
654067 would match (the first condition)
654068 would match
n would match

So this can be reduced to simply:

if>result>1

You're comparing that to:

if (result0) and (result1 )

Which is the same as saying result can be anything other than 0 or 1. -1 would match, -127 would match, 2 would match, 65407 would match, n would match.

It is the same as saying:

If (result 1)

The most glaring difference then is that this one accepts negative numbers, whereas the two IFs version does not.

So the latter accepts less than 0 or greater than 1. Whereas the former would trigger only for any value greater than 1.

So the two versions of code are not the same.

I therefore don't see any evidence of a bug in IF here. What I see - given that I can't reproduce it anyway - is that your single line version triggers for negative values, whereas your two line version doesn't.

The obvious way to test it is to try various values of result and hard code them and you'll see all the outcomes.

I feel it's therefore more likely we're seeing something about the key state or the particular key. And the logic tells me you're getting a negative value which is ignored when you switch to the two line version.

I for one can't make the first GetKeyState trigger at all but that may be that OEM_3 is something different on my laptop and I don't know what it is.

It's more likely you've misunderstood how GetKeyState works. Here's what Microsoft says about the result of GetKeyState:
Type: SHORT
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.
So you need to be looking at the high-order bit, not the entire value.
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Thu Dec 06, 2012 7:43 am

Hi Marcus,

Please run the following code... and while you do, alternately hold down and release the ALT key and also occasionally tap any other key and release it:

Code: Select all

//VK_MENU?(18) ALT key
Let>VK_MENU=18

Let>count=0

Label>Loop
Let>count=count+1
LibFunc>user32,GetKeyState,result,VK_MENU
Message>result
If>count<10000,Loop

MDL>DONE!
You should be able to verify that ONLY four different values are returned for result:

These values while the ALT key is up:
0
1

And these values while the ALT key is down:
65408
65409

So now run this example code...

Code: Select all

//VK_MENU?(18) ALT key
Let>VK_MENU=18

MDL>After clicking OK, hold the ALT key down CONTINUOUSLY and alternately tap and release other keys

Wait>3

Label>wait_for_ALT_to_be_up

LibFunc>user32,GetKeyState,result,VK_MENU

//Possible values for result are:
// 0 or 1 when ALT key is up
// 65408 or 65409 when ALT key is down

Message>result

If>{(%result%<>0) AND (%result%<>1)},wait_for_ALT_to_be_up

MDL>You finally released the ALT key!
The above code works fine... it won't let you out of the loop until you actually release the ALT key.

Now run the following code...

Code: Select all

//VK_MENU?(18) ALT key
Let>VK_MENU=18

MDL>After clicking OK, hold the ALT key down CONTINUOUSLY and alternately tap and release other keys

Wait>3

Label>wait_for_ALT_to_be_up

LibFunc>user32,GetKeyState,result,VK_MENU

//Possible values for result are:
// 0 or 1 when ALT key is up
// 65408 or 65409 when ALT key is down

Message>result

If>result>1,wait_for_ALT_to_be_up

MDL>You finally released the ALT key! Didn't you?
After a few keypresses on other keys... even though you CONTINUOUSLY hold down the ALT key, the above code will FAIL and let you out of the loop even though you did not release the ALT key. The only line that is different from the example that works properly is the following line:

If>result>1,wait_for_ALT_to_be_up

To recap, since we are holding down the ALT key CONTINUOUSLY, the only two values it can POSSIBLY return for result are:

// 65408 or 65409 when ALT key is down

And the way I see it...

65408 is greater than 1 so it should go to wait_for_ALT_to_be_up
65409 is greater than 1 so it should go to wait_for_ALT_to_be_up

So it should keep waiting... but it does not.

Again, the question is why?
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
Marcus Tettmar
Site Admin
Posts: 7395
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Thu Dec 06, 2012 8:42 am

So now change the last line of your last (failing) script to this:

MDL>You finally released the ALT key! Didn't you (%result%)?

This will tell us what the value of result was when it jumped out of the loop.

If you are right and there's a bug with If you'll see a value greater than 1. But of course there is no bug with if and what I saw was -127.

I held ALT down continuously and tapped other keys. I just happened to hit the I key and the script popped out of the loop and showed:

You finally released the ALT key! Didn't you (-127)?

So I refer you back to my original response. There IS NO bug with If. Result was -127 and therefore the If logic performed CORRECTLY.

You are simply making false assumptions about how GetKeyState works. Documentation is here: http://msdn.microsoft.com/en-gb/library ... s.85).aspx
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Thu Dec 06, 2012 9:52 am

Hi Marcus,
Marcus wrote:You are simply making false assumptions about how GetKeyState works. Documentation is here: http://msdn.microsoft.com/en-gb/library ... s.85).aspx
That's exactly right... In testing I did not see -127 but there it is. So as it turns out, the following line is the way to go for a valid reason:

If>{(%result%0) AND (%result%1)},wait_for_ALT_to_be_up

Because this takes care of whatever other values might be returned (like -127) that do NOT correspond to the ALT key being up.

0 or 1 both indicate the ALT key is up. If result is anything other than that, we keep waiting... perfect.

Once a false assumption is made, it is sometimes hard to see past it.

Thanks for explaining Marcus... and take care.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

Post Reply
Sign up to our newsletter for free automation tips, tricks & discounts