Wednesday, May 13, 2009

We've been doing a ton of internal work lately on our Padarn ASP.NET Web Server for Windows CE - both on features as well as just the general stuff you have to do to have a product.  Part of this work was to create a series of hands-on labs to demonstrate how to use Padarn effectively.  The PDFs (a dozen in all so far), along with the latest Developer's Guide are available for public viewing on the Padarn Downloads page.

5/13/2009 7:47:53 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Tuesday, May 12, 2009

Admittedly this isn't really mobile related, but the guys over at CI Advantage are giving away T-Shirts with every download of the eval version of Deploy Now (which we do use and love here).  If you have desktop installations of anything, including mobile software or tools (we use it for testing the SDF installer scenarios, among other things) - it's a major time saver.

5/12/2009 10:01:04 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Monday, April 20, 2009

I blogged about this feature of the SDF two years ago (almost to the day in fact), but it certainly bears repeating since it's so useful.  If you need to know wehn a disk (SD, CF, USB, etc) has been attached or removed from a CE device (including Windows Mobile) you can use the SDF's DeviceStatusMonitor class (which, generally speaking, wraps the RequestDeviceNotifications API).  It's really, really simple to use:

private void WatchForDrives()
{
  DeviceStatusMonitor monitor = new DeviceStatusMonitor(DeviceClass.FileSystem, false);
  monitor.StartStatusMonitoring();
  monitor.DeviceNotification += delegate(object sender, DeviceNotificationArgs e)
  {
    string message = string.Format("Disk '{0}' has been {1}.", e.DeviceName, e.DeviceAttached ? "inserted" : "removed");
    MessageBox.Show(message, "Disk Status");
  };
}

4/20/2009 4:08:38 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [2]  | 
 Friday, April 17, 2009

In one of the mailing lists I'm on today, someone noted that on their Windows Mobile device the performance of GDI is much better in portrait mode than it is in landscape mode and was wondering why.  The reason is actually pretty simple.  Think of the image on the screen as just a contiguous stream of bytes (which is probably is).  The physical display needs to get that data and "paint" it.  Displays are engineered to essentially take in the data in a linear fashion, left to right, top to bottom.  So it's a pretty simple operation to just send out the framebuffer data to the display.

Now consider what happens if you want the display rotated 90 degrees. Remember, the display requires the data top to bottom, left to right, as it will show on the screen.  To get it into that state you have 2 options.  You can either A) rotate the data as you take it out of the frame buffer and send it to the display or B) rotate all calls to draw into the framebuffer.  In either case you have to do a matrix transform, which is expensive and gets worse the larger your display gets (so a VGA device will be more affected than a QVGA device).

Of course some devices have hardware acceleration that can greatly improve things by having matrix functions right in the silicon, but that still requires that the OEM actually modifies the driver to use that function (you'd be surprised how many don't).

So how bad is the performance penalty?  Well, since I like to actually quantify stuff I decided to resurrect an old GDI test app I had and rework it for this.  The results of my testing, as well as tests sent in from other people (if you want to add a test to the table, send me your results):

Device Processor OS Portrait Landscape Penalty
Axim x51 PXA270 WinMo 5 188 ops/s 77 ops/s 59%
Asus P750 PXA270 520MHz WinMo 6 Pro 241 ops/s 55 ops/s 77%

As you can see, there's a significant price to running rotated.

The test application (source and ARMv4I binary) is available here

GDIPerf.zip (10.46 KB)

 

4/17/2009 2:32:33 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [1]  | 
 Wednesday, April 15, 2009

If you've ever needed to automatically launch an application under Windows CE then you probably know that one of the most common ways is to put an entry into the device registry under HKLM\Init.  This works great for native applications, but for CF applications success is hit or miss.  The reason is that CF applications require certain system APIs to be up and running before they can run.  For a native app that has this requirement, the solution is simple: you call either IsApiReady or WaitForAPIReady (depending on the OS version) and then continue when you're satisfied.  For CF apps it won't work.  The APIs need to be ready long before Main is entered and any of your managed code is running.

Of course the "right" solution is that the CF team should have put that check into the loader so we could launch this way, but they didn't so we have to work around it.

So how do we get around this?  Well we leverage the initialization process itself.  When an app is launched from HKLM\Init, it is responsible for calling SignalStarted once it is running.  This allows any other items launching from HKLM\Init to set up dependencies, for example if item 60 depends on item 50, item 60 won't launch until item 50 has called SignalStarted.  What we can do is create a native application that acts as a launch gate.  This gate app will call the appropriate wait function, and only after the APIs we need are available does it call SignalStarted.  We can then launch any CF application using HKLM\Init by simply having the gate application launch first, and then having the CF app depend on the gate.

So in the registry, it would look like this:

[HKEY_LOCAL_MACHINE\Init]
    "Launch90"="gateapp.exe"
    "Depend90"=hex:1e,00 ; depend on GWES, which is at 30
    "Launch91"="MyCFApp.exe"
    "Depend91"=hex:5a,00 ; depend on gateapp

And here's the source code for a basic gate app:

extern "C" DWORD WaitForAPIReady(DWORD, DWORD);
extern "C" BOOL IsAPIReady(DWORD hAPI);

int _tmain(int argc, _TCHAR* argv[])
{
    // quick sanity check - HKLM\Init will send in our order number
    if(argc == 0) return 0;

    BOOL success = FALSE;

    // wait for window manager - that should be enough for us
    #if _WIN32_WCE > 0x500
        success = (WaitForAPIReady(SH_WMGR, 5000) == WAIT_OBJECT_0);
    #else
        int i = 0;
        while((! IsAPIReady(SH_WMGR)) && (i++ < 50))
        {
             Sleep(100);
        }

        success = (i < 50);
    #endif

    if(success)
    {
        int launchCode = _ttoi(argv[1]);
        SignalStarted(launchCode);
    }
    else
    {
        RETAILMSG(TRUE, (_T("CFInitGate timed out - SH_WMGR was not ready after 5 seconds\r\n")));
    }

    return 0;
}

4/15/2009 1:46:38 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [2]  | 
 Tuesday, April 14, 2009

If you just got the latest release of the IE8 Beta, your C++ Smart Device wizard will now fail.  When you try to create a project you'll get a few screen flashes and then an unhelpful "project creation failed" message in teh status bar of Studio.  The fix is outlined here (and worked on my XP box).

4/14/2009 10:03:58 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [2]  | 
 Wednesday, April 01, 2009

I'm in the middle of adding a Passive View Model-View-Presenter(MVP) framework to the OpenNETCF IoC Framework.  I just checked in a working version (it's in the source downloads, not as a release).  If you're interested and want to have a say in how it ends up, go ahead and download it and give me your feedback.  There's a simple usage example in source control.

4/1/2009 4:10:37 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [3]  |