Eliminar un icono de una bandeja

Using the code below results in that sometimes an icon remains in a tray right after call to removeIconFromTray method and disappears only after a user moves over an icon in tray.

void CMyDlg::addIconToTray()
{
    static HICON hIcon = ::LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON));
    NOTIFYICONDATA data;

    data.cbSize = sizeof(data);
    data.hIcon = hIcon;
    data.hWnd = m_hWnd;
    strcpy (data.szTip, m_sTrayIconTip.c_str());
    data.uFlags = NIF_ICON | NIF_TIP;
    data.uID = (UINT)this;

    Shell_NotifyIcon (NIM_ADD, &data);
}

void CMyDlg::removeIconFromTray()
{
    NOTIFYICONDATA data;

    data.cbSize = sizeof(data);
    data.hWnd = m_hWnd;
    data.uID = (UINT)this;

    Shell_NotifyIcon (NIM_DELETE, &data);

}

Whats wrong in this code and how to achieve that an icon disappears from a tray as soon as a code deleting it form there finished working?

preguntado el 08 de noviembre de 11 a las 13:11

You don't check the return value of Shell_NotifyIcon. So you cannot know when it failed, you can only watch it misbehave. Arbitrary guess is that m_hWnd was already destroyed. -

3 Respuestas

One obvious problem is that you are failing to initialize your struct. You should do this:

NOTIFYICONDATA data = { 0 };

Other than that check for errors and call GetLastError to find out what caused any error.

respondido 08 nov., 11:18

This is particularly important in the NIM_DELETE case, as the data.uFlags field is not being initialized, so it likely is getting set to random bits that are causing NIM_DELETE fallar. - Remy Lebeau

Según MSDN:

Shell_NotifyIcon function

Deletes an icon from the status area. NOTIFYICONDATA structure pointed to by lpdata uses the ID originally assigned to the icon when it was added to the notification area (NIM_ADD) to identify the icon to be deleted.

So, you should pass the same data of NOTIFYICONDATA to Shell_NotifyIcon function.

void CMyDlg::addIconToTray()
{
    static HICON hIcon = ::LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_MYICON));
    NOTIFYICONDATA data;

    data.cbSize = sizeof(data);
    data.hIcon = hIcon;
    data.hWnd = m_hWnd;
    strcpy (data.szTip, m_sTrayIconTip.c_str());
    data.uFlags = NIF_ICON | NIF_TIP;
    data.uID = (UINT)this;

    Shell_NotifyIcon (NIM_ADD, &data);
}

void CMyDlg::removeIconFromTray()
{
    NOTIFYICONDATA data;

    data.cbSize = sizeof(data);
    data.hIcon = hIcon;
    data.hWnd = m_hWnd;
    strcpy (data.szTip, m_sTrayIconTip.c_str());
    data.uFlags = NIF_ICON | NIF_TIP;
    data.uID = (UINT)this;

    Shell_NotifyIcon (NIM_DELETE, &data);

}

This will work properly. Or, save the data to a member variable.

Respondido 04 Abr '15, 01:04

You DO NOT need to do this. Specifying , de manera the same HWND and ID as those used with NIM_ADD is enough, as those are the only fields that NIM_DELETE looks at (since NIF_GUID is not being used). - Remy Lebeau

As DavidHeffernan said, you should zero-initialize your data struct (you should ALWAYS zero-init any struct that you pass to a Win32 API function), eg:

NOTIFYICONDATA data = {0};

o:

NOTIFYICONDATA data;
ZeroMemory(&data, sizeof(data));

This way, any unused fields have consistent and predictable values. In your case, when calling NIM_DELETE, you are not initializing data, entonces es uFlags field will have random bits, which is likely to cause Shell_NotifyIcon() to misinterpret the content of your NOTIFYICONDATA and fail, and thus your icon is not removed.

Respondido 04 Abr '15, 01:04

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.