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

Last change on this file since 564 was 561, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 24.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 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 "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
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 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
195void QVistaBackButton::enterEvent(QEvent *event)
196{
197 if (isEnabled())
198 update();
199 QAbstractButton::enterEvent(event);
200}
201
202void QVistaBackButton::leaveEvent(QEvent *event)
203{
204 if (isEnabled())
205 update();
206 QAbstractButton::leaveEvent(event);
207}
208
209void 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
239QVistaHelper::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
249QVistaHelper::~QVistaHelper()
250{
251}
252
253bool 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
266bool QVistaHelper::isThemeActive()
267{
268 return is_vista && pIsThemeActive();
269}
270
271QVistaHelper::VistaState QVistaHelper::vistaState()
272{
273 if (cachedVistaState == Dirty)
274 cachedVistaState =
275 isCompositionEnabled() ? VistaAero : isThemeActive() ? VistaBasic : Classic;
276 return cachedVistaState;
277}
278
279QColor 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
293bool 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
308void 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
339void 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
352bool 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
388void QVistaHelper::setMouseCursor(QPoint pos)
389{
390#ifndef QT_NO_CURSOR
391 if (rtTop.contains(pos))
392 wizard->setCursor(Qt::SizeVerCursor);
393 else
394 wizard->setCursor(Qt::ArrowCursor);
395#endif
396}
397
398void QVistaHelper::mouseEvent(QEvent *event)
399{
400 switch (event->type()) {
401 case QEvent::MouseMove:
402 mouseMoveEvent(static_cast<QMouseEvent *>(event));
403 break;
404 case QEvent::MouseButtonPress:
405 mousePressEvent(static_cast<QMouseEvent *>(event));
406 break;
407 case QEvent::MouseButtonRelease:
408 mouseReleaseEvent(static_cast<QMouseEvent *>(event));
409 break;
410 default:
411 break;
412 }
413}
414
415// The following hack ensures that the titlebar is updated correctly
416// when the wizard style changes to and from AeroStyle. Specifically,
417// this function causes a Windows message of type WM_NCCALCSIZE to
418// be triggered.
419void QVistaHelper::setWindowPosHack()
420{
421 const int x = wizard->geometry().x(); // ignored by SWP_NOMOVE
422 const int y = wizard->geometry().y(); // ignored by SWP_NOMOVE
423 const int w = wizard->width();
424 const int h = wizard->height();
425 SetWindowPos(wizard->winId(), 0, x, y, w, h, SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
426}
427
428// The following hack allows any QWidget subclass to access
429// QWidgetPrivate::topData() without being declared as a
430// friend by QWidget.
431class QHackWidget : public QWidget
432{
433public:
434 Q_DECLARE_PRIVATE(QWidget)
435 QTLWExtra* topData() { return d_func()->topData(); }
436};
437
438void QVistaHelper::collapseTopFrameStrut()
439{
440 QTLWExtra *top = ((QHackWidget *)wizard)->d_func()->topData();
441 int x1, y1, x2, y2;
442 top->frameStrut.getCoords(&x1, &y1, &x2, &y2);
443 top->frameStrut.setCoords(x1, 0, x2, y2);
444}
445
446bool QVistaHelper::handleWinEvent(MSG *message, long *result)
447{
448 if (message->message == WIZ_WM_THEMECHANGED || message->message == WIZ_WM_DWMCOMPOSITIONCHANGED)
449 cachedVistaState = Dirty;
450
451 bool status = false;
452 if (wizard->wizardStyle() == QWizard::AeroStyle && vistaState() == VistaAero) {
453 status = winEvent(message, result);
454 if (message->message == WM_NCCALCSIZE) {
455 if (status)
456 collapseTopFrameStrut();
457 } else if (message->message == WM_NCPAINT) {
458 wizard->update();
459 }
460 }
461 return status;
462}
463
464void QVistaHelper::resizeEvent(QResizeEvent * event)
465{
466 Q_UNUSED(event);
467 rtTop = QRect (0, 0, wizard->width(), frameSize());
468 int height = captionSize() + topOffset();
469 if (vistaState() == VistaBasic)
470 height -= titleBarSize();
471 rtTitle = QRect (0, frameSize(), wizard->width(), height);
472}
473
474void QVistaHelper::paintEvent(QPaintEvent *event)
475{
476 Q_UNUSED(event);
477 QPainter painter(wizard);
478 drawTitleBar(&painter);
479}
480
481void QVistaHelper::mouseMoveEvent(QMouseEvent *event)
482{
483 if (wizard->windowState() & Qt::WindowMaximized) {
484 event->ignore();
485 return;
486 }
487
488 QRect rect = wizard->geometry();
489 if (pressed) {
490 switch (change) {
491 case resizeTop:
492 {
493 const int dy = event->pos().y() - pressedPos.y();
494 if ((dy > 0 && rect.height() > wizard->minimumHeight())
495 || (dy < 0 && rect.height() < wizard->maximumHeight()))
496 rect.setTop(rect.top() + dy);
497 }
498 break;
499 case movePosition: {
500 QPoint newPos = event->pos() - pressedPos;
501 rect.moveLeft(rect.left() + newPos.x());
502 rect.moveTop(rect.top() + newPos.y());
503 break; }
504 default:
505 break;
506 }
507 wizard->setGeometry(rect);
508
509 } else if (vistaState() == VistaAero) {
510 setMouseCursor(event->pos());
511 }
512 event->ignore();
513}
514
515void QVistaHelper::mousePressEvent(QMouseEvent *event)
516{
517 change = noChange;
518
519 if (wizard->windowState() & Qt::WindowMaximized) {
520 event->ignore();
521 return;
522 }
523
524 if (rtTitle.contains(event->pos())) {
525 change = movePosition;
526 } else if (rtTop.contains(event->pos()))
527 change = (vistaState() == VistaAero) ? resizeTop : movePosition;
528
529 if (change != noChange) {
530 if (vistaState() == VistaAero)
531 setMouseCursor(event->pos());
532 pressed = true;
533 pressedPos = event->pos();
534 } else {
535 event->ignore();
536 }
537}
538
539void QVistaHelper::mouseReleaseEvent(QMouseEvent *event)
540{
541 change = noChange;
542 if (pressed) {
543 pressed = false;
544 wizard->releaseMouse();
545 if (vistaState() == VistaAero)
546 setMouseCursor(event->pos());
547 }
548 event->ignore();
549}
550
551bool QVistaHelper::eventFilter(QObject *obj, QEvent *event)
552{
553 if (obj != wizard)
554 return QObject::eventFilter(obj, event);
555
556 if (event->type() == QEvent::MouseMove) {
557 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
558 long result;
559 MSG msg;
560 msg.message = WM_NCHITTEST;
561 msg.wParam = 0;
562 msg.lParam = MAKELPARAM(mouseEvent->globalX(), mouseEvent->globalY());
563 msg.hwnd = wizard->winId();
564 winEvent(&msg, &result);
565 msg.wParam = result;
566 msg.message = WM_NCMOUSEMOVE;
567 winEvent(&msg, &result);
568 } else if (event->type() == QEvent::MouseButtonPress) {
569 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
570 long result;
571 MSG msg;
572 msg.message = WM_NCHITTEST;
573 msg.wParam = 0;
574 msg.lParam = MAKELPARAM(mouseEvent->globalX(), mouseEvent->globalY());
575 msg.hwnd = wizard->winId();
576 winEvent(&msg, &result);
577 msg.wParam = result;
578 msg.message = WM_NCLBUTTONDOWN;
579 winEvent(&msg, &result);
580 } else if (event->type() == QEvent::MouseButtonRelease) {
581 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
582 long result;
583 MSG msg;
584 msg.message = WM_NCHITTEST;
585 msg.wParam = 0;
586 msg.lParam = MAKELPARAM(mouseEvent->globalX(), mouseEvent->globalY());
587 msg.hwnd = wizard->winId();
588 winEvent(&msg, &result);
589 msg.wParam = result;
590 msg.message = WM_NCLBUTTONUP;
591 winEvent(&msg, &result);
592 }
593
594 return false;
595}
596
597HFONT QVistaHelper::getCaptionFont(HANDLE hTheme)
598{
599 LOGFONT lf = {0};
600
601 if (!hTheme)
602 pGetThemeSysFont(hTheme, WIZ_TMT_CAPTIONFONT, &lf);
603 else
604 {
605 NONCLIENTMETRICS ncm = {sizeof(NONCLIENTMETRICS)};
606 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, false);
607 lf = ncm.lfMessageFont;
608 }
609 return CreateFontIndirect(&lf);
610}
611
612bool QVistaHelper::drawTitleText(QPainter *painter, const QString &text, const QRect &rect, HDC hdc)
613{
614 bool value = false;
615 if (vistaState() == VistaAero) {
616 HANDLE hTheme = pOpenThemeData(QApplication::desktop()->winId(), L"WINDOW");
617 if (!hTheme) return false;
618 // Set up a memory DC and bitmap that we'll draw into
619 HDC dcMem;
620 HBITMAP bmp;
621 BITMAPINFO dib = {{0}};
622 dcMem = CreateCompatibleDC(hdc);
623
624 dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
625 dib.bmiHeader.biWidth = rect.width();
626 dib.bmiHeader.biHeight = -rect.height();
627 dib.bmiHeader.biPlanes = 1;
628 dib.bmiHeader.biBitCount = 32;
629 dib.bmiHeader.biCompression = BI_RGB;
630
631 bmp = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0);
632
633 // Set up the DC
634 HFONT hCaptionFont = getCaptionFont(hTheme);
635 HBITMAP hOldBmp = (HBITMAP)SelectObject(dcMem, (HGDIOBJ) bmp);
636 HFONT hOldFont = (HFONT)SelectObject(dcMem, (HGDIOBJ) hCaptionFont);
637
638 // Draw the text!
639 WIZ_DTTOPTS dto = { sizeof(WIZ_DTTOPTS) };
640 const UINT uFormat = WIZ_DT_SINGLELINE|WIZ_DT_CENTER|WIZ_DT_VCENTER|WIZ_DT_NOPREFIX;
641 RECT rctext ={0,0, rect.width(), rect.height()};
642
643 dto.dwFlags = WIZ_DTT_COMPOSITED|WIZ_DTT_GLOWSIZE;
644 dto.iGlowSize = glowSize();
645
646 pDrawThemeTextEx(hTheme, dcMem, 0, 0, (LPCWSTR)text.utf16(), -1, uFormat, &rctext, &dto );
647 BitBlt(hdc, rect.left(), rect.top(), rect.width(), rect.height(), dcMem, 0, 0, SRCCOPY);
648 SelectObject(dcMem, (HGDIOBJ) hOldBmp);
649 SelectObject(dcMem, (HGDIOBJ) hOldFont);
650 DeleteObject(bmp);
651 DeleteObject(hCaptionFont);
652 DeleteDC(dcMem);
653 //ReleaseDC(hwnd, hdc);
654 } else if (vistaState() == VistaBasic) {
655 painter->drawText(rect, text);
656 }
657 return value;
658}
659
660bool QVistaHelper::drawBlackRect(const QRect &rect, HDC hdc)
661{
662 bool value = false;
663 if (vistaState() == VistaAero) {
664 // Set up a memory DC and bitmap that we'll draw into
665 HDC dcMem;
666 HBITMAP bmp;
667 BITMAPINFO dib = {{0}};
668 dcMem = CreateCompatibleDC(hdc);
669
670 dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
671 dib.bmiHeader.biWidth = rect.width();
672 dib.bmiHeader.biHeight = -rect.height();
673 dib.bmiHeader.biPlanes = 1;
674 dib.bmiHeader.biBitCount = 32;
675 dib.bmiHeader.biCompression = BI_RGB;
676
677 bmp = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0);
678 HBITMAP hOldBmp = (HBITMAP)SelectObject(dcMem, (HGDIOBJ) bmp);
679
680 BitBlt(hdc, rect.left(), rect.top(), rect.width(), rect.height(), dcMem, 0, 0, SRCCOPY);
681 SelectObject(dcMem, (HGDIOBJ) hOldBmp);
682
683 DeleteObject(bmp);
684 DeleteDC(dcMem);
685 }
686 return value;
687}
688
689bool QVistaHelper::resolveSymbols()
690{
691 static bool tried = false;
692 if (!tried) {
693 tried = true;
694 QLibrary dwmLib(QString::fromAscii("dwmapi"));
695 pDwmIsCompositionEnabled =
696 (PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled");
697 if (pDwmIsCompositionEnabled) {
698 pDwmDefWindowProc = (PtrDwmDefWindowProc)dwmLib.resolve("DwmDefWindowProc");
699 pDwmExtendFrameIntoClientArea =
700 (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea");
701 }
702 QLibrary themeLib(QString::fromAscii("uxtheme"));
703 pIsAppThemed = (PtrIsAppThemed)themeLib.resolve("IsAppThemed");
704 if (pIsAppThemed) {
705 pDrawThemeBackground = (PtrDrawThemeBackground)themeLib.resolve("DrawThemeBackground");
706 pGetThemePartSize = (PtrGetThemePartSize)themeLib.resolve("GetThemePartSize");
707 pGetThemeColor = (PtrGetThemeColor)themeLib.resolve("GetThemeColor");
708 pIsThemeActive = (PtrIsThemeActive)themeLib.resolve("IsThemeActive");
709 pOpenThemeData = (PtrOpenThemeData)themeLib.resolve("OpenThemeData");
710 pCloseThemeData = (PtrCloseThemeData)themeLib.resolve("CloseThemeData");
711 pGetThemeSysFont = (PtrGetThemeSysFont)themeLib.resolve("GetThemeSysFont");
712 pDrawThemeTextEx = (PtrDrawThemeTextEx)themeLib.resolve("DrawThemeTextEx");
713 pSetWindowThemeAttribute = (PtrSetWindowThemeAttribute)themeLib.resolve("SetWindowThemeAttribute");
714 }
715 }
716
717 return (
718 pDwmIsCompositionEnabled != 0
719 && pDwmDefWindowProc != 0
720 && pDwmExtendFrameIntoClientArea != 0
721 && pIsAppThemed != 0
722 && pDrawThemeBackground != 0
723 && pGetThemePartSize != 0
724 && pGetThemeColor != 0
725 && pIsThemeActive != 0
726 && pOpenThemeData != 0
727 && pCloseThemeData != 0
728 && pGetThemeSysFont != 0
729 && pDrawThemeTextEx != 0
730 && pSetWindowThemeAttribute != 0
731 );
732}
733
734int QVistaHelper::titleOffset()
735{
736 int iconOffset = wizard ->windowIcon().isNull() ? 0 : iconSize() + padding();
737 return leftMargin() + iconOffset;
738}
739
740QT_END_NAMESPACE
741
742#endif // QT_NO_STYLE_WINDOWSVISTA
743
744#endif // QT_NO_WIZARD
Note: See TracBrowser for help on using the repository browser.