Friday, June 05, 2009

The new Demo showing XAML for Windows CE is really, really impressive.  This is non-WinMo, meaning CE no longer is a second-class citizen  in the device market.  If only I knew how to do design work....

6/5/2009 6:48:26 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
I've pushed up a new set of features and fixes for the OpenNETCF.IoC Framework as well as rolled a new release. See the Project Site for full details on what changed, but the general feature additions are that the framework now supports loading modules from configuration XML (you can now really decouple your app modules) and I added support for a DeckWorkspace and all the trappings around starting your app from a workspace.
6/5/2009 2:21:56 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [0]  | 
 Tuesday, May 19, 2009

Detecting if your application has been idle (i.e. no user mouse or keyboard actions) for a certain period of time is straightforward using an IMessageFilter implementation.  The filter would look like this:

using System;

using System.Collections.Generic;
using System.Text;
using OpenNETCF.Win32;
using System.Windows.Forms;
using OpenNETCF.Windows.Forms;

namespace MessageFilterSample
{
  public class InactivityFilter : IMessageFilter
  {
    public event MethodInvoker InactivityElapsed;

    private Timer m_inactivityTimer;

    public InactivityFilter(int timeoutMilliseconds)
    {
      m_inactivityTimer = new Timer();
      m_inactivityTimer.Interval = timeoutMilliseconds;

      m_inactivityTimer.Tick += new EventHandler(m_inactivityTimer_Tick);
      Reset();
    }

    void m_inactivityTimer_Tick(object sender, EventArgs e)
    {
      m_inactivityTimer.Enabled = false;
      Elapsed = true;

      if (InactivityElapsed != null) InactivityElapsed();
    }

    public bool PreFilterMessage(ref Microsoft.WindowsCE.Forms.Message m)
    {
      switch ((WM)m.Msg)
      {
        case WM.KEYUP:
        case WM.LBUTTONUP:
        case WM.MOUSEMOVE:
          // reset the timer
          m_inactivityTimer.Enabled = false;
          m_inactivityTimer.Enabled = true;
          break;
      }
      return false;
    }

    public int Timeout { get; set; }
    public bool Elapsed { get; private set; }

    public void Reset()
    {
      Elapsed = false;
      m_inactivityTimer.Enabled = true;
    }
  }
}

To use it, you must use one of the Run overloads in Application2 to start your application, then you can add your filter like this:

InactivityFilter m_filter = new InactivityFilter(5000);
m_filter.InactivityElapsed += new MethodInvoker(m_filter_InactivityElapsed);
Application2.AddMessageFilter(m_filter);
...
void m_filter_InactivityElapsed()
{
   MessageBox.Show("Inactivity timer fired");
}

Download the sample here:
 

MessageFilterSample.zip (3.92 KB)
5/19/2009 5:35:42 PM (Eastern Daylight Time, UTC-04:00)  #    Comments [3]  | 
 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]  |