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);