Why isn't my system tray icon sent by shell_notifyicon sending any message to my application when clicked?

-1

I am working on c# app that handles windowing and whatnot entirely through UI (I want it to have a super small footprint). I'm trying to add a system tray icon. I've successfully added the icon -- I see it when I trigger it in the app and it disappears when the app closes, but clicking on it doesn't do anything. I'd like to eventually use it to bring up a configuration screen.

I believe that I'm supposed to set the uCallbackMessage to an int value, and when I interact with the icon a win32 message object will be sent to the application with the handle as specified by hWnd of the NotifyIconData object, but I'm not seeing any messages received from the message processing loop. Am I missing some obvious configuration piece? Below is an MVCE that displays the same behavior.

public class Program
{
    public  static class User32Wrapper
    {
        // GetMessage
        [DllImport(@"user32.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern bool GetMessage(ref MSG message, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);
        [DllImport(@"user32.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern bool TranslateMessage(ref MSG message);
        [DllImport(@"user32.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
        public static extern long DispatchMessage(ref MSG message);

        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            long x;
            long y;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MSG
        {
            IntPtr hwnd;
            public uint message;
            UIntPtr wParam;
            IntPtr lParam;
            uint time;
            POINT pt;
        }
    }

    public static void Main(string[] args)
    {
        Console.WriteLine("HELLO");
        var bmp = new Bitmap(32, 32);
        var g = Graphics.FromImage(bmp);
        g.FillRectangle(Brushes.Red, new Rectangle(new Point(2, 2), new Size(28, 28)));

        Tray.CreateIcon(bmp.GetHicon(), Process.GetCurrentProcess().MainWindowHandle);

        User32Wrapper.MSG msg = new User32Wrapper.MSG();
        while (User32Wrapper.GetMessage(ref msg, IntPtr.Zero, 0, 0))
        {
            //I want to know every command it recieves
            Console.WriteLine($"{msg.message}");

            User32Wrapper.TranslateMessage(ref msg);
            User32Wrapper.DispatchMessage(ref msg);
            System.Threading.Thread.Sleep(10);
        }
    }
}

public static class Tray
{

    [DllImport("shell32.dll", SetLastError = true)]
    static extern bool Shell_NotifyIcon(NIM dwMessage, [In] ref NotifyIconData pnid);

    public enum NIM : int
    {
        ADD = 0x00000000,
        MODIFY = 0x00000001,
        DELETE = 0x00000002,
        SETFOCUS = 0x00000003,
        SETVERSION = 0x00000004,
    }

    [Flags]
    public enum NIF
    {
        MESSAGE = 0x01,
        ICON = 0x02,
        TIP = 0x04,
        STATE = 0x08,
        INFO = 0x10,
        GUID = 0x20,
        REALTIME = 0x40,
        SHOWTIP = 0x80,
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct NotifyIconData
    {
        public System.Int32 cbSize; // DWORD
        public System.IntPtr hWnd; // HWND
        public System.Int32 uID; // UINT
        public NIF uFlags; // UINT
        public System.Int32 uCallbackMessage; // UINT
        public System.IntPtr hIcon; // HICON
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
        public System.String szTip; // char[128]
        public System.Int32 dwState; // DWORD
        public System.Int32 dwStateMask; // DWORD
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public System.String szInfo; // char[256]
        public System.Int32 uTimeoutOrVersion; // UINT
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
        public System.String szInfoTitle; // char[64]
        public System.Int32 dwInfoFlags; // DWORD
    }

    public static void CreateIcon(IntPtr iconPtr, IntPtr OwnerApp)
    {
        var data = new NotifyIconData()
        {
            uID = 1,
            hWnd = OwnerApp,
            hIcon = iconPtr,
            uFlags = NIF.ICON | NIF.MESSAGE | NIF.TIP | NIF.INFO,
            szTip = "This is my ballon text, short and std out",
            uCallbackMessage = 0xBFFF,
            szInfo = "System Tray Icon",
            szInfoTitle = "Hello My Name Is"
        };
        data.cbSize = Marshal.SizeOf(data);


        Shell_NotifyIcon(NIM.ADD, ref data);
    }
}
c#
windows
trayicon
window-messages
asked on Stack Overflow Aug 25, 2020 by Sidney

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0