Qt 4.8
qsystemtrayicon_wince.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qsystemtrayicon_p.h"
43 #ifndef QT_NO_SYSTEMTRAYICON
44 #define _WIN32_IE 0x0600 //required for NOTIFYICONDATA_V2_SIZE
45 
46 #include <qt_windows.h>
47 #include <shlwapi.h>
48 #include <QApplication>
49 
51 
52 static const UINT q_uNOTIFYICONID = 13; // IDs from 0 to 12 are reserved on WinCE.
53 #define MYWM_NOTIFYICON (WM_APP+101)
54 
56  DWORD cbSize;
57  HWND hWnd;
58  UINT uID;
59  GUID guidItem;
60 };
61 
63 {
64 public:
67  bool winEvent( MSG *m, long *result );
68  bool trayMessage(DWORD msg);
69  void setIconContents(NOTIFYICONDATA &data);
70  void createIcon();
71  QRect findTrayGeometry();
72  HICON hIcon;
73  QPoint globalPos;
74  QSystemTrayIcon *q;
75 private:
76  uint notifyIconSize;
77  int maxTipLength;
78  bool ignoreNextMouseRelease;
79 };
80 
82  : hIcon(0), q(object), ignoreNextMouseRelease(false)
83 
84 {
85  notifyIconSize = FIELD_OFFSET(NOTIFYICONDATA, szTip[64]); // NOTIFYICONDATAW_V1_SIZE;
86  maxTipLength = 64;
87 }
88 
90 {
91  if (hIcon)
92  DestroyIcon(hIcon);
93 }
94 
96 {
97  // Use lower right corner as fallback
98  QPoint brCorner = qApp->desktop()->screenGeometry().bottomRight();
99  QRect ret(brCorner.x() - 10, brCorner.y() - 10, 10, 10);
100  return ret;
101 }
102 
103 void QSystemTrayIconSys::setIconContents(NOTIFYICONDATA &tnd)
104 {
105  tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
106  tnd.uCallbackMessage = MYWM_NOTIFYICON;
107  tnd.hIcon = hIcon;
108  QString tip = q->toolTip();
109 
110  if (!tip.isNull()) {
111  tip = tip.left(maxTipLength - 1) + QChar();
112  memcpy(tnd.szTip, tip.utf16(), qMin(tip.length() + 1, maxTipLength) * sizeof(wchar_t));
113  }
114 }
115 
116 bool QSystemTrayIconSys::trayMessage(DWORD msg)
117 {
118  NOTIFYICONDATA tnd;
119  memset(&tnd, 0, notifyIconSize);
120  tnd.uID = q_uNOTIFYICONID;
121  tnd.cbSize = notifyIconSize;
122  tnd.hWnd = winId();
123 
124  Q_ASSERT(testAttribute(Qt::WA_WState_Created));
125 
126  if (msg != NIM_DELETE) {
127  setIconContents(tnd);
128  }
129 
130  return Shell_NotifyIcon(msg, &tnd);
131 }
132 
134 {
135  hIcon = 0;
136  QIcon icon = q->icon();
137  if (icon.isNull())
138  return;
139 
140  //const QSize preferredSize(GetSystemMetrics(SM_CXSMICON) * 2, GetSystemMetrics(SM_CYSMICON) * 2);
141  const QSize preferredSize(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
142  QPixmap pm = icon.pixmap(preferredSize);
143  if (pm.isNull())
144  return;
145 
146  hIcon = pm.toWinHICON();
147 }
148 
149 bool QSystemTrayIconSys::winEvent( MSG *m, long *result )
150 {
151  switch(m->message) {
152  case WM_CREATE:
153  SetWindowLong(winId(), GWL_USERDATA, (LONG)((CREATESTRUCTW*)m->lParam)->lpCreateParams);
154  break;
155 
156  case MYWM_NOTIFYICON:
157  {
158  QPoint gpos = QCursor::pos();
159 
160  switch (m->lParam) {
161  case WM_LBUTTONUP:
162  if (ignoreNextMouseRelease)
163  ignoreNextMouseRelease = false;
164  else
165  emit q->activated(QSystemTrayIcon::Trigger);
166  break;
167 
168  case WM_LBUTTONDBLCLK:
169  ignoreNextMouseRelease = true; // Since DBLCLICK Generates a second mouse
170  // release we must ignore it
171  emit q->activated(QSystemTrayIcon::DoubleClick);
172  break;
173 
174  case WM_RBUTTONUP:
175  if (q->contextMenu()) {
176  q->contextMenu()->popup(gpos);
177 
178  // We must ensure that the popup menu doesn't show up behind the task bar.
179  QRect desktopRect = qApp->desktop()->availableGeometry();
180  int maxY = desktopRect.y() + desktopRect.height() - q->contextMenu()->height();
181  if (gpos.y() > maxY) {
182  gpos.ry() = maxY;
183  q->contextMenu()->move(gpos);
184  }
185  }
186  emit q->activated(QSystemTrayIcon::Context);
187  break;
188 
189  case WM_MBUTTONUP:
190  emit q->activated(QSystemTrayIcon::MiddleClick);
191  break;
192 
193  default:
194  break;
195  }
196  break;
197  }
198  default:
199  return QWidget::winEvent(m, result);
200  }
201  return 0;
202 }
203 
205 {
207  if (!sys) {
208  sys = new QSystemTrayIconSys(q);
209  sys->createIcon();
210  sys->trayMessage(NIM_ADD);
211  }
212 }
213 
214 void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, int timeOut)
215 {
216  if (!sys)
217  return;
218 
219  uint uSecs = 0;
220  if ( timeOut < 0)
221  uSecs = 10000; //10 sec default
222  else uSecs = (int)timeOut;
223 
224  //message is limited to 255 chars + NULL
225  QString messageString;
226  if (message.isEmpty() && !title.isEmpty())
227  messageString = QLatin1Char(' '); //ensures that the message shows when only title is set
228  else
229  messageString = message.left(255) + QChar();
230 
231  //title is limited to 63 chars + NULL
232  QString titleString = title.left(63) + QChar();
233 
234  //show QBalloonTip
235  QRect trayRect = sys->findTrayGeometry();
236  QBalloonTip::showBalloon(type, title, message, sys->q, QPoint(trayRect.left(),
237  trayRect.center().y()), uSecs, false);
238 }
239 
241 {
242  return QRect();
243 }
244 
246 {
247  if (!sys)
248  return;
249 
250  sys->trayMessage(NIM_DELETE);
251  delete sys;
252  sys = 0;
253 }
254 
256 {
257  if (!sys)
258  return;
259 
260  HICON hIconToDestroy = sys->hIcon;
261 
262  sys->createIcon();
263  sys->trayMessage(NIM_MODIFY);
264 
265  if (hIconToDestroy)
266  DestroyIcon(hIconToDestroy);
267 }
268 
270 {
271 
272 }
273 
275 {
276  // Calling sys->trayMessage(NIM_MODIFY) on an existing icon is broken on Windows CE.
277  // So we need to call updateIcon_sys() which creates a new icon handle.
278  updateIcon_sys();
279 }
280 
282 {
283  return true;
284 }
285 
287 {
288  return true;
289 }
290 
292 
293 #endif
void showMessage_sys(const QString &msg, const QString &title, QSystemTrayIcon::MessageIcon icon, int secs)
int type
Definition: qmetatype.cpp:239
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
#define MYWM_NOTIFYICON
Definition: quuid.h:52
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
int left() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:240
int & ry()
Returns a reference to the y coordinate of this point.
Definition: qpoint.h:143
bool winEvent(MSG *m, long *result)
This special event handler can be reimplemented in a subclass to receive native Windows events which ...
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
static void showBalloon(QSystemTrayIcon::MessageIcon icon, const QString &title, const QString &msg, QSystemTrayIcon *trayIcon, const QPoint &pos, int timeout, bool showArrow=true)
#define Q_Q(Class)
Definition: qglobal.h:2483
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
#define qApp
static bool isSystemTrayAvailable_sys()
#define emit
Definition: qobjectdefs.h:76
bool isNull() const
Returns true if the icon is empty; otherwise returns false.
Definition: qicon.cpp:769
void setIconContents(NOTIFYICONDATA &data)
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
static const UINT q_uNOTIFYICONID
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition: qstring.h:505
QPoint center() const
Returns the center point of the rectangle.
Definition: qrect.h:300
struct tagMSG MSG
virtual bool winEvent(MSG *message, long *result)
This special event handler can be reimplemented in a subclass to receive native Windows events which ...
Definition: qwidget.cpp:9941
HICON toWinHICON() const
Returns the HICON handle.
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
int y() const
Returns the y coordinate of this point.
Definition: qpoint.h:131
The QPixmap class is an off-screen image representation that can be used as a paint device...
Definition: qpixmap.h:71
bool trayMessage(DWORD msg)
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.
Definition: qicon.cpp:693
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
bool isNull() const
Returns true if this is a null pixmap; otherwise returns false.
Definition: qpixmap.cpp:615
MessageIcon
This enum describes the icon that is shown when a balloon message is displayed.
QSystemTrayIconSys(QSystemTrayIcon *icon, QSystemTrayIconPrivate *d)
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
static QPoint pos()
Returns the position of the cursor (hot spot) in global screen coordinates.
Definition: qcursor_mac.mm:310
The QSystemTrayIcon class provides an icon for an application in the system tray. ...
const ushort * utf16() const
Returns the QString as a &#39;\0\&#39;-terminated array of unsigned shorts.
Definition: qstring.cpp:5290
The QIcon class provides scalable icons in different modes and states.
Definition: qicon.h:60