Thread: Windows task tray icons

  1. #1
    Registered User
    Join Date
    Mar 2006
    Posts
    150

    Windows task tray icons

    I need help. I want to be able to put an application icon in the task tray to restore an application, but i have no clue where to start. I researched the topic on the MSDN, but they aren't very clear about things and i got completely lost. Here is some code i came up with to do this.
    Code:
    #include <windows.h>
    #include <shellapi.h>
    #include <iostream>
    #include <WindowClasses.h>
    #include <string.h>
    
    #define TASKBAR_RESTORE 0x2000
    #define _WIN32_IE 0x0600
    
    using namespace std;
    
    LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
     cout << msg;
    
     switch (msg)
     {
      case WM_CLOSE:
    
           DestroyWindow (hwnd);
           break;
    
      case WM_DESTROY:
    
           PostQuitMessage(0);
           break;
      
      case TASKBAR_RESTORE:
    
           MessageBox (NULL, "I'm doing stuff in the task bar", "HEY!!!", MB_OK);
    
           switch (lParam)
           {
            case WM_CONTEXTMENU:
           
             MessageBox (NULL, "The Mouse moved!!!", "HEY!!!", MB_OK);
             PostMessage (hwnd, SW_SHOW, 0, 0);
             break;
           }
    
      default:
      
           return DefWindowProc (hwnd, msg, wParam, lParam);
     }
     cout << msg;
    
     return 0;
    }
     
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
     WINDOW window;
     MSG Msg;
     NOTIFYICONDATA icon_dat;
     InitWindowClasses (hInstance);
    
     // initialize icon data
    
     icon_dat.cbSize           = sizeof (NOTIFYICONDATA);
     icon_dat.hWnd             = window.GetHandle();
     icon_dat.uID              = 10;
     icon_dat.uFlags           = NIF_MESSAGE | NIF_ICON;
     icon_dat.uCallbackMessage = TASKBAR_RESTORE;
     icon_dat.hIcon            = LoadIcon (NULL, IDI_APPLICATION);
    
     window.MakeWindow ("Test Window", 200, 200, 200, 200, WndProc);
     ShowWindow (window.GetHandle(), SW_SHOW);
     UpdateWindow (window.GetHandle());
    
     Shell_NotifyIcon (NIM_ADD, &icon_dat);
    
     while(GetMessage(&Msg, NULL, 0, 0) > 0)
     {
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
     }
     return Msg.wParam;
    }
    the class window is in a different header if you need that too:

    Code:
    #ifndef WINDOW_CLASSES_H
    #define WINDOW_CLASSES_H
    
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    LRESULT CALLBACK Default (HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
    {
    }
    
    HWND defaultWnd;
    HINSTANCE instance;
    
    int InitWindowClasses (HINSTANCE progInstance)
    {
     WNDCLASSEX wc;
    
     instance = progInstance;
    
     wc.cbSize        = sizeof(WNDCLASSEX);
     wc.style         = 0;
     wc.lpfnWndProc   = Default;
     wc.cbClsExtra    = 0;
     wc.cbWndExtra    = 0;
     wc.hInstance     = progInstance;
     wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
     wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
     wc.hbrBackground = (HBRUSH)(COLOR_BACKGROUND+15);
     wc.lpszMenuName  = NULL;
     wc.lpszClassName = "WindowClass";
     wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
    
     if (!RegisterClassEx (&wc))
     {
      return -1;
     }
     defaultWnd = CreateWindow (
                  "WindowClass",
                  "HELLO",
                  WS_DISABLED,
                  1, 
                  1,
                  1,
                  1,
                  NULL,
                  NULL,
                  progInstance,
                  NULL);
     return 0;
    }
    
    class WINDOW
    {
     private:
      
      HWND *controls;
      HWND winCreated;
      int index, count;
      bool firstControl;
      friend int DestroyWndVar ();
    
     public:
    
      int MakeWindow (const char *WinTitle, int xPos, int yPos, int xSize, int ySize, WNDPROC wndproc)
      {
       if (SetClassLong (defaultWnd, GCL_WNDPROC, (LONG) wndproc) == 0)
        return -1;
       
       winCreated = CreateWindow (
                    "WindowClass",
    	            WinTitle,
    	            WS_OVERLAPPEDWINDOW,
    	            xPos,
    	            yPos,
    	            xSize,
    	            ySize,
    	            NULL,
    	            NULL,
    	            instance,
    	            NULL);
       index = 0;
       count = 1;
       controls = (HWND *) malloc (1);
       firstControl = true;
    
       return 0;
      }
      int  AddButton (const char *ButtonText, int xPos, int yPos, int xSize, int ySize)
      {
       HWND button;
       HWND *temp;
    
       button = CreateWindow (
                "BUTTON",
    	        ButtonText,
    	        WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
    	        xPos,
    	        yPos,
    	        xSize,
    	        ySize,
    	        winCreated,
                (HMENU) index,
    	        instance,
    	        NULL);
    
       controls[index] = button;
       ++index;
       ++count;
       temp = (HWND *) realloc (controls, count * sizeof (HWND));
       if (temp == NULL)
       {
        return -1;
       }
       controls = temp;
       return 0;
      }
      int  AddTextBox     (const char *starttext, int xPos, int yPos, int xSize, int ySize)
      {
       HWND textbox;
       HWND *temp;
    
       textbox = CreateWindow (
                "EDIT",
    	        starttext,
    	        WS_CHILD | WS_VISIBLE | WS_BORDER |ES_AUTOHSCROLL | WS_GROUP | WS_TABSTOP,
    	        xPos,
    	        yPos,
    	        xSize,
    	        ySize,
    	        winCreated,
                (HMENU) index,
    	        instance,
    	        NULL);
    
       controls[index] = textbox;
       ++index;
       ++count;
       temp = (HWND *) realloc (controls, count * sizeof (HWND));
       if (temp == NULL)
       {
        return -1;
       }
       controls = temp;
       return 0;
      }
      int  AddComboBox    (const char *data[], int arrayItems, int xPos, int yPos, int xSize, int ySize)
      {
       HWND combobox;
       HWND *temp;
    
       combobox = CreateWindow (
                "COMBOBOX",
    	        "",
    	        WS_CHILD | WS_VISIBLE | WS_VSCROLL | CBS_HASSTRINGS | CBS_DROPDOWNLIST | WS_TABSTOP,
    	        xPos,
    	        yPos,
    	        xSize,
    	        ySize,
    	        winCreated,
                (HMENU) index,
    	        instance,
    	        NULL);
    
       for (int added = 0; added < arrayItems; added++)
       {
        SendMessage (combobox, CB_ADDSTRING, 0, (LPARAM) data[added]);
       }
    
       controls[index] = combobox;
       ++index;
       ++count;
       temp = (HWND *) realloc (controls, count * sizeof (HWND));
       if (temp == NULL)
       {
        return -1;
       }
       controls = temp;
       return 0;
      }
      int  AddStaticText  (const char *text, int xPos, int yPos, int xSize, int ySize)
      {
       HWND statictext;
       HWND *temp;
    
       statictext = CreateWindow (
                "STATIC",
    	        text,
    	        WS_CHILD | WS_VISIBLE,
    	        xPos,
    	        yPos,
    	        xSize,
    	        ySize,
    	        winCreated,
                (HMENU) index,
    	        instance,
    	        NULL);
    
       controls[index] = statictext;
       ++index;
       ++count;
       temp = (HWND *) realloc (controls, count * sizeof (HWND));
       if (temp == NULL)
       {
        return -1;
       }
       controls = temp;
       return 0;
      }
      void Visible (int show)
      {
       ShowWindow (winCreated, show);
       UpdateWindow (winCreated);
      }
      HWND GetHandle (void)
      {
       return winCreated;
      }
    };
    
    #endif
    i know that it isnt very heavily error checked, but if anyone can help me with this, i would be very very greatful. I have no clue where to even start!

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    If it would help you, I can share my own tray icon source.
    But typically, in your window proc, all you need to do is check for your callback message, and then check the low word of the lParam for the actual message:

    Code:
    		switch ( LOWORD(lParam) )
    		{
    			case WM_RBUTTONUP: // User right-clicked on the tray icon
    		}
    If you want to display a menu when the user right-clicks, you would load the menu and call TrackPopupMenu:
    Code:
    	uint32_t TrackPopupMenu(CMenu& Menu)
    	{
    		POINT p;
    		GetCursorPos(&p);
    		Stuff::pMsgDlg->SetForegroundWindow();
    		uint32_t Temp = (uint32_t)Menu.TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN | TPM_RIGHTBUTTON, p.x, p.y, Stuff::pMsgDlg);
    		Stuff::pMsgDlg->PostMessage(WM_NULL);
    	}
    According to MSDN, before display the popup menu, your notification window must be in the foreground.
    And afterwards, you must post WM_NULL message.
    The code illustrates this.
    Last edited by Elysia; 05-22-2008 at 01:41 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Registered User
    Join Date
    Mar 2006
    Posts
    150
    Well, that helps a little, but for some reason when i run the program i wrote, the icon disappears as soon as i mouse over it., even though i checked for the message and handled the loword of lparam. nothing i have tried has helped. I also got an error when i tried to set the item icon_data.szTip to "Tooltip". The compiler told me that i couldnt convert "const char * to CHAR[64]". I just want it to bring up a program window when someone clicks on the icon for now, i'll add a menu later.
    Last edited by xixpsychoxix; 05-22-2008 at 08:22 PM.

  4. #4
    Registered User
    Join Date
    Apr 2008
    Posts
    58
    icon_dat.cbSize = sizeof (NOTIFYICONDATA);
    icon_dat.hWnd = window.GetHandle();
    icon_dat.uID = 10;
    icon_dat.uFlags = NIF_MESSAGE | NIF_ICON;
    icon_dat.uCallbackMessage = TASKBAR_RESTORE;
    icon_dat.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    icon disappearing is why icon_dat.hWnd doesnt get correct value in 2 line.

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by xixpsychoxix View Post
    Well, that helps a little, but for some reason when i run the program i wrote, the icon disappears as soon as i mouse over it., even though i checked for the message and handled the loword of lparam. nothing i have tried has helped.
    It means the tray icon has not been associated with a valid window handle. When windows encounters such an icon, it removes it for the tray.

    I also got an error when i tried to set the item icon_data.szTip to "Tooltip". The compiler told me that i couldnt convert "const char * to CHAR[64]".
    The structure contains a string buffer, not a string pointer, so you need to copy the string into the buffer using strcpy.

    I just want it to bring up a program window when someone clicks on the icon for now, i'll add a menu later.
    Then you can handle the left-click message instead.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Registered User
    Join Date
    Mar 2006
    Posts
    150
    once again the cprogramming.com message board has come through!!!! Thanks guys, but i have one more question. Does anyone know what the name of the message is that is processed when a window is minimized or maximized? I cant seem to find that on the MSDN either.

  7. #7
    Registered User
    Join Date
    Apr 2008
    Posts
    58
    ON_WM_SIZE.
    is everything ok?

  8. #8
    Registered User
    Join Date
    Mar 2006
    Posts
    150
    yeah it should be. thanx alot guys

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by sgh View Post
    ON_WM_SIZE.
    No, that's wrong.
    Try WM_SHOWWINDOW instead.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how to make a windows application
    By crvenkapa in forum C++ Programming
    Replies: 3
    Last Post: 03-26-2007, 09:59 AM
  2. Script errors - bool unrecognized and struct issues
    By ulillillia in forum Windows Programming
    Replies: 10
    Last Post: 12-18-2006, 04:44 AM
  3. Windows task won't trigger..
    By knutso in forum Windows Programming
    Replies: 2
    Last Post: 12-03-2004, 01:28 AM
  4. IE 6 status bar
    By DavidP in forum Tech Board
    Replies: 15
    Last Post: 10-23-2002, 05:31 PM
  5. Manipulating the Windows Clipboard
    By Johno in forum Windows Programming
    Replies: 2
    Last Post: 10-01-2002, 09:37 AM