Saturday 30 August 2014

Testing for modifier keys in FileMaker

A couple of days ago we had a developer do something like this

If ( Get ( ActiveModifierKeys = 4 ) ) //Control Key
—do stuff
End If

In testing, it worked for him, and didn’t work for me.  Why, when I was holding down the control key, did it not work for me?  Well, Get ( ActiveModifierKeys ) returns an integer, based on the sum of all the modifier keys, and I had my caps lock on accidentally, which caused Get ( ActiveModifierKeys ) to return 6, and therefore not run the intended code.  So a little analysis (and a better test for which keys are down) is necessary here.

From FileMaker’s documentation :
The number returned is calculated by summing numbers representing each modifier key being pressed. The values assigned to the keys are:

Shift = 1
Caps Lock = 2
Ctrl (Windows) and Control (OS X) = 4
Alt (Windows) and Option (OS X) = 8
Command (OS X) = 16

OK, so we have numbers that are powers of two, so obvious FileMaker is assigning each modifier key to a “bit” of the integer byte value, and we can therefore create a better test, by seeing if a specific “bit” is set.  As so often happens in the FileMaker World, someone else already did it.  In this case, it was Mikhail Edoshin, and he wrote some nice custom functions to handle this.  

Custom functions to simplify reading the current state of modifier keys

I highly recommend browsing Mikail’s stuff in the web archive, he’s written some really cool stuff.


To get back to topic at hand, Mikhail’s custom function:
Function: Bit Is Set ( number ; bit ) =
Mod( Div( number; 2^( bit - 1 ) ); 2 )

Very elegant!

From this Mikhail wrote some more custom functions

Function: Shift Is Pressed()=
Bit is Set( Get( ActiveModifierKeys ); 1 )

Function: Caps Lock Is Pressed()=
Bit is Set( Get( ActiveModifierKeys ); 2 )

Function: Control Is Pressed()=
Bit is Set( Get( ActiveModifierKeys ); 3 )

Function: Option Is Pressed()=
Bit is Set( Get( ActiveModifierKeys ); 4 )

Function: Command Is Pressed()=
Bit is Set( Get( ActiveModifierKeys ); 5 )

For Windows machines, “ALT” = Mac “Option” Key, and “Windows” Key = Mac “Command” key. 

So, back to the original problem, changing the code to this

If ( Control Is Pressed )
—do stuff
End If

does two things : 
1) reads like English, and 
2) it doesn’t matter what other modifier keys are being pressed, it will correctly determine if the “Control” key is one of them.

It's a subtle thing, but it adds the kind of polish to your code that distinguishes professionals from amateurs.

No comments:

Post a Comment