Как отобразить всплывающую подсказку со значком уведомлений оболочки по требованию?

Моя цель — создать значок уведомления оболочки и заставить его отображать всплывающую подсказку при необходимости. Я написал следующий код.

bool SystemTrayIcon::Create(const std::wstring &    Tip,
HWND                    hWndParent,
const GUID &            Guid,
UINT                    IdCallback,
HICON                   hIcon,
TYPE                    Type,
bool                    bSound,
bool                    bSharedIcon,
bool                    bHidden,
bool                    bLargeIcon,
bool                    bRespectQuiteTime)
{
NotifyIconData.cbSize           = sizeof(NotifyIconData);
NotifyIconData.hWnd             = hWndParent;
NotifyIconData.uID              = 0;    // Use GUID instead. (NIF_GUID)
NotifyIconData.uFlags           = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_STATE | NIF_GUID | NIF_REALTIME | NIF_SHOWTIP;
NotifyIconData.uCallbackMessage = IdCallback;
NotifyIconData.hIcon            = hIcon;

if (Tip.length() > MAX_TIP)
{
std::wcsncpy(NotifyIconData.szTip, Tip.c_str(), MAX_TIP);
NotifyIconData.szTip[MAX_TIP] = wchar_t(0);
}
else
{
std::wcsncpy(NotifyIconData.szTip, Tip.c_str(), Tip.length() + 1);
}

NotifyIconData.dwState          = (bSharedIcon      ? NIS_SHAREDICON    : 0)
| (bHidden          ? NIS_HIDDEN        : 0);
NotifyIconData.dwStateMask      = NIS_SHAREDICON | NIS_HIDDEN;
NotifyIconData.uVersion         = NOTIFYICON_VERSION_4;

DWORD dwType;
switch (Type)
{
case TYPE::STI_INFO:
dwType = NIIF_INFO;
break;
case TYPE::STI_WARNING:
dwType = NIIF_WARNING;
break;
case TYPE::STI_ERROR:
dwType = NIIF_ERROR;
break;
}

NotifyIconData.dwInfoFlags      = dwType | NIIF_USER
| (bSound               ? 0                         :   NIIF_NOSOUND)
| (bLargeIcon           ? NIIF_LARGE_ICON           :   0)
| (bRespectQuiteTime    ? NIIF_RESPECT_QUIET_TIME   :   0);

NotifyIconData.guidItem         = Guid;

return bInitialized = Shell_NotifyIconW(NIM_ADD, &NotifyIconData);
}

void SystemTrayIcon::Balloon(   const std::wstring &    Title,
const std::wstring &    Message,
HICON                   hBalloonIcon)
{
if (!bInitialized) return;
if (Title.length() > MAX_TITLE)
{
std::wcsncpy(NotifyIconData.szInfoTitle, Title.c_str(), MAX_TITLE);
NotifyIconData.szInfoTitle[MAX_TITLE] = wchar_t(0);
}
else
{
std::wcsncpy(NotifyIconData.szInfoTitle, Title.c_str(), Title.length() + 1);
}
if (Message.length() > MAX_MESSAGE)
{
std::wcsncpy(NotifyIconData.szInfo, Message.c_str(), MAX_MESSAGE);
NotifyIconData.szInfo[MAX_MESSAGE] = wchar_t(0);
}
else
{
std::wcsncpy(NotifyIconData.szInfo, Message.c_str(), Message.length() + 1);
}
NotifyIconData.hBalloonIcon = hBalloonIcon;
NotifyIconData.dwInfoFlags |= NIF_INFO;
Update();
}

void SystemTrayIcon::Update()
{
Shell_NotifyIconW(NIM_MODIFY, &NotifyIconData);
}

Я вызываю эти функции-члены в коде так:

TrayIcon.Create(/*const std::wstring &  Tip*/               L"Tip",
/*HWND                  hWndParent*/        Window.hWnd,
/*const GUID &          Guid*/              GUID {0x7f0f02e3, 0x479b, 0x4a09, {0xbf, 0x99, 0xd3, 0x39, 0xe9, 0x3a, 0x8b, 0x22}},
/*UINT                  IdCallback*/        ID_TRAYICON,
/*HICON                 hIcon*/             (HICON) LoadImageW(Status::hInstance, L"icon1.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE),
/*TYPE                  Type*/              SystemTrayIcon::TYPE::STI_INFO,
/*bool                  bSound*/            true,
/*bool                  bSharedIcon*/       false,
/*bool                  bHidden*/           false,
/*bool                  bLargeIcon*/        true,
/*bool                  bRespectQuiteTime*/ false);
Sleep(10000);
TrayIcon.Balloon(   L"New Title",
L"New Message",
(HICON) LoadImageW(Status::hInstance, L"icon2.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE));

Значок отображается правильно после вызова Create() метод. Но Balloon() метод не имеет никакого эффекта. Не отображается наконечник баллона.

Я могу заставить его отображать воздушный шар при создании, добавив NIF_INFO постоянный uFlagsи заполняя szInfoTitle а также szInfo члены. Но я пытаюсь показать это в любое произвольное время, вызывая Balloon() метод.

Что мне здесь не хватает?

0

Решение

Я решил много проблем в моем коде. Теперь он работает отлично и как я хотел. Ниже мой новый код. Обратите внимание на изменения.

bool SystemTrayIcon::Create(const std::wstring &    Tip,
HWND                    hWndParent,
const GUID &            Guid,
UINT                    IdCallback,
HICON                   hIcon,
bool                    bSharedIcon,
bool                    bHidden)
{
if (bInitialized) return false;

NotifyIconData.cbSize           = sizeof(NotifyIconData);
NotifyIconData.hWnd             = hWndParent;
NotifyIconData.uID              = 0;    // Use GUID instead. (NIF_GUID)
NotifyIconData.uFlags           = NIF_MESSAGE | NIF_ICON | NIF_TIP | NIF_STATE | NIF_GUID | NIF_SHOWTIP;
NotifyIconData.uCallbackMessage = IdCallback;
NotifyIconData.hIcon            = hIcon;

if (Tip.length() > MAX_TIP)
{
std::wcsncpy(NotifyIconData.szTip, Tip.c_str(), MAX_TIP);
NotifyIconData.szTip[MAX_TIP] = wchar_t(0);
}
else
{
std::wcsncpy(NotifyIconData.szTip, Tip.c_str(), Tip.length() + 1);
}

NotifyIconData.dwState          = (bSharedIcon      ? NIS_SHAREDICON    : 0)
| (bHidden          ? NIS_HIDDEN        : 0);
NotifyIconData.dwStateMask      = NIS_SHAREDICON | NIS_HIDDEN;

NotifyIconData.guidItem         = Guid;

bInitialized = Shell_NotifyIconW(NIM_ADD, &NotifyIconData);

NotifyIconData.uVersion         = NOTIFYICON_VERSION_4;
bLastResult = Shell_NotifyIconW(NIM_SETVERSION, &NotifyIconData);

return bInitialized;
}

void SystemTrayIcon::Balloon(   const std::wstring &    Title,
const std::wstring &    Message,
HICON                   hBalloonIcon,
BALLOON_ICON_TYPE       IconType,
UINT                    Timeout,    // In milliseconds.
bool                    bSound,
bool                    bLargeIcon,
bool                    bRespectQuiteTime)
{
if (!bInitialized) return;

if (Title.length() > MAX_TITLE)
{
std::wcsncpy(NotifyIconData.szInfoTitle, Title.c_str(), MAX_TITLE);
NotifyIconData.szInfoTitle[MAX_TITLE] = wchar_t(0);
}
else
{
std::wcsncpy(NotifyIconData.szInfoTitle, Title.c_str(), Title.length() + 1);
}

if (Message.length() > MAX_MESSAGE)
{
std::wcsncpy(NotifyIconData.szInfo, Message.c_str(), MAX_MESSAGE);
NotifyIconData.szInfo[MAX_MESSAGE] = wchar_t(0);
}
else
{
std::wcsncpy(NotifyIconData.szInfo, Message.c_str(), Message.length() + 1);
}

DWORD dwType;
switch (IconType)
{
case BALLOON_ICON_TYPE::BIT_NONE:
dwType = 0;
break;
case BALLOON_ICON_TYPE::BIT_INFO:
dwType = NIIF_INFO;
break;
case BALLOON_ICON_TYPE::BIT_WARNING:
dwType = NIIF_WARNING;
break;
case BALLOON_ICON_TYPE::BIT_ERROR:
dwType = NIIF_ERROR;
break;
case BALLOON_ICON_TYPE::BIT_USER_DEFINED:
dwType = NIIF_USER; // Use the "hBalloonIcon" parameter.
break;
}

NotifyIconData.dwInfoFlags      = dwType
| (bSound               ? 0                         :   NIIF_NOSOUND)
| (bLargeIcon           ? NIIF_LARGE_ICON           :   0)
| (bRespectQuiteTime    ? NIIF_RESPECT_QUIET_TIME   :   0);

NotifyIconData.uTimeout     = Timeout;
NotifyIconData.hBalloonIcon = hBalloonIcon;
NotifyIconData.uFlags       = NIF_INFO | NIF_GUID;

Update();
}

void SystemTrayIcon::Update()
{
bLastResult = Shell_NotifyIconW(NIM_MODIFY, &NotifyIconData);
}

Использование в коде:

TrayIcon.Create(/*const std::wstring &  Tip*/               L"Tip",
/*HWND                  hWndParent*/        Window.hWnd,
/*const GUID &          Guid*/              GUID {0x7f0f02e4, 0x479b, 0x4a09, {0xbf, 0x99, 0xd3, 0x39, 0xe9, 0x3a, 0x8b, 0x22}},
/*UINT                  IdCallback*/        ID_TRAYICON,
/*HICON                 hIcon*/             (HICON) hImage,
/*bool                  bSharedIcon*/       false,
/*bool                  bHidden*/           false);

// ...

TrayIcon.Balloon(   L"Button 2",
L"You have just clicked the Button #2.",
(HICON) hImage,
SystemTrayIcon::BALLOON_ICON_TYPE::BIT_USER_DEFINED,
20000U,
true,
true,
false);
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]