Saturday, April 15, 2006

2614.aspx

SendKeys on .NET Compact Framework

I needed SendKeys in .NET CF when I implemented the AutoType feature in poSecrets. I found a SendKeys  implementation on OpenNetCF. It implements the SendKeys logic for handling repetitions and special keys like shift, alt, ctrl, etc but it does not support upper case/lower case and some special characters.  I thought I had to implement my own key map until I found PostKeybdMessage. It is perfect as it manages all the shift states.


I modified the SendChar routine like this and now it works like a charm:


private static void SendChar(byte k, byte [] mods)
{           
    // Use the PostKeybdMessage() api instead of keybd_event
    // as it correctly manages upper case, lower case
    // and special characters
    //keybd_event(k, 0, 0, 0);
    //keybd_event(k, 0, KEYEVENTF_KEYUP, 0);
    uint KeyStateDownFlag= 0x0080;
    uint KeyShiftDeadFlag= 0x20000;
    uint[] buf1 = new uint[1];
    uint[] DownStates = new uint[1];
    DownStates[0]=KeyStateDownFlag;
    buf1[0]=(uint)k; 
    uint[] DeadStates = {KeyShiftDeadFlag};
    int hwnd = -1;
    PostKeybdMessage(hwnd,0,KeyStateDownFlag,(uint)buf1.Length, DownStates, buf1);
    PostKeybdMessage(hwnd,0,KeyShiftDeadFlag,1, DeadStates, buf1);
    CancelMods(mods, 4);
}

I will send the updated code to opennetcf so I guess the code will make it into the main branch soon. In the mean time you can download the source code for SendKeys in the downloads section.

9 comments:

  1. hi,

    thanks.. works fine. but i noticed that it works fine in address bar of the IE in mobile device and in normal text box but does not work when the cursor is where we edit sms or in word mobile. there some keys works (e.g. q,w) but some does not come or shows different symbols.

    any idea?

    rnv

    ReplyDelete
  2. Which characters do you have problems with?



    I tried the following characters without problems in Pocket Word on a iPaq h4150 (.NET CF 1.0) using SendKeys.cs from the downloads section:

    1!2@3#4$5%6^7&0*9()_+/.,<>\|qwertlBMDPOmsnDFk

    ReplyDelete
  3. I managed to reproduce and fix the problem with the Windows Mobile 5.0 SDK. Insert the new line below and SendKeys works with Mobile Word as well:

    PostKeybdMessage(hwnd,0,KeyStateDownFlag,(uint)buf1.Length, DownStates, buf1);

    buf1[0] = 0; // New line

    PostKeybdMessage(hwnd,0,KeyShiftDeadFlag,1, DeadStates, buf1);



    The file in the downloads section has been updated.

    ReplyDelete
  4. thank you!



    I have problem to use this.



    SendKeys.Send("+zzz"); // it returns "zzz" not "Zzz"

    SendKeys.Send("^c"); // it returns "c" instead of "copy"



    so I think it doens't take shift, ctrl, and alt.



    is there anyway to fix it?







    ReplyDelete
  5. I managed to reproduce the problem on a device. Looks like the Shift+Ctr+Alt capabilities got lost when I moved to from keyed_event() to PostKeybdMessage(). I will add support to KeyShiftAnyCtrlFlag, KeyShiftAnyShiftFlag, KeyShiftAnyAltFlag and post a comment here when it's ready. The fixed version should be ready by next week.



    Thanks for the bug report.

    ReplyDelete
  6. I have been to busy at work to spend a lot of time on the issue. The problem is that I probably pass KeyShiftAnyCtrlFlag, KeyShiftAnyShiftFlag, KeyShiftAnyAltFlag incorrectly to PostKeybEvents() as it ignores the flags completely. I will have a look again next week but it looks like it will take me some time to find a solution.



    BTW: Shift is not really needed as SendKeys support both upper and lower case characters.

    ReplyDelete
  7. thanks.

    I just need to send "ctrl"+C and "crtl" +V ...etc now.

    so here is my solution for now if any one is doing the same thing.







    const int KEYEVENTF_KEYUP = 2;





    /// <summary>

    /// Sends the "control"+ "C" to keyboard.

    /// </summary>

    public static void SendControlC()

    {

    try

    {

    keybd_event(0x11, 0, 0, 0);// press ctrl

    keybd_event(0x43, 0, 0, 0); // press c

    keybd_event(0x43, 0, KEYEVENTF_KEYUP, 0); //release c

    keybd_event(0x11, 0, KEYEVENTF_KEYUP, 0); //release ctrl

    }

    catch

    {

    throw new ArgumentException("error to copy");

    }

    }



    /// <summary>

    /// Sends the "control"+ "V" to keyboard.

    /// </summary>

    public static void SendControlV()

    {

    try

    {

    keybd_event(0x11, 0, 0, 0);// press ctrl

    keybd_event(0x56, 0, 0, 0); // press V

    keybd_event(0x56, 0, KEYEVENTF_KEYUP, 0); //release V

    keybd_event(0x11, 0, KEYEVENTF_KEYUP, 0); //release ctrl

    }

    catch

    {

    throw new ArgumentException("error to paste");

    }

    }



    /// <summary>

    /// Sends the "control"+ "X" to keyboard.

    /// </summary>

    public static void SendControlX()

    {

    try

    {

    keybd_event(0x11, 0, 0, 0);// press ctrl

    keybd_event(0x58, 0, 0, 0); // press X

    keybd_event(0x58, 0, KEYEVENTF_KEYUP, 0); //release X

    keybd_event(0x11, 0, KEYEVENTF_KEYUP, 0); //release ctrl

    }

    catch

    {

    throw new ArgumentException("error to cut");

    }

    }

    ReplyDelete
  8. I'm having problems sendit {TAB}...it doenst move to the next control in the tab index...

    I'll really apreciate ur help.



    thanks.

    ReplyDelete
  9. Which application are you sending the text to?



    I tried SendKeys("abc{TAB}def") and SendKeys("abc\tdef") and both work OK in my test cases.



    Keep in mind that some applications like Pocket Word will insert a tab in the text instead of moving to the next control.

    ReplyDelete