views:

230

answers:

1

Hail all! I want to display notification and play custom sound on my Windows Mobile 5/6 device. I have tried something like that, but my custom sound does not play, though message is displayed with standart sound.

If i edit Wave key in [HKEY_CURRENT_USER\ControlPanel\Notifications{15F11F90-8A5F-454c-89FC-BA9B7AAB0CAD}] to sound file i need then it plays okay. But why there are flag NotificationAction.Sound and property UserNotification.Sound? It doesn't work. Also Vibration and Led don't work, if i use such flags.

(You can obtain full project sources from http://dl.dropbox.com/u/1758206/Code/Thunder.zip)

var trigger = new UserNotificationTrigger
{
    StartTime = DateTime.Now + TimeSpan.FromSeconds(1),
    Type = NotificationType.ClassicTime
};
var userNotification = new UserNotification
{
    Sound = @"\Windows\Alarm1.wma",
    Text = "Hail from Penza, Russia!",
    Action = NotificationAction.Dialog | NotificationAction.Sound,
    Title = string.Empty,
    MaxSound = 16384
};
NotificationTools.SetUserNotification(0, trigger, userNotification);

UserNotificationTrigger.cs:

using System;
using System.Runtime.InteropServices;

namespace Thunder.Lib.ThunderMethod1
{
    /// <summary>
    /// Specifies the type of notification.
    /// </summary>
    public enum NotificationType
    {
        /// <summary>
        /// Equivalent to using the SetUserNotification function.
        /// The standard command line is supplied.
        /// </summary>
        ClassicTime = 4,
        /// <summary>
        /// System event notification.
        /// </summary>
        Event = 1,
        /// <summary>
        /// Time-based notification that is active for the time period between StartTime and EndTime.
        /// </summary>
        Period = 3,
        /// <summary>
        /// Time-based notification.
        /// </summary>
        Time = 2
    }

    /// <summary>   
    /// System Event Flags   
    /// </summary>
    public enum NotificationEvent
    {
        None,
        TimeChange,
        SyncEnd,
        OnACPower,
        OffACPower,
        NetConnect,
        NetDisconnect,
        DeviceChange,
        IRDiscovered,
        RS232Detected,
        RestoreEnd,
        Wakeup,
        TimeZoneChange,
        MachineNameChange,
        RndisFNDetected,
        InternetProxyChange
    }

    /// <summary>
    /// Defines what event activates a notification.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public class UserNotificationTrigger
    {
        internal int dwSize = 52;
        private int dwType;
        private int dwEvent;

        [MarshalAs(UnmanagedType.LPWStr)]
        private string lpszApplication = string.Empty;

        [MarshalAs(UnmanagedType.LPWStr)]
        private string lpszArguments;

        internal SYSTEMTIME stStartTime;
        internal SYSTEMTIME stEndTime;

        /// <summary>
        /// Specifies the type of notification.
        /// </summary>
        public NotificationType Type
        {
            get { return (NotificationType) dwType; }
            set { dwType = (int) value; }
        }

        /// <summary>
        /// Specifies the type of event should Type = Event.
        /// </summary>
        public NotificationEvent Event
        {
            get { return (NotificationEvent) dwEvent; }
            set { dwEvent = (int) value; }
        }

        /// <summary>
        /// Name of the application to execute.
        /// </summary>
        public string Application
        {
            get { return lpszApplication; }
            set { lpszApplication = value; }
        }

        /// <summary>
        /// Command line (without the application name). 
        /// </summary>
        public string Arguments
        {
            get { return lpszArguments; }
            set { lpszArguments = value; }
        }

        /// <summary>
        /// Specifies the beginning of the notification period.
        /// </summary>
        public DateTime StartTime
        {
            get { return stStartTime.ToDateTime(); }
            set { stStartTime = SYSTEMTIME.FromDateTime(value); }
        }

        /// <summary>
        /// Specifies the end of the notification period. 
        /// </summary>
        public DateTime EndTime
        {
            get { return stEndTime.ToDateTime(); }
            set { stEndTime = SYSTEMTIME.FromDateTime(value); }
        }
    }
}

UserNotification.cs:

using System.Runtime.InteropServices;

namespace Thunder.Lib.ThunderMethod1
{
    /// <summary>
    /// Contains information used for a user notification.
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public class UserNotification
    {
        private int ActionFlags;
        [MarshalAs(UnmanagedType.LPWStr)] private string pwszDialogTitle;
        [MarshalAs(UnmanagedType.LPWStr)] private string pwszDialogText;
        [MarshalAs(UnmanagedType.LPWStr)] private string pwszSound;
        private int nMaxSound;
        private int dwReserved;

        /// <summary>
        /// Any combination of the <see cref="T:Thunder.Lib.NotificationAction" /> members.  
        /// </summary>
        /// <value>Flags which specifies the action(s) to be taken when the notification is triggered.</value>
        /// <remarks>Flags not valid on a given hardware platform will be ignored.</remarks>
        public NotificationAction Action
        {
            get { return (NotificationAction) ActionFlags; }
            set { ActionFlags = (int) value; }
        }

        /// <summary>
        /// Required if NotificationAction.Dialog is set, ignored otherwise
        /// </summary>
        public string Title
        {
            get { return pwszDialogTitle; }
            set { pwszDialogTitle = value; }
        }

        /// <summary>
        /// Required if NotificationAction.Dialog is set, ignored otherwise.
        /// </summary>
        public string Text
        {
            get { return pwszDialogText; }
            set { pwszDialogText = value; }
        }

        /// <summary>
        /// Sound string as supplied to PlaySound.
        /// </summary>
        public string Sound
        {
            get { return pwszSound; }
            set { pwszSound = value; }
        }

        public int MaxSound 
        { 
            get { return nMaxSound; }
            set { nMaxSound = value; } 
        }
    }
}

NativeMethods.cs:

using System;
using System.Runtime.InteropServices;

namespace Thunder.Lib.ThunderMethod1
{
    [StructLayout(LayoutKind.Sequential)]
    public struct SYSTEMTIME
    {
        public short wYear;
        public short wMonth;
        public short wDayOfWeek;
        public short wDay;
        public short wHour;
        public short wMinute;
        public short wSecond;
        public short wMillisecond;

        public static SYSTEMTIME FromDateTime(DateTime dt)
        {
            return new SYSTEMTIME
            {
                wYear = (short) dt.Year,
                wMonth = (short) dt.Month,
                wDayOfWeek = (short) dt.DayOfWeek,
                wDay = (short) dt.Day,
                wHour = (short) dt.Hour,
                wMinute = (short) dt.Minute,
                wSecond = (short) dt.Second,
                wMillisecond = (short) dt.Millisecond
            };
        }

        public DateTime ToDateTime()
        {
            if ((((wYear == 0) && (wMonth == 0)) && ((wDay == 0) && (wHour == 0))) && ((wMinute == 0) && (wSecond == 0)))
                return DateTime.MinValue;
            return new DateTime(wYear, wMonth, wDay, wHour, wMinute, wSecond, wMillisecond);
        }
    }

    /// <summary>
    /// Specifies the action to take when a notification event occurs.
    /// </summary>
    [Flags]
    public enum NotificationAction
    {
        /// <summary>
        /// Displays the user notification dialog box.
        /// </summary>
        Dialog = 4,
        /// <summary>
        /// Flashes the LED.
        /// </summary>
        Led = 1,
        /// <summary>
        /// Dialog box z-order flag.
        /// Set if the notification dialog box should come up behind the password.
        /// </summary>
        Private = 32,
        /// <summary>
        /// Repeats the sound for 10–15 seconds.
        /// </summary>
        Repeat = 16,
        /// <summary>
        /// Plays the sound specified.
        /// </summary>
        Sound = 8,
        /// <summary>
        /// Vibrates the device.
        /// </summary>
        Vibrate = 2
    }

    internal class NativeMethods
    {
        [DllImport("coredll.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode,
            SetLastError = true)]
        internal static extern int CeSetUserNotificationEx(int hNotification, UserNotificationTrigger lpTrigger,
            UserNotification lpUserNotification);
    }
}

NotificationTools.cs:

using System.ComponentModel;
using System.Runtime.InteropServices;

namespace Thunder.Lib.ThunderMethod1
{
    public static class NotificationTools
    {
        /// <summary>
        /// This function modifies an existing user notification.
        /// </summary>
        /// <param name="handle">Handle of the Notification to be modified</param>
        /// <param name="trigger">A UserNotificationTrigger that defines what event activates a notification.</param>
        /// <param name="notification">A UserNotification that defines how the system should respond when a notification occurs.</param>
        /// <returns>Handle to the notification event if successful.</returns>
        public static int SetUserNotification(int handle, UserNotificationTrigger trigger, UserNotification notification)
        {
            int num = NativeMethods.CeSetUserNotificationEx(handle, trigger, notification);
            if (num == 0)
                throw new Win32Exception(Marshal.GetLastWin32Error(), "Error setting UserNotification");
            return num;
        }
    }
}
A: 

Instead of defining the pwszSound variable in you UserNotification class as a string, try using StringBuilder, as according to the documentation it should be a pointer to a buffer with the sound's file name.

tomlog
But how?And there is also other variable with such type: [MarshalAs(UnmanagedType.LPWStr)] private string pwszDialogText; [MarshalAs(UnmanagedType.LPWStr)] private string pwszSound;and TCHAR* pwszDialogText; TCHAR* pwszSound;And it works good.
inTagger
Like this: [MarshalAs(UnmanagedType.LPWStr)] private StringBuilder pwszSound;But according to pinvoke.net it should work with the string type, so I might be wrong there: http://pinvoke.net/default.aspx/coredll/CE_USER_NOTIFICATION.html
tomlog
I have tried it before, it doesn't work. NotSupportedException.
inTagger