Thread: Problem with taskbar icon

  1. #1
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318

    Problem with taskbar icon

    This is my code:
    Code:
    #include <windows.h>
    #define WM_TASKBAR 45154
    #define IDI_ICON1 5001
    /*  Declare Windows procedure  */
    LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
    HWND hwnd;
    /*  Make the class name into a global variable  */
    char szClassName[ ] = "WindowsApp";
    LRESULT	TaskbarFunc(WPARAM wParam, LPARAM lParam);
    void RemoveTask();
    void CreateTask();
    int WINAPI WinMain (HINSTANCE hThisInstance,
                        HINSTANCE hPrevInstance,
                        LPSTR lpszArgument,
                        int nFunsterStil)
    
    {
        MSG messages;            /* Here messages to the application are saved */
        WNDCLASSEX wincl;        /* Data structure for the windowclass */
    
        /* The Window structure */
        wincl.hInstance = hThisInstance;
        wincl.lpszClassName = szClassName;
        wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
        wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
        wincl.cbSize = sizeof (WNDCLASSEX);
    
        /* Use default icon and mouse-pointer */
        wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
        wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
        wincl.lpszMenuName = NULL;                 /* No menu */
        wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
        wincl.cbWndExtra = 0;                      /* structure or the window instance */
        /* Use Windows's default color as the background of the window */
        wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    
        /* Register the window class, and if it fails quit the program */
        if (!RegisterClassEx (&wincl))
            return 0;
    
        /* The class is registered, let's create the program*/
        hwnd = CreateWindowEx (
               0,                   /* Extended possibilites for variation */
               szClassName,         /* Classname */
               "Windows App",       /* Title Text */
               WS_OVERLAPPEDWINDOW, /* default window */
               CW_USEDEFAULT,       /* Windows decides the position */
               CW_USEDEFAULT,       /* where the window ends up on the screen */
               544,                 /* The programs width */
               375,                 /* and height in pixels */
               HWND_DESKTOP,        /* The window is a child-window to desktop */
               NULL,                /* No menu */
               hThisInstance,       /* Program Instance handler */
               NULL                 /* No Window Creation data */
               );
    
        /* Make the window visible on the screen */
        ShowWindow (hwnd, nFunsterStil);
    
        /* Run the message loop. It will run until GetMessage() returns 0 */
        while (GetMessage (&messages, NULL, 0, 0))
        {
            /* Translate virtual-key messages into character messages */
            TranslateMessage(&messages);
            /* Send message to WindowProcedure */
            DispatchMessage(&messages);
        }
    
        /* The program return-value is 0 - The value that PostQuitMessage() gave */
        return messages.wParam;
    }
    
    
    /*  This function is called by the Windows function DispatchMessage()  */
    
    LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        switch (message)                  /* handle the messages */
        {
            case WM_CREATE:
                CreateTask();
                break;
            case WM_TASKBAR:{
                UINT uMouseMsg = (UINT) lParam;	
    	        switch (uMouseMsg){
    		        case WM_LBUTTONDOWN: MessageBox(HWND_DESKTOP,"Mouse click on the Icon !","WARNING",MB_OK);
    					 break;
    		        default: break;
    	        }
                break;}
            case WM_DESTROY:
                RemoveTask();
                PostQuitMessage (0);       /* send a WM_QUIT to the message queue */
                break;
            default:                      /* for messages that we don't deal with */
                return DefWindowProc (hwnd, message, wParam, lParam);
        }
    
        return 0;
    }
    void RemoveTask(){
    	NOTIFYICONDATA tnid; 
        tnid.cbSize = sizeof(NOTIFYICONDATA); 
        tnid.hWnd = hwnd; 
    	tnid.uID = IDI_ICON1;
    	Shell_NotifyIcon(NIM_DELETE, &tnid); 	
    }
    void CreateTask(){
    	HICON hIcon;
    	char lpszTip[] = "Mouse is on the Icon !!";
    	hIcon = (HICON)LoadImage(GetModuleHandle(NULL),MAKEINTRESOURCE(IDI_ICON1),IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
    	NOTIFYICONDATA tnid; 
        tnid.cbSize = sizeof(NOTIFYICONDATA); 
        tnid.hWnd = hwnd; 
        tnid.uID = IDI_ICON1; 
        tnid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; 
        tnid.uCallbackMessage = WM_TASKBAR; // my user message 
        tnid.hIcon = hIcon; 	
    	if (lpszTip){ lstrcpyn(tnid.szTip, lpszTip, sizeof(tnid.szTip));}
        else{ tnid.szTip[0] = '\0';}
    	Shell_NotifyIcon(NIM_ADD, &tnid); 
    	if (hIcon){ DestroyIcon(hIcon); }
    }
    This is what I've mixed up from different examples what were using AFX, were coded to be compatible with Visual C++ and don't work in normal compilers or used MFC instead of Win32.
    My problem is that when I move my mouse to the icon, it just disappears. What mistakes have I made?

    My resource.rc
    Code:
    5001               ICON    DISCARDABLE     "icon1.ico"

  2. #2
    Registered User
    Join Date
    May 2006
    Posts
    34
    I tried fixing your code, but I just couldn't figure it out. It seems to be all correct, but we must be overlooking something. I decided to just code my own, but it's slightly different.

    In my version, it creates the icon when it minimizes, and when you double click the icon, it will restore the window. I have another version also that creates a popup menu when you right click the icon, but I didn't include that version...let me know if you want to see that one.

    Code:
    #include <windows.h>
    
    #define ID_TRAYICON 0
    #define WM_USER_SHELLNOTIFY (WM_USER + 666)
    #define IDM_RESTORE 1000
    #define IDM_EXIT    1001
    
    HWND g_hWnd = NULL;
    
    void MinimizeToTray(void);
    void RestoreFromTray(void);
    void DeleteTrayIcon(void);
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
    {
    	static TCHAR szAppName[] = TEXT("Simple");
    	MSG          msg;
    	WNDCLASSEX   wndclass;
    
    	wndclass.cbSize        = sizeof(wndclass);
    	wndclass.style         = CS_HREDRAW | CS_VREDRAW;
    	wndclass.lpfnWndProc   = WndProc;
    	wndclass.cbClsExtra    = 0;
    	wndclass.cbWndExtra    = 0;
    	wndclass.hInstance     = hInstance;
    	wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    	wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
    	wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    	wndclass.lpszMenuName  = NULL;
    	wndclass.lpszClassName = szAppName;
    	wndclass.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
    
    	if (!RegisterClassEx(&wndclass))
    	{
    		MessageBox (NULL, TEXT("Error Registering Window Class!"), szAppName, MB_ICONERROR);
    		return -1;
    	}
    
    	g_hWnd = CreateWindow (szAppName,
    	                       TEXT("Simple Windows App"),
    	                       WS_OVERLAPPEDWINDOW,
    	                       CW_USEDEFAULT, CW_USEDEFAULT,
    	                       CW_USEDEFAULT, CW_USEDEFAULT,
    	                       NULL, NULL,
    	                       hInstance,
    	                       NULL);
    
    	ShowWindow(g_hWnd, iCmdShow);
    	UpdateWindow(g_hWnd);
    
    	while (GetMessage(&msg, NULL, 0, 0))
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    
    	return (int)msg.wParam;
    }
    
    
    LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    
    	switch (message)
    	{
    		case WM_CREATE:
    			break;
    
    		case WM_SIZE:
    		{
    			switch (LOWORD(wParam))
    			{
    				case SIZE_MINIMIZED:
    				{
    					MinimizeToTray();
    					break;
    				}
    				default:
    					break;
    			}
    			break;
    		}
    
    		case WM_USER_SHELLNOTIFY:  // user clicked tray icon
    			if (wParam == ID_TRAYICON)
    			{
    				switch (lParam)
    				{
    					case WM_LBUTTONDBLCLK :  // user double clicked tray icon
    						RestoreFromTray();
    						break;
    					default:
    						break;
    				}
    			}
    			break;
    
    		case WM_DESTROY :
    			DeleteTrayIcon();
    			PostQuitMessage(0);
    			break;
    
    		default:
    			break;
    	}
    
    	return DefWindowProc(hWnd, message, wParam, lParam) ;
    }
    
    void MinimizeToTray(void)
    {
    	NOTIFYICONDATA nid;
    	TCHAR tooltip[] = TEXT("Tray Icon");
    
    	nid.cbSize = sizeof(NOTIFYICONDATA);
    	nid.hWnd = g_hWnd;
    	nid.uID = ID_TRAYICON;
    	nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
    	nid.uCallbackMessage = WM_USER_SHELLNOTIFY;
    	nid.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    	lstrcpyn(nid.szTip, tooltip, sizeof(tooltip));
    
    	ShowWindow(g_hWnd, SW_HIDE);       // hide main window (in taskbar too) when minimized
    	Shell_NotifyIcon(NIM_ADD, &nid);   // add our icon to the system tray
    }
    
    void DeleteTrayIcon(void)
    {
    	NOTIFYICONDATA nid;
    
    	nid.cbSize = sizeof(NOTIFYICONDATA);
    	nid.hWnd = g_hWnd;
    	nid.uID = ID_TRAYICON;
    	Shell_NotifyIcon(NIM_DELETE, &nid);  // remove tray icon when restored
    }
    
    void RestoreFromTray(void)
    {
    	ShowWindow(g_hWnd, SW_RESTORE);      // unhide main window
    	SetForegroundWindow(g_hWnd);         // bring main window to foreground
    	DeleteTrayIcon();
    }
    Edit: I forgot to say. My version doesn't use any resources...it just uses the built-in application icon instead of a custom one. If you want a custom icon, you'll need to add an icon as a resource, and then in MinimizeToTray(), change this:

    Code:
    nid.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    to this:

    Code:
    nid.hIcon = (HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
    Last edited by veecee; 05-15-2006 at 03:38 PM.

  3. #3
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    Worked
    Last edited by maxorator; 05-16-2006 at 02:20 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Icon Help
    By The Brain in forum Windows Programming
    Replies: 11
    Last Post: 04-05-2009, 04:06 PM
  2. No Sound Icon in Taskbar!!!!
    By anirban in forum Tech Board
    Replies: 5
    Last Post: 03-03-2009, 01:03 PM
  3. Tray icon (taskbar) questions
    By maxorator in forum Windows Programming
    Replies: 3
    Last Post: 09-29-2006, 12:03 PM
  4. Laptop Problem
    By Boomba in forum Tech Board
    Replies: 1
    Last Post: 03-07-2006, 06:24 PM
  5. Bin packing problem....
    By 81N4RY_DR460N in forum C++ Programming
    Replies: 0
    Last Post: 08-01-2005, 05:20 AM