source: trunk/src/gui/dialogs/qwizard_win.cpp@ 1166

Last change on this file since 1166 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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