Custom soft keys for Notifications

Screenshot of custom notification displayed on the screen with two custom soft key menu items.Since my previous posting about Notifications within the .NET Compact Framework I have seen the question of how to provide custom menu items at the bottom of a notification come up a number of times. Today I am going to provide you with one solution to this challenge.

The short answer is that the Microsoft.WindowsCE.Forms.Notification class provided by the .NET Compact Framework does not expose the required functionality. Although the native notification API allows custom menus to be associated with a notification, for some reason this hasn’t be exposed to managed developers. With a little bit of work however (i.e. some PInvoking) you can produce your own managed wrapper around the Notification APIs to expose the required functionality.

I have done this and produced a class called NotificationWithSoftKeys. You can download a copy of this class, along with a sample application which demonstrates it’s various features below.

[Download notificationsoftkeys.zip 32KB]

The rest of this blog entry will demonstrate how you can utilise the class within your own applications. It is designed to be a stand in replacement for the existing class, but adds some additional properties and events.

Adding Spinners
Screenshot of custom notification showing the use of spinnersSpinners are the first additional functionality the NotificationWithSoftKeys control exposes. A notification spinner is a little bit of text on the right hand side of a notification which sits in-between a pair of < and > buttons. The user can tap on these buttons to “spin” through a series of related notifications.

Here is a brief example of how to enable this feature within your notification.

private NotificationWithSoftKeys notification;
 
private void btnCreateNotification_Click(object sender, EventArgs e)
{
  notification = new NotificationWithSoftKeys();
  notification.Icon = Properties.Resources.Icon;
  notification.Caption = "This is my notification";
  notification.Text = "Spinner Test\t1 of 5";
  notification.Spinners = true;
  notification.SpinnerClicked +=
      new SpinnerClickEventHandler(notification_SpinnerClicked);
  notification.Visible = true;
}

The main thing you need to do is set the Spinners property to True in order to enable the Spinner functionality. After this any text within the Caption property after the first tab (\t) character will be displayed on the right hand side of the notification’s caption.

When the user presses the < or > buttons the SpinnerClicked event will fire. Within your event handler you should update your Notification’s Caption and Text properties to give the illusion that another notification has been displayed.

Display Current Time on Caption
Screenshot of custom notification showing the use of the TitleTimer propertyDisplaying the current system time on the caption is very straight forward. All you need to do is set the TitleTime property to true.

Custom Buttons
This is the feature which will probably generate the most interest. The standard notification has a “Hide” button on the left soft key. Some built in applications however display notifications with alternative softkeys and perform different actions depending upon which softkey was selected. Using the NotificationWithSoftKey class we can achieve the same effect as demonstrated with the following example.

private NotificationWithSoftKeys notification;
 
private void btnCreateNotification_Click(object sender, EventArgs e)
{
  notification = new NotificationWithSoftKeys();
  notification.Icon = Properties.Resources.Icon;
  notification.Caption = "This is my notification";
  notification.Text = "A soft key test";
  notification.LeftSoftKey =
      new NotificationSoftKey(SoftKeyType.Dismiss, "Close");
  notification.RightSoftKey =
      new NotificationSoftKey(SoftKeyType.StayOpen, "View");
  notification.RightSoftKeyClick +=
      new EventHandler(notification_rightSoftKeyClick);
  }
 
  notification.Visible = true;
}

This example will display a notification with two soft keys. The left soft key will be labeled “Close” and will remove the notification, while the right soft key will be labeled “View” and trigger the RightSoftKeyClick event when selected.

Within this event handler you could open up a second form, delete something from a database or perform any other task you would like to in response to the user pressing the soft key.

There are a number of soft key types to choose from as shown below:

Type Description
Dismiss Remove the notification when the soft key is pressed
Hide Hide the notification when the softkey is pressed (but do not dismiss)
StayOpen Do not dismiss or hide the notification when the softkey is pressed.
Submit Submit the HTML form in the notification instead of calling the click event handler
Disabled The softkey is disabled (grayed out)

Backwards Compatibility
The additional features discussed today are only available on devices running Windows Mobile 5.0 or higher. If your application is targeting multiple device types, and you need to run on Pocket PC 2003 devices the new functionality will not work.

The NotificationWithSoftKeys class utilises techniques outlined in my blog posting on device and platform detection to fail gracefully on older devices. When the class detects an older device type, it will simply ignore all the soft key related properties and revert back to the old notification style.

Sometimes you may want to check if this fallback has occurred. For instance you may want to utilise the soft key buttons for user input. In this case you would need to use an alternative approach (such as HTML based buttons) when running on Pocket PC 2003 or older devices which don’t have softkeys. You can do this by checking the PlatformSupportsCustomSoftKeyButtons property and altering the other properties of the NotificationWithSoftKeys class as required.

Summary
This is still only scratching the surface of what is possible with the native notification APIs. There are a number of notification features which are not exposed by this wrapper. For example there are the following flags which could easily be exposed as properties.

  • SHNF_DISPLAYON – the display is forced to turn on for the notification
  • SHNF_SILENT – the notification is forced to be silent and not vibrate, regardless of system settings

Please feel free to download the sample project and have a play around with it. I would be keen to hear from anyone who attempts to use it or modifies it to expose additional functionality etc.

58 Responses to “Custom soft keys for Notifications”

  1. Dan says:

    This looks wonderful! One question though. How tough do you think it would be to allow pop-up menus for the softkeys instead of just menu items?

  2. Chris says:

    Dan, that was exactly what I thought as I was reading the post!

  3. Hi Dan and Chris,

    This should be possible. The SHNOTIFICATIONDATA structure that the native notification API expects has two alternative ways to represent the soft key menu structure.

    The easiest to use from managed code is one which simply provides for two soft keys (as I exposed in my wrapper). The other allows for arbitrarily complex menus, by passing in an HMENU menu resource.

    Since there has been quite a lot of interest in this wrapper, I’ll have a go at wrapping up the rest of the features of the native API which are not currently exposed by my managed wrapper.

    Once the wrapper is feature complete from that perspective, I guess it’s onto improving the design time experience of the control…

  4. I’ve tried tis project and it works great.
    But I would like delete a notification from code the same way as the dismiss softkey do.
    I have notifications that doesn’t fit in the small notification windows, so I have a “Show detail” softkey to display the entire notification in a new form. I would like to dismiss the notification in that form.
    Any suggestions?

  5. Hi Geir,

    I am not sure I completely understand the situation you are describing, so feel free to clarify if my answer doesn’t appear to answer your problem…

    If I understand the problem you have a notification displayed which has a custom softkey labeled “Show Detail”. When this is selected you want to totally remove the notification and popup another form.

    To do this using the wrapper discussed in this blog entry you should be able to use a line of code something like the following to setup the soft key.

    notification.LeftSoftKey =
          new NotificationSoftKey(SoftKeyType.Dismiss, "Show Details");

    The important part is the SoftKeyType.Dismiss flag which tells the notification to remove itself whenever the softkey is pressed. You could then display your new form in response to the LeftSoftKeyClick event.

    If you are using the standard .NET Compact Framework notification class some of the comments on a previous blog entry may help you out.

    Let me know if this isn’t exactly what you wanted.

    PS: For anyone who is interested my newer notification class wrapper which supports numerious additional bits of functionality (such as popup menus containing more than 2 softkeys etc) is nearing completion. Expect to see it posted in the next few days provided I get a bit of spare time over the weekend.

  6. Hi Geir,

    In the sample application I posted there is already an example which is fairly close to what you want.

    On the main form you should see a button labeled “Display a Form”. If you view the source code for it’s Click event handler you should be able to change the “Open” button displayed on the soft key from SoftKeyType.StayOpen to SoftKeyType.Dismiss and get the behaviour you are looking for.

  7. Na, not exactly. The notifications are too long to be displayed in a normal notification bubble. So I have the left soft key to display the entire message in a new form, in a WebBrowser control. On this form, I would like to have two menues, one who just closes the form and another that deletes the notification, just like the ‘dismiss’ softkey do.
    hope I make myself clear..

  8. Hi Geir,

    In that case what you need to do is pass your NotificationWithSoftKeys instance to the second form (perhaps via a constructor parameter or property).

    Then within a button click event handler on the second form you can then set the Visible property of your notification to false in order to hide it.

    However…. there is a bug/feature of the NotificationWithSoftKeys class as currently written which stops this from working. Within NotificationWithSoftKeys.cs you will need to make a small change for the above functionality to work.

    Find the following code (it’s within the Visible property setter) within NotificationWithSoftKeys.cs

    #if !DESIGN
            if (mVisible != value)
            {
              mVisible = value;
     
              if (mVisible)
              {
                int hresult = SHNotificationAdd(ref m_data);

    What you need to do is comment out the line “if (mVisible != value)” at the top. When your second form is displayed the notification is technically not visible (it’s ‘iconic’ and only displayed on the nav bar at the top of the screen), but we want to call SHNotificationRemove anyway in order to compeltely dismiss the notification.

    Hopefully this will get you the behaviour you want. I have not tested the full ramifications of making this change, but I’ll test it further as I get the improved version of this notification wrapper ready for release.

  9. The commenting of the above mentionend code row did the trick. I tried that earlier, but it didn’t work.

    Instead of passing the object ByRef to the other form, I did it this way:
    In the LeftClick event I pass the Text property to the other form, and display the form with DisplayDialog().
    After that I check the form’s DialogResult. If its Cancel, the notification should be removed:
    ‘—————————-
    ‘In the main form:
    Private Sub Notify_LeftClick(ByVal sender As Object, ByVal e As EventArgs)
    Dim Document As String = DirectCast(sender, NotificationWithSoftKeys).Text
    Dim fNotifyDetails As New frmNotifyDetails(Document)
    fNotifyDetails.ShowDialog()
    If fNotifyDetails.DialogResult = Forms.DialogResult.Cancel Then
    CustomNotify.Visible = False
    End If
    fNotifyDetails.Dispose()
    End Sub

    ‘In the called form:
    Public Sub New(ByVal Document As String)
    InitializeComponent()
    WebBrowser1.DocumentText = Document
    End Sub

    Private Sub MenuItem1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem1.Click
    Me.DialogResult = Windows.Forms.DialogResult.OK
    Me.Close()
    End Sub

    Private Sub MenuItem2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MenuItem2.Click
    Me.DialogResult = Windows.Forms.DialogResult.Cancel
    Me.Close()
    End Sub
    ‘—————————-

    Thanks for your patience and support!

  10. Salil Dhawan says:

    Hello

    I have few questions concerning Windows Mobile device capabilities.

    I am looking to search for 2 properties in Windows Mobile :
    1. user switches off the display –> system switches to prompt mode
    2. user switches off the loud speaker –> system switches to graphic only mode

    From where i can get these properties in Windows Mobile? Pleae can you explain me in detail.

    Thanks in advance
    Salil

  11. Graham Downs says:

    Hi,

    All we wanted was a way to have the notification icon pop up without playing any sound. After searching for almost the entire day yesterday, I stumbled accross your control. While your version does not contain a property to make the thing silent, I found it was pretty easy to wrap the SILENT flag. Thank you very much! You made my day! :-)

    I only have two problems now. I can’t get the icon to go away when I terminate my application (Dispose() does not seem to be working), and also I can’t get the icon to display without the bubble (Setting InitialDuration to 0 and Visible to false isn’t working – the bubble displays anyway).

    Any ideas?

  12. Graham Downs says:

    Nevermind on the first problem. I got it to die by calling SHNotificationRemove in the Dispose() method of the custom control.

    But I still can’t figure out to to get it to NOT display the bubble until the user clicks. :(

  13. Elad says:

    Any news regarding a version that supports popup menus? It would definitely make my day…!

    Thanks for sharing.
    Elad.

  14. Hi Elad,

    There is no update yet… As I mentioned in a previous blog posting I have recently had a number of things on the go, including study for a University exam. This busy period is hopefully over for a while, so it’s my intention to get back onto this control library.

    So perhaps you’ll see something in the next week or two. I have a variant which partially supports popup menus, I just need a little bit of time to tidy it up, and apply some fixes for some of the bugs which have been reported above etc.

    I’ll keep you informed. At the same time I’m thinking of merging some of the other sample controls (such as the smartphone compatible tab control) into a single “custom controls assembly” which I’ll continue adding to as I develop future custom controls on this blog.

  15. Elad says:

    This is really great, your blog is one of the best sources for non standard CF user controls. I appreciate your help, and looking forward to the next release.
    Elad.

  16. Hi Geir,

    So you’ve teamed up with Mikael Olsson again (sogeti)?

    Please send me an email if you still have my email address.

    / Fredrik

  17. Howard says:

    I agree with Elad; your site has got a lot of great stuff in it.

    I too am looking forward to the modified Notification class with popup menus.

  18. Fuzzy says:

    After spending days searching for a way to do this, I stumbled across your site. I have found a bunch of code to help me with my problems. I have a question using this DLL with VB.NET though. I’ve gotten everything to work except when trying to do LeftSoftKeyClick or RightSoftKeyClick. I get a must use RaiseEvent Error on the following line.

    softKeyNotifySend.RightSoftKeyClick += New EventHandler(AddressOf softKeyNotifySendRight_Click)

    I do not have an option for SoftKeyClick. Any Idea? Am i just looking at this the wrong way.

  19. Fuzzy says:

    I got another question for you and no one seems to have any info or examples on how to display the balloon without having a form open. Is there a way to use your custom balloon to be displayed but without the form being visible? Just like how a normal sms messages is recieved or reminder event from the calendar are displayed.

  20. Fuzzy says:

    Sorry for the posts but I figured out everything I needed. i was way over thinking what i was doing. Its amazing what takeing a couple days off will do. You got a great little DLL here. It is surprising though that there isn’t managed code for the use of the bubble besides a simple dismiss. Keep up the good work your site had been incredibly helpful.

  21. Henning says:

    I am using this control for quite some time now.
    But the one question that is still bugging me:
    Have you made any progress with the addition of using menus with the notificationkeys? This would really save my day…
    Or have i just missed a post where you already published a new version?
    Anyway thanks for this blog… it really is helpful.

  22. Time… or the lack there of…

    Yes making this update is still on my agenda (and is sitting semi-complete on my laptop). The problem is finding enough time to not only complete the changes, but making them robust enough for use by others.

    I’ll make sure to keep you up to date when I finally get around to finishing it. If anyone else has made modifications to this class I would be happy to include them in this update…

  23. Bojan says:

    Hi Christopher, I’m writing a application for windows mobile 6.0 which runs on HTC Touch (T-Mobile). I’m having trouble adapting your file christec.windowsce.forms,Version=1.0.3040.42759.
    In Visual studio 2005 it works perfect, no errors, but on my device, it collapses whit message:
    Culture=neutral, PublicKeyToken=null, or one of it’s dependencies was not found.
    In the previous examples I wasn’t getting any errors and with standard windows notifications it works. I’m missing something??

  24. JDBarclay says:

    I would like to modify the appointment notifications. I want to have the SNOOZE option on first hand (Snooze instead of Dismiss). Is this possible?

    Thanks

  25. Henning says:

    Hi!

    while still waiting for you to find the time to complete the additions to this control, i tried to understand the code you wrote…
    its embarrassing to admit… but i failed…
    i found the msdn entry for the structures and what you can do…
    yet i do not understand some parts of your code…
    why use 0×0001 on the one hand in another enum 0×00000001?
    (might sound like the easiest question there is… but i fail to understand it)
    maybe a little tutorial in how to wrap native code for compact framework user would be a nice addition for your blog :)
    or just a link to another page which already did this (the ones i found where not really helping)

    Thanks again

  26. Shaun says:

    Is this source code “Open Source”??

  27. SpacixOne says:

    I was looking though this code, which is great!

    I did notice that SHNOTIFICATIONDATA.cs has SHNP_ICONIC set to zero instead of 0×1B2 which is the enum value per the aygshell.h file.

    I’m wondering if there was a reason for this?

  28. SpacixOne says:

    @Henning

    leading zeros don’t matter at all just like the number
    100 is the same as 0100 or 00100

    0×0021 is the same value as 0×00000021

    in the above example the latter is normally written because somwhere else there might be a value of 0×21000000 so all of the numbers like up in a row.

    it makes it easy to see where bits/bytes will be in relation to each other like below:
    0×00000021
    0×00002100
    0×00210000
    0×21000000

    you see where the 21 is in relation to the other values faster than writing it where all of the 21 values line up.
    0×21
    0×2100
    0×210000
    0×21000000

  29. Keith says:

    I have an application that updates the text of the balloon whenever it is shown. Normally this works fine, but if there are multiple notifications active it locks up. When there are multiple notifications active (1 from my app, another from somewhere else) the notification icon is changed to a chat bubble, when you click this it has a drop down bar with the icons for each notification. Clicking on the icon for my notification causes it to lock up.

    In my code I have a single NotificationWithSoftKeys
    notification1 = new NotificationWithSoftKeys();

    In my OnBalloonChanged callback I do
    notification1.Text = “Some text”;

    I’ve stepped through the code in the debugger and inside the Text property it calls SHNotificationUpdate. This function never returns in this scenario.

    Does anyone have any ideas what could be going on here? It works just fine as long as there is only 1 active notification.

    Thanks

  30. SpacixOne says:

    @Keith: I’m working on a similar bug. If I add a notification and let it sit for a while without changing from the calling app. The notification will fail to remove, update, or respond.

    Though I’ve modified this class to expose \most\ of the functionality of a native code. It happens with the original classes from here too.

    I think your problem and mine are related, I think something is getting garbage collected from sitting idle in the these classes. I’ve hadn’t the chance to debug it further, but I’ll post here when i have time. I’m thinking I might get to look at this during the coming weekend.

  31. SpacixOne says:

    Whew, I got some time after work last night to look at this bug, though I don’t have a fix I know the cause now.

    The leak is the clsid of the notification, when the “private static Guid clsid = Guid.NewGuid();” is getting lost somewhere and we lose control of the notification, it’ll makes a new one. Putting the old one in limbo with your C# reference pointing to the new notification.

    I’m thinking that if the clsid in NotificationWithSoftKeys and/or SHNOTIFICATIONDATA was readonly the error might go away. I’ll have to try and test this further…

  32. wgarcia says:

    Hi,
    This looks wonderful! One question though. Is there any way to create my own box with a different design (without task bar) for Windows Mobile 6.

    Regards,

  33. SpacixOne says:

    Hmm, I was wrong in my previous post above. it seems that a stray “dismiss” message is being tossed to the message pump even with the timeout set to -1 (infinite timeout) the dismiss call is sent.

    This is the cause of the problem for using onballonchanged and drawing a string to the message window then. If the window thinks it is it’ll call add again then you get the leaked window pointing to a function that doesn’t exist causing the soft lock.

    Chris do you want to work together to fix these problems? if so contact me by email.

  34. Louis says:

    I’m totally new in Windows Mobile but I’m working in a company on software development with Windows (C++, VB, …, Fortran !) since a lot of years. And also new in mobiles…
    I would like, for starting, to modify the notification window : increase the size, use a larger and bold font, and modify the softkeys for incoming SMS.
    I see it’s possible to capture the window (similar to XP) but, as I’m a beginner, I just would like to start with a short program which manages the notification window by running it without capture. I’ll run it with a button not used on the edge of the phone (HTC).
    I think that is quite easy but … could you tell me which environment is the best and the most practical for the development ? Is .NET Compact Framework absolutely needed ?
    Do you know – don’t laugh ! – if we can use very old tools like VB toolkit for Windows CE ? It seems there is not a big difference between CE and WM6.
    Thanks in advance.

  35. SpacixOne says:

    @Louis: You don’t need to capture the windows at all. The notification toast window contains an IE control which displays the text. This lets you make the font bold by adding this is bolded text tags inside the “Text” property. The same goes for the standard .NET 2.0 notification window too.

  36. SpacixOne says:

    Edit of my previous post (I didn’t know HTML was enabled)

    you can add <b>this is bolded text</b> around text and it’ll bold it.

  37. Louis says:

    I know this usual function in the HTML language but how to convert the notification which comes up ? Is there a template file to use ? Or do you mean that I have to read the HTML contents of the notification and then modify it ? If so, how to programmatically read the contents ?

  38. Arun says:

    This one is a really good article. Do you know if a system notification susch as missed call notification can be supressed and displayed custom notification described in your article?

  39. TK says:

    Hello Chris,

    This is excellent article.

    But when i click on a hyper link on a notification window, the link is not opening any browser.

    Then I tried to used right menu item “Open” event handler to open default browser in mobile. But I don’t know how to open Internet explorer application programatically when a “Open” menu item is clicked.

    And i want to create a background service for Windows Mobile 6.0. This service calls an online web service for every 12 hours and display notifications based on result of web service.

    To write a background service, what type of Mobile Project should i select in VS2005?

    Could you please provide some sample code for writing background service using/notusing Windows Forms.

    Waiting for your valuable reply….
    itsvtk

  40. JB says:

    This is great Chris! you rock.

  41. SpacixOne says:

    @Louis: Sorry for the delay, I’ve been busy.

    Once you obtain a handle to the window you can then read and rewrite the text in the control with native code or interop from managed code.

    The SetWindowText(HWND hWnd, LPCTSTR lpString); function should change the top text, and IE control can be sent the DTM_ADDTEXT message.

    You may be able to grab an instance and edit it in memory. Here is the control I think the window contains: http://msdn.microsoft.com/en-us/library/bb159694.aspx YMMV

  42. SpacixOne says:

    @TK:

    You need to process the click inside your application and have the application open the IE window.

    The following code example should be enough to get you a new IE window inside your application.

                Process OpenBrowser = new Process();
                //Add your URL as the file name to open the address in IE Mobile
                OpenBrowser.StartInfo.FileName = @"http://www.christec.co.nz";
                //Always call Dispose the process instance.
                //  this does NOT close the IE window
                OpenBrowser.Dispose();
  43. Wow — Nice work. Saved me a WHOLE lot of time. Many thanks!!

  44. Prabhu says:

    Hi,

    Great Article. Its been a very long time, any update regarding the menu based Notification control. Am stuck at the point of how to pass HMENU parameter of SOFTKEYMENU using c#.

  45. Dear Chris,

    First, I’d like to thank you for sharing the great code! I found it very useful. Unfotunately, sometimes, when dismiss button is clicked, I receive KeyNotFound exception. I tried to contact you, but contact form on your blog it is not working (I can’t see it). I was wondering is it possible for you to drop me a line and I’d describe this issue in more details. Many thanks in advance and very best regards from Poland!

  46. Dear Chris,

    I’m trying to contact you regarding NotificationWithSoftKeys class and exception I receive. Unfortunately I can’t see contact form on your blog. I also tried to submit a comment, but with no luck. I hope this time it will work. I was wondering if you could drop me a line and I could describe my issue in more details. Very best regards and many thanks in advance!

  47. Hi, I used you code in this program: http://www.alexju.be/SMSChat/

    Thx vm!

  48. Flemming Ast says:

    Question. How can you force your own Icon to show always at the top form frame in Windows Mobile to launch an application?

    Thank you.

  49. JRock says:

    you, sir, are the man.

  50. Juan says:

    Hi!

    We wanted to use this code in our application MoBots (www.mobots.org).

    Would there be any problem to use it as is in our application?

    Thanks in advance,
    Juan

Leave a Reply