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

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

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 23.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department 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{
243 is_vista = resolveSymbols();
244 backButton_ = new QVistaBackButton(wizard);
245}
246
247QVistaHelper::~QVistaHelper()
248{
249}
250
251bool QVistaHelper::isCompositionEnabled()
252{
253 bool value = is_vista;
254 if (is_vista) {
255 HRESULT hr;
256 BOOL bEnabled;
257
258 hr = pDwmIsCompositionEnabled(&bEnabled);
259 value = (SUCCEEDED(hr) && bEnabled);
260 }
261 return value;
262}
263
264bool QVistaHelper::isThemeActive()
265{
266 return is_vista && pIsThemeActive();
267}
268
269QVistaHelper::VistaState QVistaHelper::vistaState()
270{
271 if (cachedVistaState == Dirty)
272 cachedVistaState =
273 isCompositionEnabled() ? VistaAero : isThemeActive() ? VistaBasic : Classic;
274 return cachedVistaState;
275}
276
277QColor QVistaHelper::basicWindowFrameColor()
278{
279 DWORD rgb;
280 HANDLE hTheme = pOpenThemeData(qApp->desktop()->winId(), L"WINDOW");
281 pGetThemeColor(
282 hTheme, WIZ_WP_CAPTION, WIZ_CS_ACTIVE,
283 wizard->isActiveWindow() ? WIZ_TMT_FILLCOLORHINT : WIZ_TMT_BORDERCOLORHINT,
284 &rgb);
285 BYTE r = GetRValue(rgb);
286 BYTE g = GetGValue(rgb);
287 BYTE b = GetBValue(rgb);
288 return QColor(r, g, b);
289}
290
291bool QVistaHelper::setDWMTitleBar(TitleBarChangeType type)
292{
293 bool value = false;
294 if (vistaState() == VistaAero) {
295 WIZ_MARGINS mar = {0};
296 if (type == NormalTitleBar)
297 mar.cyTopHeight = 0;
298 else
299 mar.cyTopHeight = titleBarSize() + topOffset();
300 HRESULT hr = pDwmExtendFrameIntoClientArea(wizard->winId(), &mar);
301 value = SUCCEEDED(hr);
302 }
303 return value;
304}
305
306void QVistaHelper::drawTitleBar(QPainter *painter)
307{
308 if (vistaState() == VistaAero)
309 drawBlackRect(
310 QRect(0, 0, wizard->width(), titleBarSize() + topOffset()),
311 painter->paintEngine()->getDC());
312
313 const int btnTop = backButton_->mapToParent(QPoint()).y();
314 const int btnHeight = backButton_->size().height();
315 const int verticalCenter = (btnTop + btnHeight / 2);
316
317 wizard->windowIcon().paint(
318 painter, QRect(leftMargin(), verticalCenter - iconSize() / 2, iconSize(), iconSize()));
319
320 const QString text = wizard->window()->windowTitle();
321 const QFont font = QApplication::font("QWorkspaceTitleBar");
322 const QFontMetrics fontMetrics(font);
323 const QRect brect = fontMetrics.boundingRect(text);
324 int textHeight = brect.height();
325 int textWidth = brect.width();
326 if (vistaState() == VistaAero) {
327 textHeight += 2 * glowSize();
328 textWidth += 2 * glowSize();
329 }
330 drawTitleText(
331 painter, text,
332 QRect(titleOffset(), verticalCenter - textHeight / 2, textWidth, textHeight),
333 painter->paintEngine()->getDC());
334}
335
336void QVistaHelper::setTitleBarIconAndCaptionVisible(bool visible)
337{
338 if (is_vista) {
339 WIZ_WTA_OPTIONS opt;
340 opt.dwFlags = WIZ_WTNCA_NODRAWICON | WIZ_WTNCA_NODRAWCAPTION;
341 if (visible)
342 opt.dwMask = 0;
343 else
344 opt.dwMask = WIZ_WTNCA_NODRAWICON | WIZ_WTNCA_NODRAWCAPTION;
345 pSetWindowThemeAttribute(wizard->winId(), WIZ_WTA_NONCLIENT, &opt, sizeof(WIZ_WTA_OPTIONS));
346 }
347}
348
349bool QVistaHelper::winEvent(MSG* msg, long* result)
350{
351 bool retval = true;
352
353 switch (msg->message) {
354 case WM_NCHITTEST: {
355 LRESULT lResult;
356 pDwmDefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam, &lResult);
357 if (lResult == HTCLOSE || lResult == HTMAXBUTTON || lResult == HTMINBUTTON || lResult == HTHELP)
358 *result = lResult;
359 else
360 *result = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
361 break;
362 }
363 case WM_NCMOUSEMOVE:
364 case WM_NCLBUTTONDOWN:
365 case WM_NCLBUTTONUP:
366 case WIZ_WM_NCMOUSELEAVE: {
367 LRESULT lResult;
368 pDwmDefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam, &lResult);
369 *result = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
370 break;
371 }
372 case WM_NCCALCSIZE: {
373 NCCALCSIZE_PARAMS* lpncsp = (NCCALCSIZE_PARAMS*)msg->lParam;
374 *result = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
375 lpncsp->rgrc[0].top -= (vistaState() == VistaAero ? titleBarSize() : 0);
376 break;
377 }
378 default:
379 retval = false;
380 }
381
382 return retval;
383}
384
385void QVistaHelper::setMouseCursor(QPoint pos)
386{
387 if (rtTop.contains(pos))
388 wizard->setCursor(Qt::SizeVerCursor);
389 else
390 wizard->setCursor(Qt::ArrowCursor);
391}
392
393void QVistaHelper::mouseEvent(QEvent *event)
394{
395 switch (event->type()) {
396 case QEvent::MouseMove:
397 mouseMoveEvent(static_cast<QMouseEvent *>(event));
398 break;
399 case QEvent::MouseButtonPress:
400 mousePressEvent(static_cast<QMouseEvent *>(event));
401 break;
402 case QEvent::MouseButtonRelease:
403 mouseReleaseEvent(static_cast<QMouseEvent *>(event));
404 break;
405 default:
406 break;
407 }
408}
409
410// The following hack ensures that the titlebar is updated correctly
411// when the wizard style changes to and from AeroStyle. Specifically,
412// this function causes a Windows message of type WM_NCCALCSIZE to
413// be triggered.
414void QVistaHelper::setWindowPosHack()
415{
416 const int x = wizard->geometry().x(); // ignored by SWP_NOMOVE
417 const int y = wizard->geometry().y(); // ignored by SWP_NOMOVE
418 const int w = wizard->width();
419 const int h = wizard->height();
420 SetWindowPos(wizard->winId(), 0, x, y, w, h, SWP_NOMOVE | SWP_NOZORDER | SWP_FRAMECHANGED);
421}
422
423// The following hack allows any QWidget subclass to access
424// QWidgetPrivate::topData() without being declared as a
425// friend by QWidget.
426class QHackWidget : public QWidget
427{
428public:
429 Q_DECLARE_PRIVATE(QWidget)
430 QTLWExtra* topData() { return d_func()->topData(); }
431};
432
433void QVistaHelper::collapseTopFrameStrut()
434{
435 QTLWExtra *top = ((QHackWidget *)wizard)->d_func()->topData();
436 int x1, y1, x2, y2;
437 top->frameStrut.getCoords(&x1, &y1, &x2, &y2);
438 top->frameStrut.setCoords(x1, 0, x2, y2);
439}
440
441bool QVistaHelper::handleWinEvent(MSG *message, long *result)
442{
443 if (message->message == WIZ_WM_THEMECHANGED || message->message == WIZ_WM_DWMCOMPOSITIONCHANGED)
444 cachedVistaState = Dirty;
445
446 bool status = false;
447 if (wizard->wizardStyle() == QWizard::AeroStyle && vistaState() == VistaAero) {
448 status = winEvent(message, result);
449 if (message->message == WM_NCCALCSIZE) {
450 if (status)
451 collapseTopFrameStrut();
452 } else if (message->message == WM_NCPAINT) {
453 wizard->update();
454 }
455 }
456 return status;
457}
458
459void QVistaHelper::resizeEvent(QResizeEvent * event)
460{
461 Q_UNUSED(event);
462 rtTop = QRect (0, 0, wizard->width(), frameSize());
463 int height = captionSize() + topOffset();
464 if (vistaState() == VistaBasic)
465 height -= titleBarSize();
466 rtTitle = QRect (0, frameSize(), wizard->width(), height);
467}
468
469void QVistaHelper::paintEvent(QPaintEvent *event)
470{
471 Q_UNUSED(event);
472 QPainter painter(wizard);
473 drawTitleBar(&painter);
474}
475
476void QVistaHelper::mouseMoveEvent(QMouseEvent *event)
477{
478 if (wizard->windowState() & Qt::WindowMaximized) {
479 event->ignore();
480 return;
481 }
482
483 QRect rect = wizard->geometry();
484 if (pressed) {
485 switch (change) {
486 case resizeTop:
487 {
488 const int dy = event->pos().y() - pressedPos.y();
489 if ((dy > 0 && rect.height() > wizard->minimumHeight())
490 || (dy < 0 && rect.height() < wizard->maximumHeight()))
491 rect.setTop(rect.top() + dy);
492 }
493 break;
494 case movePosition: {
495 QPoint newPos = event->pos() - pressedPos;
496 rect.moveLeft(rect.left() + newPos.x());
497 rect.moveTop(rect.top() + newPos.y());
498 break; }
499 default:
500 break;
501 }
502 wizard->setGeometry(rect);
503
504 } else if (vistaState() == VistaAero) {
505 setMouseCursor(event->pos());
506 }
507 event->ignore();
508}
509
510void QVistaHelper::mousePressEvent(QMouseEvent *event)
511{
512 change = noChange;
513
514 if (wizard->windowState() & Qt::WindowMaximized) {
515 event->ignore();
516 return;
517 }
518
519 if (rtTitle.contains(event->pos())) {
520 change = movePosition;
521 } else if (rtTop.contains(event->pos()))
522 change = (vistaState() == VistaAero) ? resizeTop : movePosition;
523
524 if (change != noChange) {
525 if (vistaState() == VistaAero)
526 setMouseCursor(event->pos());
527 pressed = true;
528 pressedPos = event->pos();
529 } else {
530 event->ignore();
531 }
532}
533
534void QVistaHelper::mouseReleaseEvent(QMouseEvent *event)
535{
536 change = noChange;
537 if (pressed) {
538 pressed = false;
539 wizard->releaseMouse();
540 if (vistaState() == VistaAero)
541 setMouseCursor(event->pos());
542 }
543 event->ignore();
544}
545
546bool QVistaHelper::eventFilter(QObject *obj, QEvent *event)
547{
548 if (obj != wizard)
549 return QObject::eventFilter(obj, event);
550
551 if (event->type() == QEvent::MouseMove) {
552 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
553 long result;
554 MSG msg;
555 msg.message = WM_NCHITTEST;
556 msg.wParam = 0;
557 msg.lParam = MAKELPARAM(mouseEvent->globalX(), mouseEvent->globalY());
558 msg.hwnd = wizard->winId();
559 winEvent(&msg, &result);
560 msg.wParam = result;
561 msg.message = WM_NCMOUSEMOVE;
562 winEvent(&msg, &result);
563 } else if (event->type() == QEvent::MouseButtonPress) {
564 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
565 long result;
566 MSG msg;
567 msg.message = WM_NCHITTEST;
568 msg.wParam = 0;
569 msg.lParam = MAKELPARAM(mouseEvent->globalX(), mouseEvent->globalY());
570 msg.hwnd = wizard->winId();
571 winEvent(&msg, &result);
572 msg.wParam = result;
573 msg.message = WM_NCLBUTTONDOWN;
574 winEvent(&msg, &result);
575 } else if (event->type() == QEvent::MouseButtonRelease) {
576 QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
577 long result;
578 MSG msg;
579 msg.message = WM_NCHITTEST;
580 msg.wParam = 0;
581 msg.lParam = MAKELPARAM(mouseEvent->globalX(), mouseEvent->globalY());
582 msg.hwnd = wizard->winId();
583 winEvent(&msg, &result);
584 msg.wParam = result;
585 msg.message = WM_NCLBUTTONUP;
586 winEvent(&msg, &result);
587 }
588
589 return false;
590}
591
592HFONT QVistaHelper::getCaptionFont(HANDLE hTheme)
593{
594 LOGFONT lf = {0};
595
596 if (!hTheme)
597 pGetThemeSysFont(hTheme, WIZ_TMT_CAPTIONFONT, &lf);
598 else
599 {
600 NONCLIENTMETRICS ncm = {sizeof(NONCLIENTMETRICS)};
601 SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, false);
602 lf = ncm.lfMessageFont;
603 }
604 return CreateFontIndirect(&lf);
605}
606
607bool QVistaHelper::drawTitleText(QPainter *painter, const QString &text, const QRect &rect, HDC hdc)
608{
609 bool value = false;
610 if (vistaState() == VistaAero) {
611 HANDLE hTheme = pOpenThemeData(qApp->desktop()->winId(), L"WINDOW");
612 if (!hTheme) return false;
613 // Set up a memory DC and bitmap that we'll draw into
614 HDC dcMem;
615 HBITMAP bmp;
616 BITMAPINFO dib = {0};
617 dcMem = CreateCompatibleDC(hdc);
618
619 dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
620 dib.bmiHeader.biWidth = rect.width();
621 dib.bmiHeader.biHeight = -rect.height();
622 dib.bmiHeader.biPlanes = 1;
623 dib.bmiHeader.biBitCount = 32;
624 dib.bmiHeader.biCompression = BI_RGB;
625
626 bmp = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0);
627
628 // Set up the DC
629 HFONT hCaptionFont = getCaptionFont(hTheme);
630 HBITMAP hOldBmp = (HBITMAP)SelectObject(dcMem, (HGDIOBJ) bmp);
631 HFONT hOldFont = (HFONT)SelectObject(dcMem, (HGDIOBJ) hCaptionFont);
632
633 // Draw the text!
634 WIZ_DTTOPTS dto = { sizeof(WIZ_DTTOPTS) };
635 const UINT uFormat = WIZ_DT_SINGLELINE|WIZ_DT_CENTER|WIZ_DT_VCENTER|WIZ_DT_NOPREFIX;
636 RECT rctext ={0,0, rect.width(), rect.height()};
637
638 dto.dwFlags = WIZ_DTT_COMPOSITED|WIZ_DTT_GLOWSIZE;
639 dto.iGlowSize = glowSize();
640
641 pDrawThemeTextEx(hTheme, dcMem, 0, 0, (LPCWSTR)text.utf16(), -1, uFormat, &rctext, &dto );
642 BitBlt(hdc, rect.left(), rect.top(), rect.width(), rect.height(), dcMem, 0, 0, SRCCOPY);
643 SelectObject(dcMem, (HGDIOBJ) hOldBmp);
644 SelectObject(dcMem, (HGDIOBJ) hOldFont);
645 DeleteObject(bmp);
646 DeleteObject(hCaptionFont);
647 DeleteDC(dcMem);
648 //ReleaseDC(hwnd, hdc);
649 } else if (vistaState() == VistaBasic) {
650 painter->drawText(rect, text);
651 }
652 return value;
653}
654
655bool QVistaHelper::drawBlackRect(const QRect &rect, HDC hdc)
656{
657 bool value = false;
658 if (vistaState() == VistaAero) {
659 // Set up a memory DC and bitmap that we'll draw into
660 HDC dcMem;
661 HBITMAP bmp;
662 BITMAPINFO dib = {0};
663 dcMem = CreateCompatibleDC(hdc);
664
665 dib.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
666 dib.bmiHeader.biWidth = rect.width();
667 dib.bmiHeader.biHeight = -rect.height();
668 dib.bmiHeader.biPlanes = 1;
669 dib.bmiHeader.biBitCount = 32;
670 dib.bmiHeader.biCompression = BI_RGB;
671
672 bmp = CreateDIBSection(hdc, &dib, DIB_RGB_COLORS, NULL, NULL, 0);
673 HBITMAP hOldBmp = (HBITMAP)SelectObject(dcMem, (HGDIOBJ) bmp);
674
675 BitBlt(hdc, rect.left(), rect.top(), rect.width(), rect.height(), dcMem, 0, 0, SRCCOPY);
676 SelectObject(dcMem, (HGDIOBJ) hOldBmp);
677
678 DeleteObject(bmp);
679 DeleteDC(dcMem);
680 }
681 return value;
682}
683
684bool QVistaHelper::resolveSymbols()
685{
686 static bool tried = false;
687 if (!tried) {
688 tried = true;
689 QLibrary dwmLib(QString::fromAscii("dwmapi"));
690 pDwmIsCompositionEnabled =
691 (PtrDwmIsCompositionEnabled)dwmLib.resolve("DwmIsCompositionEnabled");
692 if (pDwmIsCompositionEnabled) {
693 pDwmDefWindowProc = (PtrDwmDefWindowProc)dwmLib.resolve("DwmDefWindowProc");
694 pDwmExtendFrameIntoClientArea =
695 (PtrDwmExtendFrameIntoClientArea)dwmLib.resolve("DwmExtendFrameIntoClientArea");
696 }
697 QLibrary themeLib(QString::fromAscii("uxtheme"));
698 pIsAppThemed = (PtrIsAppThemed)themeLib.resolve("IsAppThemed");
699 if (pIsAppThemed) {
700 pDrawThemeBackground = (PtrDrawThemeBackground)themeLib.resolve("DrawThemeBackground");
701 pGetThemePartSize = (PtrGetThemePartSize)themeLib.resolve("GetThemePartSize");
702 pGetThemeColor = (PtrGetThemeColor)themeLib.resolve("GetThemeColor");
703 pIsThemeActive = (PtrIsThemeActive)themeLib.resolve("IsThemeActive");
704 pOpenThemeData = (PtrOpenThemeData)themeLib.resolve("OpenThemeData");
705 pCloseThemeData = (PtrCloseThemeData)themeLib.resolve("CloseThemeData");
706 pGetThemeSysFont = (PtrGetThemeSysFont)themeLib.resolve("GetThemeSysFont");
707 pDrawThemeTextEx = (PtrDrawThemeTextEx)themeLib.resolve("DrawThemeTextEx");
708 pSetWindowThemeAttribute = (PtrSetWindowThemeAttribute)themeLib.resolve("SetWindowThemeAttribute");
709 }
710 }
711
712 return (
713 pDwmIsCompositionEnabled != 0
714 && pDwmDefWindowProc != 0
715 && pDwmExtendFrameIntoClientArea != 0
716 && pIsAppThemed != 0
717 && pDrawThemeBackground != 0
718 && pGetThemePartSize != 0
719 && pGetThemeColor != 0
720 && pIsThemeActive != 0
721 && pOpenThemeData != 0
722 && pCloseThemeData != 0
723 && pGetThemeSysFont != 0
724 && pDrawThemeTextEx != 0
725 && pSetWindowThemeAttribute != 0
726 );
727}
728
729int QVistaHelper::titleOffset()
730{
731 int iconOffset = wizard ->windowIcon().isNull() ? 0 : iconSize() + padding();
732 return leftMargin() + iconOffset;
733}
734
735QT_END_NAMESPACE
736
737#endif // QT_NO_STYLE_WINDOWSVISTA
738
739#endif // QT_NO_WIZARD
Note: See TracBrowser for help on using the repository browser.