fredag 9 oktober 2009

CeSetUserNotification - Using CSharp

Have you ever wanted to display a notification as is displayed by the calendar application when you are reminded of an event? If so, then CeSetUserNotification might be your saviour.

With CeSetUserNotification we introduce yet another struct. To invoke this API you must also construct an instance of CE_USER_NOTIFICATION. This struct holds some basic information on the notification such as strings and actionflags. It's declared as follows.

Comments on each field are taken from Notify.h which is part of the Windows Mobile 6 SDK.

    [StructLayout(LayoutKind.Sequential)]
public class CE_USER_NOTIFICATION
{
[MarshalAs(UnmanagedType.U4)]
public PUN_FLAGS ActionFlags; //@field Action Flags. Any combination of the
// PUN_* flags. Flags not valid on a given
// hardware platform will be ignored.
[MarshalAs(UnmanagedType.LPTStr)]
public string sDialogTitle; //@field Dialog Title. Required if PUN_DIALOG is set, ignored
// otherwise. Ignored by CeGetUserNotificationPreferences().
[MarshalAs(UnmanagedType.LPTStr)]
public string sDialogText; //@field Dialog Text. Required if PUN_DIALOG is set, ignored
// otherwise. Ignored by CeGetUserNotificationPreferences().
[MarshalAs(UnmanagedType.LPTStr)]
public string sSound; //@field Sound string as supplied to sndPlaySound.
// CeSetUserNotification() ignores it if PUN_SOUND is not set.
[MarshalAs(UnmanagedType.U4)]
public uint nMaxSound; //@field Max Sound string length. Specifies the
// maximum length of the string that can be copied
// into the pwszSound buffer by
// CeGetUserNotificationPreferences().
// Should be at least MAX_PATH * sizeof(TCHAR).
// Ignored by CeSetUserNotification().
[MarshalAs(UnmanagedType.U4)]
public uint Reserved; //@field Reserved. Must be NULL or a pointer to
// platform-defined expansion structure.
// The first dword of the structure
// indicates the size of the structure.
[MarshalAs(UnmanagedType.U4)]
public uint pReserved;
}


You probably notice that we also need the PUN_FLAGS enum for this. PUN_FLAGS are the bit flags that specify how the device will behave when the notification is invoked.

Again; Comments on each field are take from Notify.h.

    public enum PUN_FLAGS
{
PUN_LED = 1 //@flag PUN_LED | LED flag. Set if the LED should be
// flashed when the notification occurs.
,
PUN_VIBRATE = 2 //@flag PUN_VIBRATE | Vibrate flag. Set if the device should
// be vibrated.
,
PUN_DIALOG = 4 //@flag PUN_DIALOG | Dialog flag. Set if a dialog should be
// displayed (the app must provide title and text
// when calling <f CeSetUserNotification>).
,
PUN_SOUND = 8 //@flag PUN_SOUND | Sound flag. Set if the sound specified
// in pwszSound should be played.
,
PUN_REPEAT = 16 //@flag PUN_REPEAT | Sound repeat flag. Set if the sound
// specified in pwszSound should be repeated progressively.
,
PUN_PRIVATE = 32 //@flag PUN_PRIVATE | Dialog box z-order flag. Set if the
// notification dialog box should come up behind the password.
};


Combin any of these flags to specifiy the behaviour you want.
The example below will flash the led and turn on the vibrator when the notification is invoked by Windows.

CE_USER_NOTIFICATION ceun = new CE_USER_NOTIFICATION();
ceun.ActionFlags = PUN_FLAGS.PUN_LED & PUN_FLAGS.PUN_VIBRATE


Enough ranting.. CeSetUserNotification is declared as follows:

        [DllImport("CoreDLL.dll", SetLastError=false, EntryPoint="CeSetUserNotification")]
public static extern uint SetUserNotification([MarshalAs(UnmanagedType.U4)]uint hNotification, string AppName, SYSTEMTIME Time, CE_USER_NOTIFICATION Notification);


As you can see we also pass a SYSTEMTIME instance. Nothing magical here - this works the same way as the call to CeRunAppAtTime did.

If you want to create a new notification, pass hNotification as 0. To modify an existing one pass that notifications handle. (Hint: The handle is the return value from CeSetUserNotification.)
You may also pass a string that identifies your application. This identification can be used later on when calling CeHandleAppNotifications.

below is a complete listing of a function using CeSetUserNotification.

            CE_USER_NOTIFICATION ceun = new CE_USER_NOTIFICATION();
DateTime dtTime = DateTime.Now;
dtTime = dtTime.AddMinutes(1);
SYSTEMTIME sysTimeStart = new SYSTEMTIME(dtTime);

ceun.ActionFlags = PUN_FLAGS.PUN_DIALOG;
ceun.sDialogTitle = "";
ceun.sDialogText = "This is a notfication set by the Notifications Sample Application.";
ceun.Reserved = 0;

uint nHandle = SetUserNotification(0, "MySampleApp", sysTimeStart, ceun);
MessageBox.Show("Handle returned by SetUserNotification:" + nHandle.ToString() + "\r\nNotification is scheduled for:" + dtTime.ToShortTimeString());


Notifications that has already occured can be marked as "Handled" by calling CeHandleAppNotifications. Remember, calling ceHandleAppNotifications doesn't cancel out scheduled notifications but simply dismisses notifications that has already occured.

CeHandleAppNotification is declared as follows:

        [DllImport("CoreDLL.dll", SetLastError = false, EntryPoint="CeHandleAppNotifications")]
public extern static bool HandleAppNotifications(string AppName);


And that's it! Next week we'll work out why Microsoft has marked these functions as obselete and what alternative APIs there are. We'll also take a look at DateTime.Now() and make sure you understand why you should use the native function GetLocalTime() instead.

Have a great weekend!

1 kommentar:

  1. marked as obolete coz there is now : CeSetUserNotificationEx

    and be careful :

    ceun.ActionFlags = PUN_FLAGS.PUN_LED & PUN_FLAGS.PUN_VIBRATE

    you should use "or" : |

    Best
    Lotfi

    SvaraRadera