|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtGui module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #ifndef QT_NO_WIZARD |
|
43 #ifndef QT_NO_STYLE_WINDOWSVISTA |
|
44 |
|
45 #include "qwizard_win_p.h" |
|
46 #include "qlibrary.h" |
|
47 #include "qwizard.h" |
|
48 #include "qpaintengine.h" |
|
49 #include "qapplication.h" |
|
50 #include <QtGui/QMouseEvent> |
|
51 #include <QtGui/QDesktopWidget> |
|
52 |
|
53 // Note, these tests are duplicates in qwindowsxpstyle_p.h. |
|
54 #ifdef Q_CC_GNU |
|
55 # include <w32api.h> |
|
56 # if (__W32API_MAJOR_VERSION >= 3 || (__W32API_MAJOR_VERSION == 2 && __W32API_MINOR_VERSION >= 5)) |
|
57 # ifdef _WIN32_WINNT |
|
58 # undef _WIN32_WINNT |
|
59 # endif |
|
60 # define _WIN32_WINNT 0x0501 |
|
61 # include <commctrl.h> |
|
62 # endif |
|
63 #endif |
|
64 |
|
65 #include <uxtheme.h> |
|
66 |
|
67 QT_BEGIN_NAMESPACE |
|
68 |
|
69 //DWM related |
|
70 typedef struct { //MARGINS |
|
71 int cxLeftWidth; // width of left border that retains its size |
|
72 int cxRightWidth; // width of right border that retains its size |
|
73 int cyTopHeight; // height of top border that retains its size |
|
74 int cyBottomHeight; // height of bottom border that retains its size |
|
75 } WIZ_MARGINS; |
|
76 typedef struct { //DTTOPTS |
|
77 DWORD dwSize; |
|
78 DWORD dwFlags; |
|
79 COLORREF crText; |
|
80 COLORREF crBorder; |
|
81 COLORREF crShadow; |
|
82 int eTextShadowType; |
|
83 POINT ptShadowOffset; |
|
84 int iBorderSize; |
|
85 int iFontPropId; |
|
86 int iColorPropId; |
|
87 int iStateId; |
|
88 BOOL fApplyOverlay; |
|
89 int iGlowSize; |
|
90 } WIZ_DTTOPTS; |
|
91 |
|
92 typedef struct { |
|
93 DWORD dwFlags; |
|
94 DWORD dwMask; |
|
95 } WIZ_WTA_OPTIONS; |
|
96 |
|
97 #define WIZ_WM_THEMECHANGED 0x031A |
|
98 #define WIZ_WM_DWMCOMPOSITIONCHANGED 0x031E |
|
99 |
|
100 enum WIZ_WINDOWTHEMEATTRIBUTETYPE { |
|
101 WIZ_WTA_NONCLIENT = 1 |
|
102 }; |
|
103 |
|
104 #define WIZ_WTNCA_NODRAWCAPTION 0x00000001 |
|
105 #define WIZ_WTNCA_NODRAWICON 0x00000002 |
|
106 |
|
107 #define WIZ_DT_CENTER 0x00000001 //DT_CENTER |
|
108 #define WIZ_DT_VCENTER 0x00000004 |
|
109 #define WIZ_DT_SINGLELINE 0x00000020 |
|
110 #define WIZ_DT_NOPREFIX 0x00000800 |
|
111 |
|
112 enum WIZ_NAVIGATIONPARTS { //NAVIGATIONPARTS |
|
113 WIZ_NAV_BACKBUTTON = 1, |
|
114 WIZ_NAV_FORWARDBUTTON = 2, |
|
115 WIZ_NAV_MENUBUTTON = 3, |
|
116 }; |
|
117 |
|
118 enum WIZ_NAV_BACKBUTTONSTATES { //NAV_BACKBUTTONSTATES |
|
119 WIZ_NAV_BB_NORMAL = 1, |
|
120 WIZ_NAV_BB_HOT = 2, |
|
121 WIZ_NAV_BB_PRESSED = 3, |
|
122 WIZ_NAV_BB_DISABLED = 4, |
|
123 }; |
|
124 |
|
125 #define WIZ_TMT_CAPTIONFONT (801) //TMT_CAPTIONFONT |
|
126 #define WIZ_DTT_COMPOSITED (1UL << 13) //DTT_COMPOSITED |
|
127 #define WIZ_DTT_GLOWSIZE (1UL << 11) //DTT_GLOWSIZE |
|
128 |
|
129 #define WIZ_WM_NCMOUSELEAVE 674 //WM_NCMOUSELEAVE |
|
130 |
|
131 #define WIZ_WP_CAPTION 1 //WP_CAPTION |
|
132 #define WIZ_CS_ACTIVE 1 //CS_ACTIVE |
|
133 #define WIZ_TMT_FILLCOLORHINT 3821 //TMT_FILLCOLORHINT |
|
134 #define WIZ_TMT_BORDERCOLORHINT 3822 //TMT_BORDERCOLORHINT |
|
135 |
|
136 typedef BOOL (WINAPI *PtrDwmDefWindowProc)(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *plResult); |
|
137 typedef HRESULT (WINAPI *PtrDwmIsCompositionEnabled)(BOOL* pfEnabled); |
|
138 typedef HRESULT (WINAPI *PtrDwmExtendFrameIntoClientArea)(HWND hWnd, const WIZ_MARGINS* pMarInset); |
|
139 typedef HRESULT (WINAPI *PtrSetWindowThemeAttribute)(HWND hwnd, enum WIZ_WINDOWTHEMEATTRIBUTETYPE eAttribute, PVOID pvAttribute, DWORD cbAttribute); |
|
140 |
|
141 static PtrDwmDefWindowProc pDwmDefWindowProc = 0; |
|
142 static PtrDwmIsCompositionEnabled pDwmIsCompositionEnabled = 0; |
|
143 static PtrDwmExtendFrameIntoClientArea pDwmExtendFrameIntoClientArea = 0; |
|
144 static PtrSetWindowThemeAttribute pSetWindowThemeAttribute = 0; |
|
145 |
|
146 //Theme related |
|
147 typedef bool (WINAPI *PtrIsAppThemed)(); |
|
148 typedef bool (WINAPI *PtrIsThemeActive)(); |
|
149 typedef HANDLE (WINAPI *PtrOpenThemeData)(HWND hwnd, LPCWSTR pszClassList); |
|
150 typedef HRESULT (WINAPI *PtrCloseThemeData)(HANDLE hTheme); |
|
151 typedef HRESULT (WINAPI *PtrGetThemeSysFont)(HANDLE hTheme, int iFontId, LOGFONTW *plf); |
|
152 typedef HRESULT (WINAPI *PtrDrawThemeTextEx)(HANDLE hTheme, HDC hdc, int iPartId, int iStateId, LPCWSTR pszText, int cchText, DWORD dwTextFlags, LPRECT pRect, const WIZ_DTTOPTS *pOptions); |
|
153 typedef HRESULT (WINAPI *PtrDrawThemeBackground)(HANDLE hTheme, HDC hdc, int iPartId, int iStateId, const RECT *pRect, OPTIONAL const RECT *pClipRect); |
|
154 typedef HRESULT (WINAPI *PtrGetThemePartSize)(HANDLE hTheme, HDC hdc, int iPartId, int iStateId, OPTIONAL RECT *prc, enum THEMESIZE eSize, OUT SIZE *psz); |
|
155 typedef HRESULT (WINAPI *PtrGetThemeColor)(HANDLE hTheme, int iPartId, int iStateId, int iPropId, OUT COLORREF *pColor); |
|
156 |
|
157 static PtrIsAppThemed pIsAppThemed = 0; |
|
158 static PtrIsThemeActive pIsThemeActive = 0; |
|
159 static PtrOpenThemeData pOpenThemeData = 0; |
|
160 static PtrCloseThemeData pCloseThemeData = 0; |
|
161 static PtrGetThemeSysFont pGetThemeSysFont = 0; |
|
162 static PtrDrawThemeTextEx pDrawThemeTextEx = 0; |
|
163 static PtrDrawThemeBackground pDrawThemeBackground = 0; |
|
164 static PtrGetThemePartSize pGetThemePartSize = 0; |
|
165 static PtrGetThemeColor pGetThemeColor = 0; |
|
166 |
|
167 bool QVistaHelper::is_vista = false; |
|
168 QVistaHelper::VistaState QVistaHelper::cachedVistaState = QVistaHelper::Dirty; |
|
169 |
|
170 /****************************************************************************** |
|
171 ** QVistaBackButton |
|
172 */ |
|
173 |
|
174 QVistaBackButton::QVistaBackButton(QWidget *widget) |
|
175 : QAbstractButton(widget) |
|
176 { |
|
177 setFocusPolicy(Qt::NoFocus); |
|
178 } |
|
179 |
|
180 QSize QVistaBackButton::sizeHint() const |
|
181 { |
|
182 ensurePolished(); |
|
183 int width = 32, height = 32; |
|
184 /* |
|
185 HANDLE theme = pOpenThemeData(0, L"Navigation"); |
|
186 SIZE size; |
|
187 if (pGetThemePartSize(theme, 0, WIZ_NAV_BACKBUTTON, WIZ_NAV_BB_NORMAL, 0, TS_TRUE, &size) == S_OK) { |
|
188 width = size.cx; |
|
189 height = size.cy; |
|
190 } |
|
191 */ |
|
192 return QSize(width, height); |
|
193 } |
|
194 |
|
195 void QVistaBackButton::enterEvent(QEvent *event) |
|
196 { |
|
197 if (isEnabled()) |
|
198 update(); |
|
199 QAbstractButton::enterEvent(event); |
|
200 } |
|
201 |
|
202 void QVistaBackButton::leaveEvent(QEvent *event) |
|
203 { |
|
204 if (isEnabled()) |
|
205 update(); |
|
206 QAbstractButton::leaveEvent(event); |
|
207 } |
|
208 |
|
209 void QVistaBackButton::paintEvent(QPaintEvent *) |
|
210 { |
|
211 QPainter p(this); |
|
212 QRect r = rect(); |
|
213 HANDLE theme = pOpenThemeData(0, L"Navigation"); |
|
214 //RECT rect; |
|
215 RECT clipRect; |
|
216 int xoffset = QWidget::mapToParent(r.topLeft()).x(); |
|
217 int yoffset = QWidget::mapToParent(r.topLeft()).y(); |
|
218 |
|
219 clipRect.top = r.top() + yoffset; |
|
220 clipRect.bottom = r.bottom() + yoffset; |
|
221 clipRect.left = r.left() + xoffset; |
|
222 clipRect.right = r.right() + xoffset; |
|
223 |
|
224 int state = WIZ_NAV_BB_NORMAL; |
|
225 if (!isEnabled()) |
|
226 state = WIZ_NAV_BB_DISABLED; |
|
227 else if (isDown()) |
|
228 state = WIZ_NAV_BB_PRESSED; |
|
229 else if (underMouse()) |
|
230 state = WIZ_NAV_BB_HOT; |
|
231 |
|
232 pDrawThemeBackground(theme, p.paintEngine()->getDC(), WIZ_NAV_BACKBUTTON, state, &clipRect, &clipRect); |
|
233 } |
|
234 |
|
235 /****************************************************************************** |
|
236 ** QVistaHelper |
|
237 */ |
|
238 |
|
239 QVistaHelper::QVistaHelper(QWizard *wizard) |
|
240 : pressed(false) |
|
241 , wizard(wizard) |
|
242 , backButton_(0) |
|
243 { |
|
244 is_vista = resolveSymbols(); |
|
245 if (is_vista) |
|
246 backButton_ = new QVistaBackButton(wizard); |
|
247 } |
|
248 |
|
249 QVistaHelper::~QVistaHelper() |
|
250 { |
|
251 } |
|
252 |
|
253 bool QVistaHelper::isCompositionEnabled() |
|
254 { |
|
255 bool value = is_vista; |
|
256 if (is_vista) { |
|
257 HRESULT hr; |
|
258 BOOL bEnabled; |
|
259 |
|
260 hr = pDwmIsCompositionEnabled(&bEnabled); |
|
261 value = (SUCCEEDED(hr) && bEnabled); |
|
262 } |
|
263 return value; |
|
264 } |
|
265 |
|
266 bool QVistaHelper::isThemeActive() |
|
267 { |
|
268 return is_vista && pIsThemeActive(); |
|
269 } |
|
270 |
|
271 QVistaHelper::VistaState QVistaHelper::vistaState() |
|
272 { |
|
273 if (cachedVistaState == Dirty) |
|
274 cachedVistaState = |
|
275 isCompositionEnabled() ? VistaAero : isThemeActive() ? VistaBasic : Classic; |
|
276 return cachedVistaState; |
|
277 } |
|
278 |
|
279 QColor QVistaHelper::basicWindowFrameColor() |
|
280 { |
|
281 DWORD rgb; |
|
282 HANDLE hTheme = pOpenThemeData(QApplication::desktop()->winId(), L"WINDOW"); |
|
283 pGetThemeColor( |
|
284 hTheme, WIZ_WP_CAPTION, WIZ_CS_ACTIVE, |
|
285 wizard->isActiveWindow() ? WIZ_TMT_FILLCOLORHINT : WIZ_TMT_BORDERCOLORHINT, |
|
286 &rgb); |
|
287 BYTE r = GetRValue(rgb); |
|
288 BYTE g = GetGValue(rgb); |
|
289 BYTE b = GetBValue(rgb); |
|
290 return QColor(r, g, b); |
|
291 } |
|
292 |
|
293 bool QVistaHelper::setDWMTitleBar(TitleBarChangeType type) |
|
294 { |
|
295 bool value = false; |
|
296 if (vistaState() == VistaAero) { |
|
297 WIZ_MARGINS mar = {0}; |
|
298 if (type == NormalTitleBar) |
|
299 mar.cyTopHeight = 0; |
|
300 else |
|
301 mar.cyTopHeight = titleBarSize() + topOffset(); |
|
302 HRESULT hr = pDwmExtendFrameIntoClientArea(wizard->winId(), &mar); |
|
303 value = SUCCEEDED(hr); |
|
304 } |
|
305 return value; |
|
306 } |
|
307 |
|
308 void QVistaHelper::drawTitleBar(QPainter *painter) |
|
309 { |
|
310 if (vistaState() == VistaAero) |
|
311 drawBlackRect( |
|
312 QRect(0, 0, wizard->width(), titleBarSize() + topOffset()), |
|
313 painter->paintEngine()->getDC()); |
|
314 |
|
315 Q_ASSERT(backButton_); |
|
316 const int btnTop = backButton_->mapToParent(QPoint()).y(); |
|
317 const int btnHeight = backButton_->size().height(); |
|
318 const int verticalCenter = (btnTop + btnHeight / 2); |
|
319 |
|
320 wizard->windowIcon().paint( |
|
321 painter, QRect(leftMargin(), verticalCenter - iconSize() / 2, iconSize(), iconSize())); |
|
322 |
|
323 const QString text = wizard->window()->windowTitle(); |
|
324 const QFont font = QApplication::font("QWorkspaceTitleBar"); |
|
325 const QFontMetrics fontMetrics(font); |
|
326 const QRect brect = fontMetrics.boundingRect(text); |
|
327 int textHeight = brect.height(); |
|
328 int textWidth = brect.width(); |
|
329 if (vistaState() == VistaAero) { |
|
330 textHeight += 2 * glowSize(); |
|
331 textWidth += 2 * glowSize(); |
|
332 } |
|
333 drawTitleText( |
|
334 painter, text, |
|
335 QRect(titleOffset(), verticalCenter - textHeight / 2, textWidth, textHeight), |
|
336 painter->paintEngine()->getDC()); |
|
337 } |
|
338 |
|
339 void QVistaHelper::setTitleBarIconAndCaptionVisible(bool visible) |
|
340 { |
|
341 if (is_vista) { |
|
342 WIZ_WTA_OPTIONS opt; |
|
343 opt.dwFlags = WIZ_WTNCA_NODRAWICON | WIZ_WTNCA_NODRAWCAPTION; |
|
344 if (visible) |
|
345 opt.dwMask = 0; |
|
346 else |
|
347 opt.dwMask = WIZ_WTNCA_NODRAWICON | WIZ_WTNCA_NODRAWCAPTION; |
|
348 pSetWindowThemeAttribute(wizard->winId(), WIZ_WTA_NONCLIENT, &opt, sizeof(WIZ_WTA_OPTIONS)); |
|
349 } |
|
350 } |
|
351 |
|
352 bool QVistaHelper::winEvent(MSG* msg, long* result) |
|
353 { |
|
354 bool retval = true; |
|
355 |
|
356 switch (msg->message) { |
|
357 case WM_NCHITTEST: { |
|
358 LRESULT lResult; |
|
359 pDwmDefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam, &lResult); |
|
360 if (lResult == HTCLOSE || lResult == HTMAXBUTTON || lResult == HTMINBUTTON || lResult == HTHELP) |
|
361 *result = lResult; |
|
362 else |
|
363 *result = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam); |
|
364 break; |
|
365 } |
|
366 case WM_NCMOUSEMOVE: |
|
367 case WM_NCLBUTTONDOWN: |
|
368 case WM_NCLBUTTONUP: |
|
369 case WIZ_WM_NCMOUSELEAVE: { |
|
370 LRESULT lResult; |
|
371 pDwmDefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam, &lResult); |
|
372 *result = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam); |
|
373 break; |
|
374 } |
|
375 case WM_NCCALCSIZE: { |
|
376 NCCALCSIZE_PARAMS* lpncsp = (NCCALCSIZE_PARAMS*)msg->lParam; |
|
377 *result = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam); |
|
378 lpncsp->rgrc[0].top -= (vistaState() == VistaAero ? titleBarSize() : 0); |
|
379 break; |
|
380 } |
|
381 default: |
|
382 retval = false; |
|
383 } |
|
384 |
|
385 return retval; |
|
386 } |
|
387 |
|
388 void QVistaHelper::setMouseCursor(QPoint pos) |
|
389 { |
|
390 if (rtTop.contains(pos)) |
|
391 wizard->setCursor(Qt::SizeVerCursor); |
|
392 else |
|
393 wizard->setCursor(Qt::ArrowCursor); |
|
394 } |
|
395 |
|
396 void QVistaHelper::mouseEvent(QEvent *event) |
|
397 { |
|
398 switch (event->type()) { |
|
399 case QEvent::MouseMove: |
|
400 mouseMoveEvent(static_cast<QMouseEvent *>(event)); |
|
401 break; |
|
402 case QEvent::MouseButtonPress: |
|
403 mousePressEvent(static_cast<QMouseEvent *>(event)); |
|
404 break; |
|
405 case QEvent::MouseButtonRelease: |
|
406 mouseReleaseEvent(static_cast<QMouseEvent *>(event)); |
|
407 break; |
|
408 default: |
|
409 break; |
|
410 } |
|
411 } |
|
412 |
|
413 // The following hack ensures that the titlebar is updated correctly |
|
414 // when the wizard style changes to and from AeroStyle. Specifically, |
|
415 // this function causes a Windows message of type WM_NCCALCSIZE to |
|
416 // be triggered. |
|
417 void QVistaHelper::setWindowPosHack() |
|
418 { |
|
419 const int x = wizard->geometry().x(); // ignored by SWP_NOMOVE |
|
420 const int y = wizard->geometry().y(); // ignored by SWP_NOMOVE |
|
421 const int w = wizard->width(); |
|
422 const int h = wizard->height(); |
|
423 SetWindowPos(wizard->winId(), 0, x, y, w, h, SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED); |
|
424 } |
|
425 |
|
426 // The following hack allows any QWidget subclass to access |
|
427 // QWidgetPrivate::topData() without being declared as a |
|
428 // friend by QWidget. |
|
429 class QHackWidget : public QWidget |
|
430 { |
|
431 public: |
|
432 Q_DECLARE_PRIVATE(QWidget) |
|
433 QTLWExtra* topData() { return d_func()->topData(); } |
|
434 }; |
|
435 |
|
436 void QVistaHelper::collapseTopFrameStrut() |
|
437 { |
|
438 QTLWExtra *top = ((QHackWidget *)wizard)->d_func()->topData(); |
|
439 int x1, y1, x2, y2; |
|
440 top->frameStrut.getCoords(&x1, &y1, &x2, &y2); |
|
441 top->frameStrut.setCoords(x1, 0, x2, y2); |
|
442 } |
|
443 |
|
444 bool QVistaHelper::handleWinEvent(MSG *message, long *result) |
|
445 { |
|
446 if (message->message == WIZ_WM_THEMECHANGED || message->message == WIZ_WM_DWMCOMPOSITIONCHANGED) |
|
447 cachedVistaState = Dirty; |
|
448 |
|
449 bool status = false; |
|
450 if (wizard->wizardStyle() == QWizard::AeroStyle && vistaState() == VistaAero) { |
|
451 status = winEvent(message, result); |
|
452 if (message->message == WM_NCCALCSIZE) { |
|
453 if (status) |
|
454 collapseTopFrameStrut(); |
|
455 } else if (message->message == WM_NCPAINT) { |
|
456 wizard->update(); |
|
457 } |
|
458 } |
|
459 return status; |
|
460 } |
|
461 |
|
462 void QVistaHelper::resizeEvent(QResizeEvent * event) |
|
463 { |
|
464 Q_UNUSED(event); |
|
465 rtTop = QRect (0, 0, wizard->width(), frameSize()); |
|
466 int height = captionSize() + topOffset(); |
|
467 if (vistaState() == VistaBasic) |
|
468 height -= titleBarSize(); |
|
469 rtTitle = QRect (0, frameSize(), wizard->width(), height); |
|
470 } |
|
471 |
|
472 void QVistaHelper::paintEvent(QPaintEvent *event) |
|
473 { |
|
474 Q_UNUSED(event); |
|
475 QPainter painter(wizard); |
|
476 drawTitleBar(&painter); |
|
477 } |
|
478 |
|
479 void QVistaHelper::mouseMoveEvent(QMouseEvent *event) |
|
480 { |
|
481 if (wizard->windowState() & Qt::WindowMaximized) { |
|
482 event->ignore(); |
|
483 return; |
|
484 } |
|
485 |
|
486 QRect rect = wizard->geometry(); |
|
487 if (pressed) { |
|
488 switch (change) { |
|
489 case resizeTop: |
|
490 { |
|
491 const int dy = event->pos().y() - pressedPos.y(); |
|
492 if ((dy > 0 && rect.height() > wizard->minimumHeight()) |
|
493 || (dy < 0 && rect.height() < wizard->maximumHeight())) |
|
494 rect.setTop(rect.top() + dy); |
|
495 } |
|
496 break; |
|
497 case movePosition: { |
|
498 QPoint newPos = event->pos() - pressedPos; |
|
499 rect.moveLeft(rect.left() + newPos.x()); |
|
500 rect.moveTop(rect.top() + newPos.y()); |
|
501 break; } |
|
502 default: |
|
503 break; |
|
504 } |
|
505 wizard->setGeometry(rect); |
|
506 |
|
507 } else if (vistaState() == VistaAero) { |
|
508 setMouseCursor(event->pos()); |
|
509 } |
|
510 event->ignore(); |
|
511 } |
|
512 |
|
513 void QVistaHelper::mousePressEvent(QMouseEvent *event) |
|
514 { |
|
515 change = noChange; |
|
516 |
|
517 if (wizard->windowState() & Qt::WindowMaximized) { |
|
518 event->ignore(); |
|
519 return; |
|
520 } |
|
521 |
|
522 if (rtTitle.contains(event->pos())) { |
|
523 change = movePosition; |
|
524 } else if (rtTop.contains(event->pos())) |
|
525 change = (vistaState() == VistaAero) ? resizeTop : movePosition; |
|
526 |
|
527 if (change != noChange) { |
|
528 if (vistaState() == VistaAero) |
|
529 setMouseCursor(event->pos()); |
|
530 pressed = true; |
|
531 pressedPos = event->pos(); |
|
532 } else { |
|
533 event->ignore(); |
|
534 } |
|
535 } |
|
536 |
|
537 void QVistaHelper::mouseReleaseEvent(QMouseEvent *event) |
|
538 { |
|
539 change = noChange; |
|
540 if (pressed) { |
|
541 pressed = false; |
|
542 wizard->releaseMouse(); |
|
543 if (vistaState() == VistaAero) |
|
544 setMouseCursor(event->pos()); |
|
545 } |
|
546 event->ignore(); |
|
547 } |
|
548 |
|
549 bool QVistaHelper::eventFilter(QObject *obj, QEvent *event) |
|
550 { |
|
551 if (obj != wizard) |
|
552 return QObject::eventFilter(obj, event); |
|
553 |
|
554 if (event->type() == QEvent::MouseMove) { |
|
555 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); |
|
556 long result; |
|
557 MSG msg; |
|
558 msg.message = WM_NCHITTEST; |
|
559 msg.wParam = 0; |
|
560 msg.lParam = MAKELPARAM(mouseEvent->globalX(), mouseEvent->globalY()); |
|
561 msg.hwnd = wizard->winId(); |
|
562 winEvent(&msg, &result); |
|
563 msg.wParam = result; |
|
564 msg.message = WM_NCMOUSEMOVE; |
|
565 winEvent(&msg, &result); |
|
566 } else if (event->type() == QEvent::MouseButtonPress) { |
|
567 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); |
|
568 long result; |
|
569 MSG msg; |
|
570 msg.message = WM_NCHITTEST; |
|
571 msg.wParam = 0; |
|
572 msg.lParam = MAKELPARAM(mouseEvent->globalX(), mouseEvent->globalY()); |
|
573 msg.hwnd = wizard->winId(); |
|
574 winEvent(&msg, &result); |
|
575 msg.wParam = result; |
|
576 msg.message = WM_NCLBUTTONDOWN; |
|
577 winEvent(&msg, &result); |
|
578 } else if (event->type() == QEvent::MouseButtonRelease) { |
|
579 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); |
|
580 long result; |
|
581 MSG msg; |
|
582 msg.message = WM_NCHITTEST; |
|
583 msg.wParam = 0; |
|
584 msg.lParam = MAKELPARAM(mouseEvent->globalX(), mouseEvent->globalY()); |
|
585 msg.hwnd = wizard->winId(); |
|
586 winEvent(&msg, &result); |
|
587 msg.wParam = result; |
|
588 msg.message = WM_NCLBUTTONUP; |
|
589 winEvent(&msg, &result); |
|
590 } |
|
591 |
|
592 return false; |
|
593 } |
|
594 |
|
595 HFONT QVistaHelper::getCaptionFont(HANDLE hTheme) |
|
596 { |
|
597 LOGFONT lf = {0}; |
|
598 |
|
599 if (!hTheme) |
|
600 pGetThemeSysFont(hTheme, WIZ_TMT_CAPTIONFONT, &lf); |
|
601 else |
|
602 { |
|
603 NONCLIENTMETRICS ncm = {sizeof(NONCLIENTMETRICS)}; |
|
604 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, false); |
|
605 lf = ncm.lfMessageFont; |
|
606 } |
|
607 return CreateFontIndirect(&lf); |
|
608 } |
|
609 |
|
610 bool QVistaHelper::drawTitleText(QPainter *painter, const QString &text, const QRect &rect, HDC hdc) |
|
611 { |
|
612 bool value = false; |
|
613 if (vistaState() == VistaAero) { |
|
614 HANDLE hTheme = pOpenThemeData(QApplication::desktop()->winId(), L"WINDOW"); |
|
615 if (!hTheme) return false; |
|
616 // Set up a memory DC and bitmap that we'll draw into |
|
617 HDC dcMem; |
|
618 HBITMAP bmp; |
|
619 BITMAPINFO dib = {{0}}; |
|
620 dcMem = CreateCompatibleDC(hdc); |
|
621 |
|
622 dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); |
|
623 dib.bmiHeader.biWidth = rect.width(); |
|
624 dib.bmiHeader.biHeight = -rect.height(); |
|
625 dib.bmiHeader.biPlanes = 1; |
|
626 dib.bmiHeader.biBitCount = 32; |
|
627 dib.bmiHeader.biCompression = BI_RGB; |
|
628 |
|
629 bmp = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0); |
|
630 |
|
631 // Set up the DC |
|
632 HFONT hCaptionFont = getCaptionFont(hTheme); |
|
633 HBITMAP hOldBmp = (HBITMAP)SelectObject(dcMem, (HGDIOBJ) bmp); |
|
634 HFONT hOldFont = (HFONT)SelectObject(dcMem, (HGDIOBJ) hCaptionFont); |
|
635 |
|
636 // Draw the text! |
|
637 WIZ_DTTOPTS dto = { sizeof(WIZ_DTTOPTS) }; |
|
638 const UINT uFormat = WIZ_DT_SINGLELINE|WIZ_DT_CENTER|WIZ_DT_VCENTER|WIZ_DT_NOPREFIX; |
|
639 RECT rctext ={0,0, rect.width(), rect.height()}; |
|
640 |
|
641 dto.dwFlags = WIZ_DTT_COMPOSITED|WIZ_DTT_GLOWSIZE; |
|
642 dto.iGlowSize = glowSize(); |
|
643 |
|
644 pDrawThemeTextEx(hTheme, dcMem, 0, 0, (LPCWSTR)text.utf16(), -1, uFormat, &rctext, &dto ); |
|
645 BitBlt(hdc, rect.left(), rect.top(), rect.width(), rect.height(), dcMem, 0, 0, SRCCOPY); |
|
646 SelectObject(dcMem, (HGDIOBJ) hOldBmp); |
|
647 SelectObject(dcMem, (HGDIOBJ) hOldFont); |
|
648 DeleteObject(bmp); |
|
649 DeleteObject(hCaptionFont); |
|
650 DeleteDC(dcMem); |
|
651 //ReleaseDC(hwnd, hdc); |
|
652 } else if (vistaState() == VistaBasic) { |
|
653 painter->drawText(rect, text); |
|
654 } |
|
655 return value; |
|
656 } |
|
657 |
|
658 bool QVistaHelper::drawBlackRect(const QRect &rect, HDC hdc) |
|
659 { |
|
660 bool value = false; |
|
661 if (vistaState() == VistaAero) { |
|
662 // Set up a memory DC and bitmap that we'll draw into |
|
663 HDC dcMem; |
|
664 HBITMAP bmp; |
|
665 BITMAPINFO dib = {{0}}; |
|
666 dcMem = CreateCompatibleDC(hdc); |
|
667 |
|
668 dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); |
|
669 dib.bmiHeader.biWidth = rect.width(); |
|
670 dib.bmiHeader.biHeight = -rect.height(); |
|
671 dib.bmiHeader.biPlanes = 1; |
|
672 dib.bmiHeader.biBitCount = 32; |
|
673 dib.bmiHeader.biCompression = BI_RGB; |
|
674 |
|
675 bmp = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0); |
|
676 HBITMAP hOldBmp = (HBITMAP)SelectObject(dcMem, (HGDIOBJ) bmp); |
|
677 |
|
678 BitBlt(hdc, rect.left(), rect.top(), rect.width(), rect.height(), dcMem, 0, 0, SRCCOPY); |
|
679 SelectObject(dcMem, (HGDIOBJ) hOldBmp); |
|
680 |
|
681 DeleteObject(bmp); |
|
682 DeleteDC(dcMem); |
|
683 } |
|
684 return value; |
|
685 } |
|
686 |
|
687 bool QVistaHelper::resolveSymbols() |
|
688 { |
|
689 static bool tried = false; |
|
690 if (!tried) { |
|
691 tried = true; |
|
692 QLibrary dwmLib(QString::fromAscii("dwmapi")); |
|
693 pDwmIsCompositionEnabled = |
|
694 (PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled"); |
|
695 if (pDwmIsCompositionEnabled) { |
|
696 pDwmDefWindowProc = (PtrDwmDefWindowProc)dwmLib.resolve("DwmDefWindowProc"); |
|
697 pDwmExtendFrameIntoClientArea = |
|
698 (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea"); |
|
699 } |
|
700 QLibrary themeLib(QString::fromAscii("uxtheme")); |
|
701 pIsAppThemed = (PtrIsAppThemed)themeLib.resolve("IsAppThemed"); |
|
702 if (pIsAppThemed) { |
|
703 pDrawThemeBackground = (PtrDrawThemeBackground)themeLib.resolve("DrawThemeBackground"); |
|
704 pGetThemePartSize = (PtrGetThemePartSize)themeLib.resolve("GetThemePartSize"); |
|
705 pGetThemeColor = (PtrGetThemeColor)themeLib.resolve("GetThemeColor"); |
|
706 pIsThemeActive = (PtrIsThemeActive)themeLib.resolve("IsThemeActive"); |
|
707 pOpenThemeData = (PtrOpenThemeData)themeLib.resolve("OpenThemeData"); |
|
708 pCloseThemeData = (PtrCloseThemeData)themeLib.resolve("CloseThemeData"); |
|
709 pGetThemeSysFont = (PtrGetThemeSysFont)themeLib.resolve("GetThemeSysFont"); |
|
710 pDrawThemeTextEx = (PtrDrawThemeTextEx)themeLib.resolve("DrawThemeTextEx"); |
|
711 pSetWindowThemeAttribute = (PtrSetWindowThemeAttribute)themeLib.resolve("SetWindowThemeAttribute"); |
|
712 } |
|
713 } |
|
714 |
|
715 return ( |
|
716 pDwmIsCompositionEnabled != 0 |
|
717 && pDwmDefWindowProc != 0 |
|
718 && pDwmExtendFrameIntoClientArea != 0 |
|
719 && pIsAppThemed != 0 |
|
720 && pDrawThemeBackground != 0 |
|
721 && pGetThemePartSize != 0 |
|
722 && pGetThemeColor != 0 |
|
723 && pIsThemeActive != 0 |
|
724 && pOpenThemeData != 0 |
|
725 && pCloseThemeData != 0 |
|
726 && pGetThemeSysFont != 0 |
|
727 && pDrawThemeTextEx != 0 |
|
728 && pSetWindowThemeAttribute != 0 |
|
729 ); |
|
730 } |
|
731 |
|
732 int QVistaHelper::titleOffset() |
|
733 { |
|
734 int iconOffset = wizard ->windowIcon().isNull() ? 0 : iconSize() + padding(); |
|
735 return leftMargin() + iconOffset; |
|
736 } |
|
737 |
|
738 QT_END_NAMESPACE |
|
739 |
|
740 #endif // QT_NO_STYLE_WINDOWSVISTA |
|
741 |
|
742 #endif // QT_NO_WIZARD |