Sunday, January 29, 2006

Making apps power aware, especially through the device Power Manager works, but the code is kind of ugly and a pain to implement.  Once again SDF 2.0 simplifies things:

using System;
using System.Windows.Forms;
using OpenNETCF.WindowsCE;

namespace WindowsCETest
{
  public partial class MyPowerAwareClass
  {
    public MyPowerAwareClass()
    {
      DeviceManagement.DeviceWake +=
       new DeviceNotification(
DeviceManagement_DeviceWake);

      PowerManagement.PowerUp += new DeviceNotification(PowerManagement_PowerUp);
    }

    void PowerManagement_PowerUp()
    {
      MessageBox.Show("The Power Manager says I'm awake!");
    }

    void DeviceManagement_DeviceWake()
    {
      MessageBox.Show("Device notifications say I'm awake!");
    }
  }
}

1/29/2006 9:56:53 AM (Eastern Standard Time, UTC-05:00)  #    Comments [4]  | 
 Saturday, January 28, 2006

The Windows CE operating system supports several notifications for common device events liek changes in AC power, network status changes and time changes.  They are exposed by using the CeRunAppAtEvent or CeSetUserNotification APIs.  While the Windows Mobile Notification Broker provides an interface for some of these, it doesn't provide access to all of them, nor is it available for general Windows CE developers.

SDF 1.4 provided a set of Notification classes that could be used to get these (and those classes are still there in SDF 2.0) but we felt that a simple object model around these would really be a nice thing to have.  So we created the OpenNETCF.WindowsCE.DeviceManagement class.  Now subscribing to the notifications is as simple as this example of detecting when the device time has been modified:

using System;
using System.Windows.Forms;
using OpenNETCF.WindowsCE;

namespace WindowsCETest
{

public class MyClass
{

public MyClass()
{

    DeviceManagement.TimeChanged +=
       
new DeviceNotification(DeviceManagement_TimeChanged);
}

void
DeviceManagement_TimeChanged()
{
    MessageBox.Show(
"The time was just changed.");
}

}

}

1/28/2006 6:26:51 PM (Eastern Standard Time, UTC-05:00)  #    Comments [1]  | 
 Saturday, January 21, 2006

We're extremely close to a beta release of SDF 2.0.  To give you a taste of what's in it, we've posted the online documentation.  Any feedback is appreciated.  Enjoy.

1/21/2006 11:49:17 PM (Eastern Standard Time, UTC-05:00)  #    Comments [3]  | 
 Tuesday, December 20, 2005

So if you're working with Microsoft's new Microsoft.WindowsMobile.PocketOutlook namespace and trying to use the OutlookCollection.Restrict method to filter by a Contact's (or any PimItem's) ItemId field, you will likely run into a problem.

First, let me say the ItemID Class sucks.  It exposes basically nothing useful but a ToString() method, even though it holds numeric data.  And the first item added to POOM gets the ItemId of 0x80000001, which you might note is an *unsigned* number (again, the CLS is a pain for not allowing unsigned numbers).  So if you have an ItemId class and you want to use it, you have to do something like this:

unchecked
{
    int myId = int
.Parse(m_outlookSession.Contacts.Items[0].ItemId.ToString())
}

Really, that's how you have to do it.

So, let's say we have a Contact's ItemId and we want to see if the current session has said Contact.  One might try this:

m_outlookSession.Contacts.Items.Restrict("[ItemId]=" + itemId.ToString());

A nice try, but that gives you the not-so-helpful exception:

The query string is incorrectly formatted.
Parameter name: [ItemId]=-2147483647

Alright, so ItemId only exposes itself as a string, and Restrict has little in the way of useful documentation or samples, so maybe we can try it as a string like so:

m_outlookSession.Contacts.Items.Restrict("[ItemId]='" + itemId.ToString() + “'“);

Well that gives a similar exception, just adding the single quotes:

The query string is incorrectly formatted.
Parameter name: [ItemId]=-'2147483647'

Because I've used POOM from C++, I know that ItemId seems new to me, so just as a lark I figure I'll try 'Oid' as a field name instead, and keep it as a numeric:

m_outlookSession.Contacts.Items.Restrict("[Oid]=" + itemId.ToString());

Lo and behold, success!

Now technically this might not be a true bug, but it's sure not documented anywhere, nor would it be at all intuitive to guess if you'd not used C++ to access an IContact (which exports an Oid field, *not* an ItemId) before.  Bad Windows Mobile Team.  BAD!

Things needed:

  • The ItemID needs to have an explicit operator for conversion to an int at the very least.  A ToInt32 or ToIntPtr or something of the sort would be useful.
  • Either name the field Oid like it's stored in the database, or provide some sort of substitution so when I filter by ItemId the underlying class converts that to Oid.
  • The least they could have done was give exception text like “The field cannot be found in the collection“
  • Documenting how to remove a Restrict once set would be useful (I used Restrict(“[Oid]<>0“) for lack of any better idea)
12/20/2005 10:15:43 PM (Eastern Standard Time, UTC-05:00)  #    Comments [4]  | 
 Tuesday, December 13, 2005

Steven Pratschner has posted a really good blog entry on how the CF 2.0 CLR works.  Take a look.

12/13/2005 6:11:42 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0]  |