diff options
author | miniak <milan.burda@gmail.com> | 2009-09-22 08:33:27 (GMT) |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com> | 2009-09-22 08:33:27 (GMT) |
commit | ac7fca3606d1a7dd5985b6fc284c40c0f2682fe5 (patch) | |
tree | 986d53bf15469aa9207e301b8a1c7c401218dc36 | |
parent | c0f1055fe809e6f4c90ea7ba3c369b2c01aaae07 (diff) | |
download | Qt-ac7fca3606d1a7dd5985b6fc284c40c0f2682fe5.zip Qt-ac7fca3606d1a7dd5985b6fc284c40c0f2682fe5.tar.gz Qt-ac7fca3606d1a7dd5985b6fc284c40c0f2682fe5.tar.bz2 |
* QPixmap: Add toWinHICON() & fromWinHICON() method
Duplicate QPixmap <-> HICON conversion code removed from
qwidget_win.cpp & qsystemtrayicon_win.cpp.
Task-number: 218533
Merge-request: 1570
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>
15 files changed, 192 insertions, 75 deletions
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 4f145af..558ae54 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1678,12 +1678,15 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) operation, you can use QBitmap::fromImage() instead. In addition, on Windows, the QPixmap class supports conversion to - and from HBitmap: the toWinHBITMAP() function creates a HBITMAP + and from HBITMAP: the toWinHBITMAP() function creates a HBITMAP equivalent to the QPixmap, based on the given HBitmapFormat, and returns the HBITMAP handle. The fromWinHBITMAP() function returns a QPixmap that is equivalent to the given bitmap which has the - specified format. - + specified format. The QPixmap class also supports conversion to + and from HICON: the toWinHICON() function creates a HICON equivalent + to the QPixmap, and returns the HICON handle. The fromWinHICON() + function returns a QPixmap that is equivalent to the given icon. + In addition, on Symbian, the QPixmap class supports conversion to and from CFbsBitmap: the toSymbianCFbsBitmap() function creates CFbsBitmap equivalent to the QPixmap, based on given mode and returns @@ -2040,7 +2043,7 @@ QPixmapData* QPixmap::pixmapData() const \warning This function is only available on Windows. - \sa fromWinHBITMAP() + \sa fromWinHBITMAP(), {QPixmap#Pixmap Conversion}{Pixmap Conversion} */ /*! \fn QPixmap QPixmap::fromWinHBITMAP(HBITMAP bitmap, HBitmapFormat format) @@ -2054,6 +2057,31 @@ QPixmapData* QPixmap::pixmapData() const */ +/*! \fn HICON QPixmap::toWinHICON() const + \since 4.6 + + \bold{Win32 only:} Creates a \c HICON equivalent to the QPixmap. + Returns the \c HICON handle. + + It is the caller's responsibility to free the \c HICON data after use. + + \warning This function is only available on Windows. + + \sa fromWinHICON(), {QPixmap#Pixmap Conversion}{Pixmap Conversion} +*/ + +/*! \fn QPixmap QPixmap::fromWinHICON(HICON icon) + \since 4.6 + + \bold{Win32 only:} Returns a QPixmap that is equivalent to the given + \a icon. + + \warning This function is only available on Windows. + + \sa toWinHICON(), {QPixmap#Pixmap Conversion}{Pixmap Conversion} + +*/ + /*! \fn const QX11Info &QPixmap::x11Info() const \bold{X11 only:} Returns information about the configuration of the X display used to display the widget. diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h index 54e89ff..2ed65ea 100644 --- a/src/gui/image/qpixmap.h +++ b/src/gui/image/qpixmap.h @@ -149,7 +149,10 @@ public: }; HBITMAP toWinHBITMAP(HBitmapFormat format = NoAlpha) const; + HICON toWinHICON() const; + static QPixmap fromWinHBITMAP(HBITMAP hbitmap, HBitmapFormat format = NoAlpha); + static QPixmap fromWinHICON(HICON hicon); #endif #if defined(Q_WS_MAC) diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp index 9042840..7f0c8e3 100644 --- a/src/gui/image/qpixmap_win.cpp +++ b/src/gui/image/qpixmap_win.cpp @@ -236,6 +236,49 @@ QPixmap QPixmap::fromWinHBITMAP(HBITMAP bitmap, HBitmapFormat format) return fromImage(result); } +HBITMAP qt_createIconMask(const QBitmap &bitmap) +{ + QImage bm = bitmap.toImage().convertToFormat(QImage::Format_Mono); + int w = bm.width(); + int h = bm.height(); + int bpl = ((w+15)/16)*2; // bpl, 16 bit alignment + uchar *bits = new uchar[bpl*h]; + bm.invertPixels(); + for (int y=0; y<h; y++) + memcpy(bits+y*bpl, bm.scanLine(y), bpl); + HBITMAP hbm = CreateBitmap(w, h, 1, 1, bits); + delete [] bits; + return hbm; +} + +HICON QPixmap::toWinHICON() const +{ + QBitmap maskBitmap = mask(); + if (maskBitmap.isNull()) { + maskBitmap= QBitmap(size()); + maskBitmap.fill(Qt::color1); + } + + ICONINFO ii; + ii.fIcon = true; + ii.hbmMask = qt_createIconMask(maskBitmap); + ii.hbmColor = toWinHBITMAP(QPixmap::Alpha); + ii.xHotspot = 0; + ii.yHotspot = 0; + + HICON hIcon = CreateIconIndirect(&ii); + + DeleteObject(ii.hbmColor); + DeleteObject(ii.hbmMask); + + return hIcon; +} + +QPixmap QPixmap::fromWinHICON(HICON icon) +{ + return convertHIconToPixmap(icon); +} + #ifdef Q_WS_WIN #ifndef Q_WS_WINCE diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 211e9d4..c705e2a 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -747,25 +747,6 @@ void QWidgetPrivate::setWindowTitle_sys(const QString &caption) SetWindowText(q->internalWinId(), (wchar_t*)caption.utf16()); } -/* - Create an icon mask the way Windows wants it using CreateBitmap. -*/ - -HBITMAP qt_createIconMask(const QBitmap &bitmap) -{ - QImage bm = bitmap.toImage().convertToFormat(QImage::Format_Mono); - int w = bm.width(); - int h = bm.height(); - int bpl = ((w+15)/16)*2; // bpl, 16 bit alignment - uchar *bits = new uchar[bpl*h]; - bm.invertPixels(); - for (int y=0; y<h; y++) - memcpy(bits+y*bpl, bm.scanLine(y), bpl); - HBITMAP hbm = CreateBitmap(w, h, 1, 1, bits); - delete [] bits; - return hbm; -} - HICON qt_createIcon(QIcon icon, int xSize, int ySize, QPixmap **cache) { HICON result = 0; @@ -775,27 +756,12 @@ HICON qt_createIcon(QIcon icon, int xSize, int ySize, QPixmap **cache) if (pm.isNull()) return 0; - QBitmap mask = pm.mask(); - if (mask.isNull()) { - mask = QBitmap(pm.size()); - mask.fill(Qt::color1); - } - - HBITMAP im = qt_createIconMask(mask); - ICONINFO ii; - ii.fIcon = true; - ii.hbmMask = im; - ii.hbmColor = pm.toWinHBITMAP(QPixmap::Alpha); - ii.xHotspot = 0; - ii.yHotspot = 0; - result = CreateIconIndirect(&ii); + result = pm.toWinHICON(); if (cache) { delete *cache; *cache = new QPixmap(pm);; } - DeleteObject(ii.hbmColor); - DeleteObject(im); } return result; } diff --git a/src/gui/util/qsystemtrayicon_win.cpp b/src/gui/util/qsystemtrayicon_win.cpp index fc3d527..362be5b 100644 --- a/src/gui/util/qsystemtrayicon_win.cpp +++ b/src/gui/util/qsystemtrayicon_win.cpp @@ -98,7 +98,6 @@ public: bool allowsMessages(); bool supportsMessages(); QRect findIconGeometry(const int a_iButtonID); - HBITMAP createIconMask(const QBitmap &bitmap); void createIcon(); HICON hIcon; QPoint globalPos; @@ -241,21 +240,6 @@ bool QSystemTrayIconSys::iconDrawItem(LPDRAWITEMSTRUCT lpdi) return true; } -HBITMAP QSystemTrayIconSys::createIconMask(const QBitmap &bitmap) -{ - QImage bm = bitmap.toImage().convertToFormat(QImage::Format_Mono); - int w = bm.width(); - int h = bm.height(); - int bpl = ((w+15)/16)*2; // bpl, 16 bit alignment - uchar *bits = new uchar[bpl*h]; - bm.invertPixels(); - for (int y=0; y<h; y++) - memcpy(bits+y*bpl, bm.scanLine(y), bpl); - HBITMAP hbm = CreateBitmap(w, h, 1, 1, bits); - delete [] bits; - return hbm; -} - void QSystemTrayIconSys::createIcon() { hIcon = 0; @@ -270,23 +254,7 @@ void QSystemTrayIconSys::createIcon() if (pm.isNull()) return; - QBitmap mask = pm.mask(); - if (mask.isNull()) { - mask = QBitmap(pm.size()); - mask.fill(Qt::color1); - } - - HBITMAP im = createIconMask(mask); - ICONINFO ii; - ii.fIcon = true; - ii.hbmMask = im; - ii.hbmColor = pm.toWinHBITMAP(QPixmap::Alpha); - ii.xHotspot = 0; - ii.yHotspot = 0; - hIcon = CreateIconIndirect(&ii); - - DeleteObject(ii.hbmColor); - DeleteObject(im); + hIcon = pm.toWinHICON(); } bool QSystemTrayIconSys::winEvent( MSG *m, long *result ) diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp.ico b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp.ico Binary files differnew file mode 100644 index 0000000..dbb55cd --- /dev/null +++ b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp.ico diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_16x16.png b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_16x16.png Binary files differnew file mode 100644 index 0000000..f23f398 --- /dev/null +++ b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_16x16.png diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_256x256.png b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_256x256.png Binary files differnew file mode 100644 index 0000000..293f1c5 --- /dev/null +++ b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_256x256.png diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_32x32.png b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_32x32.png Binary files differnew file mode 100644 index 0000000..bfdb1fe --- /dev/null +++ b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_32x32.png diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_48x48.png b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_48x48.png Binary files differnew file mode 100644 index 0000000..7dd2d13 --- /dev/null +++ b/tests/auto/qpixmap/convertFromToHICON/icon_32bpp_48x48.png diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_8bpp.ico b/tests/auto/qpixmap/convertFromToHICON/icon_8bpp.ico Binary files differnew file mode 100644 index 0000000..4341a33 --- /dev/null +++ b/tests/auto/qpixmap/convertFromToHICON/icon_8bpp.ico diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_16x16.png b/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_16x16.png Binary files differnew file mode 100644 index 0000000..e9a995e --- /dev/null +++ b/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_16x16.png diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_32x32.png b/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_32x32.png Binary files differnew file mode 100644 index 0000000..41ef57f --- /dev/null +++ b/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_32x32.png diff --git a/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_48x48.png b/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_48x48.png Binary files differnew file mode 100644 index 0000000..35d60d1 --- /dev/null +++ b/tests/auto/qpixmap/convertFromToHICON/icon_8bpp_48x48.png diff --git a/tests/auto/qpixmap/tst_qpixmap.cpp b/tests/auto/qpixmap/tst_qpixmap.cpp index 4721d2d..1bfddc1 100644 --- a/tests/auto/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/qpixmap/tst_qpixmap.cpp @@ -134,6 +134,11 @@ private slots: void toWinHBITMAP(); void fromWinHBITMAP_data(); void fromWinHBITMAP(); + + void toWinHICON_data(); + void toWinHICON(); + void fromWinHICON_data(); + void fromWinHICON(); #endif #if defined(Q_WS_S60) @@ -939,13 +944,13 @@ void tst_QPixmap::fromWinHBITMAP() HDC display_dc = GetDC(0); HDC bitmap_dc = CreateCompatibleDC(display_dc); HBITMAP bitmap = CreateCompatibleBitmap(display_dc, 100, 100); - HBITMAP null_bitmap = (HBITMAP) SelectObject(bitmap_dc, bitmap); + SelectObject(bitmap_dc, bitmap); SelectObject(bitmap_dc, GetStockObject(NULL_PEN)); HGDIOBJ old_brush = SelectObject(bitmap_dc, CreateSolidBrush(RGB(red, green, blue))); Rectangle(bitmap_dc, 0, 0, 100, 100); -#ifdef Q_OS_WINCE //the device context has to be deleted before ::fromWinHBITMAP() +#ifdef Q_OS_WINCE //the device context has to be deleted before QPixmap::fromWinHBITMAP() DeleteDC(bitmap_dc); #endif QPixmap pixmap = QPixmap::fromWinHBITMAP(bitmap); @@ -966,7 +971,111 @@ void tst_QPixmap::fromWinHBITMAP() ReleaseDC(0, display_dc); } -#endif +static void compareImages(const QImage &image1, const QImage &image2) +{ + QCOMPARE(image1.width(), image2.width()); + QCOMPARE(image1.height(), image2.height()); + QCOMPARE(image1.format(), image2.format()); + + static const int fuzz = 1; + + for (int y = 0; y < image1.height(); y++) + { + for (int x = 0; x < image2.width(); x++) + { + QRgb p1 = image1.pixel(x, y); + QRgb p2 = image2.pixel(x, y); + + bool pixelMatches = + qAbs(qRed(p1) - qRed(p2)) <= fuzz + && qAbs(qGreen(p1) - qGreen(p2)) <= fuzz + && qAbs(qBlue(p1) - qBlue(p2)) <= fuzz + && qAbs(qAlpha(p1) - qAlpha(p2)) <= fuzz; + + QVERIFY(pixelMatches); + } + } +} + +void tst_QPixmap::toWinHICON_data() +{ + QTest::addColumn<QString>("image"); + QTest::addColumn<int>("width"); + QTest::addColumn<int>("height"); + + const QString prefix = QLatin1String(SRCDIR) + "/convertFromToHICON"; + + QTest::newRow("32bpp_16x16") << prefix + QLatin1String("/icon_32bpp") << 16 << 16; + QTest::newRow("32bpp_32x32") << prefix + QLatin1String("/icon_32bpp") << 32 << 32; + QTest::newRow("32bpp_48x48") << prefix + QLatin1String("/icon_32bpp") << 48 << 48; + QTest::newRow("32bpp_256x256") << prefix + QLatin1String("/icon_32bpp") << 256 << 256; + + QTest::newRow("8bpp_16x16") << prefix + QLatin1String("/icon_8bpp") << 16 << 16; + QTest::newRow("8bpp_32x32") << prefix + QLatin1String("/icon_8bpp") << 32 << 32; + QTest::newRow("8bpp_48x48") << prefix + QLatin1String("/icon_8bpp") << 48 << 48; +} + +void tst_QPixmap::toWinHICON() +{ + QFETCH(int, width); + QFETCH(int, height); + QFETCH(QString, image); + + QPixmap empty(width, height); + empty.fill(Qt::transparent); + + HDC display_dc = GetDC(0); + HDC bitmap_dc = CreateCompatibleDC(display_dc); + HBITMAP bitmap = empty.toWinHBITMAP(QPixmap::Alpha); + SelectObject(bitmap_dc, bitmap); + + QImage imageFromFile(image + QString(QLatin1String("_%1x%2.png")).arg(width).arg(height)); + imageFromFile = imageFromFile.convertToFormat(QImage::Format_ARGB32_Premultiplied); + + HICON icon = QPixmap::fromImage(imageFromFile).toWinHICON(); + + DrawIconEx(bitmap_dc, 0, 0, icon, width, height, 0, 0, DI_NORMAL); + + DestroyIcon(icon); + DeleteDC(bitmap_dc); + + QImage imageFromHICON = QPixmap::fromWinHBITMAP(bitmap, QPixmap::Alpha).toImage(); + + ReleaseDC(0, display_dc); + + // fuzzy comparison must be used, as the pixel values change slightly during conversion + // between QImage::Format_ARGB32 and QImage::Format_ARGB32_Premultiplied, or elsewhere + + // QVERIFY(imageFromHICON == imageFromFile); + compareImages(imageFromHICON, imageFromFile); +} + +void tst_QPixmap::fromWinHICON_data() +{ + toWinHICON_data(); +} + +void tst_QPixmap::fromWinHICON() +{ + QFETCH(int, width); + QFETCH(int, height); + QFETCH(QString, image); + + HICON icon = (HICON)LoadImage(0, (wchar_t*)(image + QLatin1String(".ico")).utf16(), IMAGE_ICON, width, height, LR_LOADFROMFILE); + QImage imageFromHICON = QPixmap::fromWinHICON(icon).toImage(); + DestroyIcon(icon); + + QImage imageFromFile(image + QString(QLatin1String("_%1x%2.png")).arg(width).arg(height)); + imageFromFile = imageFromFile.convertToFormat(QImage::Format_ARGB32_Premultiplied); + + // fuzzy comparison must be used, as the pixel values change slightly during conversion + // between QImage::Format_ARGB32 and QImage::Format_ARGB32_Premultiplied, or elsewhere + + // QVERIFY(imageFromHICON == imageFromFile); + compareImages(imageFromHICON, imageFromFile); +} + +#endif // Q_WS_WIN #if defined(Q_WS_S60) Q_DECLARE_METATYPE(TDisplayMode) |