4#include <QtCore/qt_windows.h>
12#include <QtGui/qguiapplication.h>
13#include <QtGui/qpixmap.h>
14#include <QtCore/qdebug.h>
15#include <QtCore/qlist.h>
16#include <QtCore/qrect.h>
17#include <QtCore/qsettings.h>
18#include <qpa/qwindowsysteminterface.h>
32#define MYWM_NOTIFYICON (WM_APP+101)
48 memset(&tnd, 0,
sizeof(NOTIFYICONDATA));
49 tnd.cbSize =
sizeof(NOTIFYICONDATA);
50 tnd.uVersion = NOTIFYICON_VERSION_4;
55 tnd.uFlags |= NIF_MESSAGE | NIF_ICON | NIF_TIP;
63 tnd.uFlags |= NIF_STATE;
64 tnd.dwStateMask = NIS_HIDDEN;
65 tnd.dwState =
v ? 0 : NIS_HIDDEN;
82 for (
int i = 0,
size = entries->size();
i <
size; ++
i) {
83 if (entries->at(
i).hwnd == hwnd)
90 WPARAM wParam, LPARAM lParam)
102 msg.pt.x = GET_X_LPARAM(lParam);
103 msg.pt.y = GET_Y_LPARAM(lParam);
105 if (hwndTrayIconEntries()->
at(
index).trayIcon->winEvent(msg, &
result))
109 return DefWindowProc(hwnd,
message, wParam, lParam);
123 const wchar_t windowName[] = L
"QTrayIconMessageWindow";
124 return CreateWindowEx(0,
reinterpret_cast<const wchar_t *
>(
className.utf16()),
125 windowName, WS_OVERLAPPED,
126 CW_USEDEFAULT, CW_USEDEFAULT,
127 CW_USEDEFAULT, CW_USEDEFAULT,
129 static_cast<HINSTANCE
>(GetModuleHandle(
nullptr)),
nullptr);
145 qCDebug(lcQpaTrayIcon) << __FUNCTION__ <<
this;
151 qCDebug(lcQpaTrayIcon) << __FUNCTION__ <<
this;
153 if (!setIconVisible(m_visible))
159 qCDebug(lcQpaTrayIcon) << __FUNCTION__ <<
this;
166 qCDebug(lcQpaTrayIcon) << __FUNCTION__ <<
'(' <<
icon <<
')' <<
this;
168 const HICON hIconToDestroy = createIcon(
icon);
169 if (ensureInstalled())
170 sendTrayMessage(NIM_MODIFY);
172 DestroyIcon(hIconToDestroy);
177 qCDebug(lcQpaTrayIcon) << __FUNCTION__ <<
'(' << tooltip <<
')' <<
this;
178 if (m_toolTip == tooltip)
182 sendTrayMessage(NIM_MODIFY);
187 if (!isIconVisible())
190 NOTIFYICONIDENTIFIER nid;
191 memset(&nid, 0,
sizeof(nid));
192 nid.cbSize =
sizeof(nid);
199 qCDebug(lcQpaTrayIcon) << __FUNCTION__ <<
this <<
"returns" <<
result;
209 << iconType << msecsIn <<
')' <<
this;
226 if (m_hMessageIcon) {
227 DestroyIcon(m_hMessageIcon);
228 m_hMessageIcon =
nullptr;
231 tnd.dwInfoFlags = NIIF_INFO;
233 tnd.dwInfoFlags = NIIF_USER | NIIF_LARGE_ICON;
235 tnd.hBalloonIcon = m_hMessageIcon;
238 tnd.uTimeout = msecsIn <= 0 ? UINT(10000) : UINT(msecsIn);
239 tnd.uFlags = NIF_INFO | NIF_SHOWTIP;
241 Shell_NotifyIcon(NIM_MODIFY, &tnd);
254 qCDebug(lcQpaTrayIcon) << __FUNCTION__ <<
this <<
"returns" << m_menu.
data();
255 return m_menu.
data();
259bool QWindowsSystemTrayIcon::ensureInstalled()
263 if (m_hIcon ==
nullptr)
276 hwndTrayIconEntries()->append(
entry);
277 sendTrayMessage(NIM_ADD);
281void QWindowsSystemTrayIcon::ensureCleanup()
286 hwndTrayIconEntries()->removeAt(
index);
287 sendTrayMessage(NIM_DELETE);
288 DestroyWindow(m_hwnd);
291 if (m_hIcon !=
nullptr)
292 DestroyIcon(m_hIcon);
293 if (m_hMessageIcon !=
nullptr)
294 DestroyIcon(m_hMessageIcon);
296 m_hMessageIcon =
nullptr;
301bool QWindowsSystemTrayIcon::setIconVisible(
bool visible)
310 return Shell_NotifyIcon(NIM_MODIFY, &tnd) == TRUE;
313bool QWindowsSystemTrayIcon::isIconVisible()
const
315 NOTIFYICONIDENTIFIER nid;
316 memset(&nid, 0,
sizeof(nid));
317 nid.cbSize =
sizeof(nid);
321 const HRESULT hr = Shell_NotifyIconGetRect(&nid, &
rect);
323 if (FAILED(hr) || hr == S_FALSE)
326 HMONITOR monitor = MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTONEAREST);
328 info.cbSize =
sizeof(MONITORINFO);
329 GetMonitorInfo(monitor, &
info);
333 return rect.bottom <=
info.rcMonitor.bottom;
336bool QWindowsSystemTrayIcon::sendTrayMessage(DWORD msg)
342 tnd.uFlags = NIF_SHOWTIP;
343 if (msg != NIM_DELETE && !m_visible)
345 if (msg == NIM_ADD || msg == NIM_MODIFY)
347 if (!Shell_NotifyIcon(msg, &tnd))
349 return msg != NIM_ADD || Shell_NotifyIcon(NIM_SETVERSION, &tnd);
353HICON QWindowsSystemTrayIcon::createIcon(
const QIcon &
icon)
355 const HICON oldIcon = m_hIcon;
359 const QSize requestedSize =
QSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
373 const int trayMessage = LOWORD(
message.lParam);
374 switch (trayMessage) {
377 if (m_ignoreNextMouseRelease)
378 m_ignoreNextMouseRelease =
false;
382 case WM_LBUTTONDBLCLK:
383 m_ignoreNextMouseRelease =
true;
386 case WM_CONTEXTMENU: {
394 screen = screenManager.screens().value(0);
401 SetForegroundWindow(m_hwnd);
407 case NIN_BALLOONUSERCLICK:
419 case WM_INITMENUPOPUP:
423 QWindowSystemInterface::handleApplicationTermination<QWindowSystemInterface::SynchronousDelivery>();
432 const QIcon oldIcon = m_icon;
436 sendTrayMessage(NIM_ADD);
443#ifndef QT_NO_DEBUG_STREAM
447 d << static_cast<const void *>(
this) <<
", \"" << m_toolTip
448 <<
"\", hwnd=" << m_hwnd <<
", m_hIcon=" << m_hIcon <<
", menu="
457 d <<
"QWindowsSystemTrayIcon(";
The QIcon class provides scalable icons in different modes and states.
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
QSize actualSize(const QSize &size, Mode mode=Normal, State state=Off) const
Returns the actual size of the icon for the requested size, mode, and state.
QPixmap pixmap(const QSize &size, Mode mode=Normal, State state=Off) const
Returns a pixmap with the requested size, mode, and state, generating one if necessary.
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
\inmodule QtCore\reentrant
constexpr int x() const noexcept
Returns the x coordinate of this point.
constexpr int y() const noexcept
Returns the y coordinate of this point.
T * data() const noexcept
bool isNull() const noexcept
\inmodule QtCore\reentrant
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
void clear()
Clears the contents of the string and makes it null.
QString & append(QChar c)
Singleton container for all relevant information.
static QString classNamePrefix()
static DWORD readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue)
static QWindowsContext * instance()
Windows native system tray icon.
void cleanup() override
This method is called to cleanup the platform dependent implementation.
bool supportsMessages() const override
Returns true if the system tray supports messages on the platform.
bool winEvent(const MSG &message, long *result)
void formatDebug(QDebug &d) const
QPlatformMenu * createMenu() const override
This method allows platforms to use a different QPlatformMenu for system tray menus than what would n...
void updateToolTip(const QString &tooltip) override
This method is called when the tooltip text did change.
void init() override
This method is called to initialize the platform dependent implementation.
void updateIcon(const QIcon &icon) override
This method is called when the icon did change.
void showMessage(const QString &title, const QString &msg, const QIcon &icon, MessageIcon iconType, int msecs) override
Shows a balloon message for the entry with the given title, message msg and icon for the time specifi...
QRect geometry() const override
This method returns the geometry of the platform dependent system tray icon on the screen.
~QWindowsSystemTrayIcon() override
static bool useNativeMenus()
Combined button and popup list for selecting options.
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
GLsizei const GLfloat * v
[13]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLuint GLsizei const GLchar * message
HICON qt_pixmapToWinHICON(const QPixmap &p)
static void setIconVisibility(NOTIFYICONDATA &tnd, bool v)
Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &)
static HWND createTrayIconMessageWindow()
static const UINT q_uNOTIFYICONID
static uint MYWM_TASKBARCREATED
QDebug operator<<(QDebug d, const QWindowsSystemTrayIcon *t)
static void initNotifyIconData(NOTIFYICONDATA &tnd)
static void setIconContents(NOTIFYICONDATA &tnd, const QString &tip, HICON hIcon)
LRESULT QT_WIN_CALLBACK qWindowsTrayIconWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
static void qStringToLimitedWCharArray(QString in, wchar_t *target, int maxLength)
QList< QWindowsHwndSystemTrayIconEntry > HwndTrayIconEntries
static int indexOfHwnd(HWND hwnd)
const char className[16]
[1]
QWindowsSystemTrayIcon * trayIcon