#c #winapi
#c #winapi
Вопрос:
Пожалуйста, взгляните на следующий код. Если я сохраню GUID
{ 0x781158ff, 0x21dd, 0x4aed,{ 0xb0, 0xc4, 0x6a, 0x75, 0xd7, 0x39, 0xc1, 0x67 } }
затем уведомления поступают при запуске приложения и при отправке пользователем NIM_MODIFY
во время выполнения.
Но, если я изменю GUID на
{ 0x781158ff, 0x21dd, 0x4aed,{ 0xb0, 0xc4, 0x6a, 0x75, 0xd7, 0x39, 0xc1, 0x66 } }
тогда значок отсутствует в трее. Журналы — это то, что ::Shell_NotifyIcon(NIM_DELETE, amp;m_notification_data)
производит Unknown error
, и ::Shell_NotifyIcon(NIM_ADD, amp;m_notification_data)
Unknown error
также производит. Я знаю, что этот идентификатор GUID (с 0x66 в конце) используется в другом приложении. в системе. Пожалуйста, объясните, как логика, связанная с GUID, работает при вызове Shell_NotifyIcon
.
Код приведен ниже.
ShellIcon notificMonWnd(NULL, LOG_PATH);
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Разместите код здесь.
// Инициализация глобальных строк
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
strcpy_s(szWindowClass, MYWNDCLASS);
MyRegisterClass(hInstance);
// Выполнить инициализацию приложения:
if (!InitInstance (hInstance, SW_HIDE))
{
return FALSE;
}
// ... more code
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Сохранить маркер экземпляра в глобальной переменной
HWND hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
// Initialize menu
hPopupMenu = CreatePopupMenu();
AppendMenuA(hPopupMenu, MF_STRING, ID_TRAY_ADD_TO_AUTORUN_CONTEXT_MENU_ITEM, "Add to Autorun");
AppendMenuA(hPopupMenu, MF_STRING, ID_TRAY_REMOVE_FROM_AUTORUN_CONTEXT_MENU_ITEM, "Remove from Autorun");
AppendMenuA(hPopupMenu, MF_SEPARATOR, 0, NULL);
AppendMenuA(hPopupMenu, MF_STRING, ID_TRAY_OPEN_LOG_CONTEXT_MENU_ITEM, "Open log");
AppendMenuA(hPopupMenu, MF_STRING, ID_TRAY_MODIFY_CONTEXT_MENU_ITEM, "Modify icon's data");
AppendMenuA(hPopupMenu, MF_SEPARATOR, 0, NULL);
AppendMenuA(hPopupMenu, MF_STRING, ID_TRAY_ABOUT_CONTEXT_MENU_ITEM, "About");
AppendMenuA(hPopupMenu, MF_STRING, ID_TRAY_EXIT_CONTEXT_MENU_ITEM, "Exit");
// Add icon to tray.
notificMonWnd.notify(NIM_ADD, TRAY_ICON_MESSAGE, hWnd, IDI_EXCLAMATION);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Разобрать выбор в меню:
switch (wmId)
{
// ... more code
case ID_TRAY_MODIFY_CONTEXT_MENU_ITEM:
OnModifyIcon(hWnd);
break;
// ... more code
}
}
break;
// ... more code
}
}
void OnModifyIcon(HWND hwnd)
{
Log::append(LOG_PATH, "OnModify", "entered");
notificMonWnd.notify(NIM_MODIFY, TRAY_ICON_MESSAGE, hwnd, IDI_EXCLAMATION);
Log::append(LOG_PATH, "OnModify", "exited");
}
bool ShellIcon::notify(unsigned int dwMessage, UINT uCallbackMessage, HWND hwnd, LPSTR iconId)
{
Log::append(m_log_path, "notify", "entered");
ZeroMemory(amp;m_notification_data, sizeof(NOTIFYICONDATA));
m_notification_data.cbSize = sizeof(NOTIFYICONDATA);
BOOL r = ::Shell_NotifyIcon(NIM_DELETE, amp;m_notification_data); // delete old balloon message
if (r == FALSE)
{
std::string msg;
utils::getLastErrorMessage(msg);
Log::append(m_log_path, "notify,NIM_DELETE", msg);
}
// N.B.!!! Displays balloon notification
m_notification_data.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE | NIF_INFO;
if (utils::isWin7OrLater())
{
m_notification_data.uFlags |= NIF_GUID;
// N.B.!!! GUID differs from GUID used in earlier call to Shell_NotifyIcon in onCreate.
// If you set the last value to 0x66 you'll never see the icon.
m_notification_data.guidItem = { 0x781158ff, 0x21dd, 0x4aed,{ 0xb0, 0xc4, 0x6a, 0x75, 0xd7, 0x39, 0xc1, 0x67 } };
}
else
{
m_notification_data.uID = 1; // superfluous as guidItem was set
}
// Set szInfo field.
m_notification_data.dwInfoFlags = NIIF_INFO; // info notification
::LoadString(m_module_instance, IDS_NOTIFICATION_TITLE, m_notification_data.szInfoTitle, sizeof(m_notification_data.szTip) / sizeof(TCHAR));
::LoadString(m_module_instance, IDS_DEFAULT_TIP_MESSAGE, m_notification_data.szInfo, sizeof(m_notification_data.szInfo) / sizeof(TCHAR));
// Set szTip field.
TCHAR notificationMessage[128] = { '' };
// concatenate <title> - <tool tip message>
::LoadString(m_module_instance, IDS_NOTIFICATION_TITLE, m_notification_data.szTip, sizeof(m_notification_data.szTip) / sizeof(TCHAR));
::LoadString(m_module_instance, IDS_DEFAULT_TIP, notificationMessage, sizeof(notificationMessage) / sizeof(TCHAR));
strcat_s(m_notification_data.szTip, _T(" - "));
strcat_s(m_notification_data.szTip, notificationMessage);
// Set icon.
m_notification_data.hIcon = ::LoadIcon(m_module_instance, iconId);
if (m_notification_data.hIcon == NULL)
{
std::string msg;
utils::getLastErrorMessage(msg);
Log::append(m_log_path, "notify,LoadIcon", msg);
}
// Please leave here code that may differ from original
// implementation of NotificationWindowMonitor::Notify
m_notification_data.uVersion = NOTIFYICON_VERSION_4;
m_notification_data.uCallbackMessage = uCallbackMessage;
m_notification_data.hWnd = hwnd;
r = ::Shell_NotifyIcon(dwMessage, amp;m_notification_data);
if (r == FALSE)
{
std::string msg;
utils::getLastErrorMessage(msg);
Log::append(m_log_path, "notify,Shell_NotifyIcon", msg);
}
Log::append(m_log_path, "notify", "exited");
return r;
}
Комментарии:
1. Вы получили ссылки на документацию, когда задавали тот же вопрос ранее. При удалении этого предыдущего вопроса вы также удалили всю информацию, которая была там представлена. Это бесполезно и довольно грубо.
2. @IInspectable, в документах говорится, что путь к двоичному файлу включен в регистрацию GUID значка и не может быть изменен. Как вы интерпретируете это предложение? Какую функцию мне вызвать, чтобы зарегистрировать GUID значка? Между ними я не перемещал двоичный файл.
3. В документации говорится о случайных попытках перерегистрировать GUID для значков области уведомлений. Распространенным режимом ошибки в этом случае было бы, если бы приложение, зарегистрировавшее GUID, было перемещено. В документации не описаны сценарии, при которых преднамеренная попытка перехватить GUID может завершиться неудачей. Злонамеренному игроку остается в качестве упражнения экстраполировать задокументированные сценарии ошибок.
4. @IInspectable, поэтому, когда я использовал этот идентификатор GUID с 0x66 в конце, это было интерпретировано как попытка перехватить этот идентификатор GUID моим приложением. Это то, что ты хочешь сказать?
5. Ну, а откуда у тебя этот GUID? Если вы справились с этим, скажем, guidgen.exe , тогда вы находитесь в лагере разработчиков, которым необходимо устранить проблему в результате несчастного случая, и документация применяется, как написано. Если вы получили GUID, проверив другой код и / или ресурсы, то вы находитесь в лагере разработчиков, которые пытаются бороться с системой. В этом случае вам придется перевести документацию в соответствии с ожиданиями злоумышленника. Основная аудитория документации — не злоумышленники.