Я использую API NotifyIcon для показа сообщений (Baloon или уведомления в Win 10). Дело в том, что сообщение упорно не показывается на экран. Возвращаемое значение всегда истина, последнее сообщение от ошибке - 0 (однако я знаю, что функция Shell_NotifyIcon вызывает SetLastError(0), поэтому я не могу получить сообщение об ошибке). Я создал минимальный пример, который демонстрирует нужный мне функционал:
Также, я добавил консоль, куда пишутся возвращаемые значения (для удобства). Вот код примера:
#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <iostream>
using namespace std;
#define MENU_TEST 10
#define RBUTTON_MENU WM_USER + 3000
void showMessage(HWND hwnd, const wchar_t* mes, int flag);
LRESULT CALLBACK wndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
SetConsoleOutputCP(1251);
SetConsoleCP(1251);
if (!AllocConsole())
return -1;
wcout.imbue(locale("rus_rus.866"));
wcin.imbue(locale("rus_rus.866"));
_wfreopen(L"CONOUT$", L"wt", stdout);
_wfreopen(L"CONIN$", L"rt", stdin);
HWND hwnd;
MSG msg;
WNDCLASSEX wc;
wc.cbSize = sizeof(wc);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = wndProc;
wc.lpszMenuName = NULL;
wc.lpszClassName = L"test__class";
wc.cbWndExtra = NULL;
wc.cbClsExtra = NULL;
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wc.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.hInstance = hInstance;
if (!RegisterClassEx(&wc))
return -1;
hwnd = CreateWindow(L"test__class", L"Test Notify", WS_OVERLAPPEDWINDOW | WS_VSCROLL, CW_USEDEFAULT, NULL, CW_USEDEFAULT, NULL, (HWND)NULL, NULL, HINSTANCE(hInstance), NULL);
if (!hwnd)
return -1;
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, NULL, NULL))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
void showMessage(HWND hwnd, const wchar_t* mes, int flag)
{
NOTIFYICONDATA nid;
static const GUID name = { 0xaaaad36f, 0xd48a, 0x4306, { 0x84, 0x45, 0x73, 0x84, 0xc9, 0xf1, 0x3f, 0xa0 } };
memset(&nid, 0, sizeof(NOTIFYICONDATA));
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hwnd;
nid.guidItem = name;
nid.uID = 7;
nid.uFlags = NIF_INFO | NIF_STATE | NIF_ICON | NIF_TIP | NIF_MESSAGE;
nid.uCallbackMessage = RBUTTON_MENU;
wcscpy_s(nid.szInfo, mes);
nid.dwInfoFlags = NIIF_NOSOUND;
wcscpy_s(nid.szTip, L"Test");
wcout << L"Message: " << mes << endl;
wcout << L"Result function NotifyIcon: " << Shell_NotifyIcon(flag, &nid) << endl;
wcout << L"Last error: " << GetLastError() << endl;
}
LRESULT CALLBACK wndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HMENU hMenu;
switch (uMsg)
{
case WM_CREATE:
{
hMenu = CreatePopupMenu();
AppendMenuA(hMenu, MF_STRING, MENU_TEST, "Click");
showMessage(hwnd, L"App started", NIM_ADD);
break;
}
case RBUTTON_MENU:
{
switch (lParam)
{
case WM_RBUTTONUP:
{
SetForegroundWindow(hwnd);
POINT pt;
GetCursorPos(&pt);
TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, 0, hwnd, NULL);
break;
}
default:
break;
}
}
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case MENU_TEST:
{
bool visible = IsWindowVisible(hwnd);
ShowWindow(hwnd, !visible ? SW_SHOW :SW_HIDE);
showMessage(hwnd, !visible ? L"App restored" : L"App minimazed", NIM_MODIFY);
break;
}
default: break;
}
break;
}
case WM_DESTROY:
showMessage(hwnd, L"App closed", NIM_DELETE);
DestroyMenu(hMenu);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
Почему так происходит? Сообщение упорно не появляется..спасибо.
В таком варианте указанный GUID будет проигнорирован, так как отсутствует флаг NIF_GUID
, видимо раз окно еще только в процессе создания комбинация hwnd + uID не прокатывает.
nid.uFlags = NIF_INFO | NIF_STATE | NIF_ICON | NIF_TIP | NIF_MESSAGE | NIF_GUID;
Далее, в wndProc
имеется неопределенное поведение, так как функция может заканчиваться не возвращая никакого значения.
Проверка результата вызова функции тоже неправильная, GetLastError
необходимо вызывать до вызова любых других функций winapi:
if(FALSE == Shell_NotifyIcon(flag, &nid))
{
auto const last_error{GetLastError()};
wcout << L"Shell_NotifyIcon failed with error #" << last_error << endl;
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Я использую memcpy для того чтобы скопировать в bytebuffer информацию из массиваВот простой код:
В функции инициализации функций для луа в моем классе, я бы хотел реализовать регистрацию функции из самого класса и что бы она выполнялась...
Всем приветКак реализовать в Jquery, чтобы при каждом клике аудиофайл проигрывался всего один раз