The Mother of All Kludges

So I spent all of today fighting with a Dell Axim X30, and I’ve again come to the conclusion that companies who keep things proprietary really suck.


My task was to print over Bluetooth.  I decided that I’d use PrinterCE from Field Software for simplicity, and all worked well if the radio was already on when I tried to print.  If the radio was off, however, things went bad quickly and the device had to be soft reset to recover.  Not a good thing for usability.


Since they use the Widcomm/Broadcomm stack, I decided to look at the BTConnect stuff from High-Point software.  After four or five hours of creating a nice class wrapper for the app (which is going to become a shared-source library from OpenNETCF shortly) I found that the radio is on whenever I am actively searching or connecting, but as soon as it’s done, the on-board BT manager shuts the radio off.  That means I can find the printer and connect with it, but as soon as I had off printing to PrinterCE, the radio shuts off and the device hangs.  Beautiful.  A plague upon the engineers at Dell.


Searching the web I find nothing hinting at how to programmatically do this.  Curses on the yet again.


I use Spy++ to see if I’m lucky and any messages might jump out when I use the BT Manager.  Nothing.  My hatred for Dell increases.


I search the registry for anything that might affect behavior and I find only one key that reports the current state.  Damn you Dell!


So I’m now a day into just turning on a Radio for a job I’ve quoted at 2 days (which I’ve already used doing the reporting code).  Now not only am I highly irritated, I’m highly irrated on my own dime.


So I make a last ditch effort to get something that at least functions.  I decided for a kludge, and a really nasty one at that.  As soon as I thought of it, I was disgusted by the idea, but I’ve really been left with no choice.  I’d simulate tapping the screen to turn the radio on.


And without further ado, I give unto you the following ugliness.  Hopefully no one elese ever has to use it, but since I’ve stooped this far, someone else probably will have to as well.  If you do, please curse Dell as well.


using System;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace OpenNETCF.Devices
{
  public static class AximX30
  {
    public static bool BluetoothRadioState
    {
      get
      {
        RegistryKey key = Registry.LocalMachine.OpenSubKey(@”SOFTWAREWIDCOMMBtConfigGeneral”);
        bool currentState = (((int)key.GetValue(“StackMode”)) == 1);
        key.Close();
        return currentState;
      }
      set
      {
        // see if any action is needed
        if (BluetoothRadioState == value)
        {
          return;
        }

        // save where we were
        IntPtr topWindow = GetForegroundWindow();

        int bticonX = Screen.PrimaryScreen.Bounds.Width 10;
        int bticonY = Screen.PrimaryScreen.Bounds.Height 10;
        int btmenuX = Screen.PrimaryScreen.Bounds.Width 20;
        int btmenuY = Screen.PrimaryScreen.Bounds.Height 80;
        int starticonX = 10;
        int starticonY = 10;
        int todayX = 10;
        int todayY = 60;

        // start
         SendTap(starticonX, starticonY);

         // let the menu draw
         System.Threading.Thread.Sleep(300);

         // today screen
         SendTap(todayX, todayY);

         // let the screen draw
         System.Threading.Thread.Sleep(300);

         // Blutooth icon tap
         SendTap(bticonX, bticonY);

         // let the menu draw
         System.Threading.Thread.Sleep(300);

         // bt menu tap
         SendTap(btmenuX, btmenuY);

         System.Threading.Thread.Sleep(300);

         // restore where we were
         ShowWindow(topWindow, SW.NORMAL);
         UpdateWindow(topWindow);
       }
      }

    [DllImport(“coredll”)]
    private static extern void mouse_event(
            MOUSEEVENTF dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

    [DllImport(“coredll”)]
    private static extern IntPtr GetForegroundWindow();


    [DllImport(“coredll”)]
    private static extern bool ShowWindow(IntPtr hWnd, SW nCmdShow);

    [DllImport(“coredll”)]
    private static extern bool UpdateWindow(IntPtr hWnd);


    [Flags]
    private enum HWND
    {
    TOP = 0,
    BOTTOM = 1,
    TOPMOST = -1,
    NOTOPMOST = -2
    }

    private enum SW
    {
    HIDE = 0,
    SHOWNORMAL = 1,
    NORMAL = 1,
    SHOWMINIMIZED = 2,
    SHOWMAXIMIZED = 3,
    MAXIMIZE = 3,
    SHOWNOACTIVATE = 4,
    SHOW = 5,
    MINIMIZE = 6,
    SHOWMINNOACTIVE = 7,
    SHOWNA = 8,
    RESTORE = 9,
    SHOWDEFAULT = 10,
    FORCEMINIMIZE = 11,
    MAX = 11
    }

    [Flags]
    private enum MOUSEEVENTF
    {
        MOVE = 0x1, /* mouse move */
        LEFTDOWN = 0x2, /* left button down */
        LEFTUP = 0x4, /*left button up */
        RIGHTDOWN = 0x8, /*right button down */
        RIGHTUP = 0x10, /*right button up */
        MIDDLEDOWN = 0x20, /*middle button down */
        MIDDLEUP = 0x40, /* middle button up */
        WHEEL = 0x800, /*wheel button rolled */
        VIRTUALDESK = 0x4000, /* map to entrire virtual desktop */
        ABSOLUTE = 0x8000, /* absolute move */
        TOUCH = 0x100000, /* absolute move */
    }

    private static void SendTap(int x, int y)
    {
      mouse_event(MOUSEEVENTF.LEFTDOWN | MOUSEEVENTF.ABSOLUTE, 
            (int)((65535 / Screen.PrimaryScreen.Bounds.Width) * x), 
            (int)((65535 / Screen.PrimaryScreen.Bounds.Height) * y), 0, 0);
      mouse_event(MOUSEEVENTF.LEFTUP, 0, 0, 0, 0);
    }
  }
}

1 thought on “The Mother of All Kludges”

  1. I had to do something very similar to this several years ago: I was working with a third party ActiveX control that was basically a glorified Edit control (it involved driving a barcode scanner and placing decodes into the field). Unfortunately, it would not respond to the SetFocus, and I wound up doing mouse_events to activate the control. Nasty, but it worked.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s