Pages

Thursday, April 7, 2011

Create your own shortcuts in AX forms

In AX it is virtually impossible to control the shortcuts of buttons. Even though button properties like KeyTip indicate that you should be able to have some control, nothing really works.
Here is a tip on how you can catch special keyboard combinations yourself, and thus create your own shortcuts.

First you need to call a method from USER32.DLL to figure out if a certain key is pressed. You could for example implement this on the WinAPI class:

static boolean getKeyPressed(int _keyCode)
{
    DLL winApiDLL = new DLL('USER32');
    DLLFunction getKeyState = new DLLFunction(winApiDLL, 'GetAsyncKeyState');
    int result;
    ;

    getKeyState.returns(ExtTypes::WORD);
    getKeyState.arg(ExtTypes::DWORD);

    result = getKeyState.call(_keyCode);

    if ((result & 0x8000) == 0x8000)
        return true;
    else
        return false;
}
The method is called with what’s called a virtual key code, which is the code of the key you want to know is pressed or not. You can find a list of these keyboard codes on MSDN: http://msdn.microsoft.com/en-us/library/dd375731(VS.85).aspx

On your form you need to implement a method that is executed again and again while the form is idle. The method needs to check if your special key combination is pressed, do the action associated with the key and set the method up for next iteration.
It could look like this:

void myKeyboardCheck()
{
    #define.ALT(0x12)
    #define.O(0x4F)
    #define.timeOut(10)
    ;

    // Check if this form is the foreground window of Windows
    if (winApi::getForegroundWindow() == this.hWnd())
    {
        // Check if ALT + O is pressed
        if (WinApi::getKeyPressed(#ALT) && WinApi::getKeyPressed(#O))
        {
            // Check if the button is enable
d            if (MyVerySpecialButton.enabled())
            {
                MyVerySpecialButton.clicked();
            }
        }
    }
    // Reset timer
    this.setTimeOut('myKeyboardCheck', #timeOut, true);
}

In the run method of the form, I set the above method up for the first iteration, and I change the label of the button to reflect the desired shortcut:

MyVerySpecialButton.text(MyVerySpecialButton.labelText() +' (o)');
this.myKeyboardCheck();

If you need to implement this in more forms, you might want to build a small supporting framework in order to avoid repeating much of the same code over and over. The class DocuFileWatchDog could be a good pattern to look at.

If you need to catch keyboard combinations at a global level, you should hook into the Info.OnEventGoingIdle() method. Global reserved keys are defined under \Application Documentation\Global\Shortcutkeys.

I want to give a big thank you to Microsoft support for pointing me in the right direction. I can only wonder why Microsoft haven't gotten this stuff correctly wired up in the first place.