source: trunk/src/gui/image/qpixmap_win.cpp@ 147

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

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

File size: 15.6 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#include "qpixmap.h"
43#include "qpixmap_raster_p.h"
44
45#include "qbitmap.h"
46#include "qimage.h"
47#include "qwidget.h"
48#include "qpainter.h"
49#include "qdatastream.h"
50#include "qbuffer.h"
51#include "qapplication.h"
52#include "qevent.h"
53#include "qfile.h"
54#include "qfileinfo.h"
55#include "qdatetime.h"
56#include "qpixmapcache.h"
57#include "qimagereader.h"
58#include "qimagewriter.h"
59#include "qdebug.h"
60#include "qt_windows.h"
61
62#if defined(Q_OS_WINCE)
63#include <winbase.h>
64#include "qguifunctions_wince.h"
65extern bool qt_wince_is_high_dpi();
66extern bool qt_wince_is_pocket_pc();
67#endif
68
69#ifndef CAPTUREBLT
70#define CAPTUREBLT ((DWORD)0x40000000)
71#endif
72
73QT_BEGIN_NAMESPACE
74
75QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h )
76{
77 RECT r;
78 GetClientRect(winId, &r);
79
80 if (w < 0) w = r.right - r.left;
81 if (h < 0) h = r.bottom - r.top;
82
83#ifdef Q_OS_WINCE_WM
84 if (qt_wince_is_pocket_pc()) {
85 QWidget *widget = QWidget::find(winId);
86 if (qobject_cast<QDesktopWidget *>(widget)) {
87 RECT rect = {0,0,0,0};
88 AdjustWindowRectEx(&rect, WS_BORDER | WS_CAPTION, FALSE, 0);
89 int magicNumber = qt_wince_is_high_dpi() ? 4 : 2;
90 y += rect.top - magicNumber;
91 }
92 }
93#endif
94
95 // Create and setup bitmap
96 HDC display_dc = GetDC(0);
97 HDC bitmap_dc = CreateCompatibleDC(display_dc);
98 HBITMAP bitmap = CreateCompatibleBitmap(display_dc, w, h);
99 HGDIOBJ null_bitmap = SelectObject(bitmap_dc, bitmap);
100
101 // copy data
102 HDC window_dc = GetDC(winId);
103 BitBlt(bitmap_dc, 0, 0, w, h, window_dc, x, y, SRCCOPY
104#ifndef Q_OS_WINCE
105 | CAPTUREBLT
106#endif
107 );
108
109 // clean up all but bitmap
110 ReleaseDC(winId, window_dc);
111 SelectObject(bitmap_dc, null_bitmap);
112 DeleteDC(bitmap_dc);
113
114 QPixmap pixmap = QPixmap::fromWinHBITMAP(bitmap);
115
116 DeleteObject(bitmap);
117 ReleaseDC(0, display_dc);
118
119 return pixmap;
120}
121
122
123
124/*!
125 \enum QPixmap::HBitmapFormat
126
127 This enum defines how the conversion between \c HBITMAP
128 and QPixmap is performed.
129
130 \warning This enum is only available on Windows.
131
132 \value NoAlpha The alpha channel is ignored and always treated as
133 being set to fully opaque. This is preferred if the \c HBITMAP is
134 used with standard GDI calls, such as \c BitBlt().
135
136 \value PremultipliedAlpha The \c HBITMAP is treated as having an
137 alpha channel and premultiplied colors. This is preferred if the
138 \c HBITMAP is accessed through the \c AlphaBlend() GDI function.
139
140 \value Alpha The \c HBITMAP is treated as having a plain alpha
141 channel. This is the preferred format if the \c HBITMAP is going
142 to be used as an application icon or systray icon.
143
144 \sa fromWinHBITMAP(), toWinHBITMAP()
145*/
146
147/*!
148 Creates a \c HBITMAP equivalent to the QPixmap, based on the given
149 \a format. Returns the \c HBITMAP handle.
150
151 It is the caller's responsibility to free the \c HBITMAP data
152 after use.
153
154 \warning This function is only available on Windows.
155
156 \sa fromWinHBITMAP()
157*/
158HBITMAP QPixmap::toWinHBITMAP(HBitmapFormat format) const
159{
160 HBITMAP bitmap = 0;
161 if (data->classId() == QPixmapData::RasterClass) {
162 QRasterPixmapData* d = static_cast<QRasterPixmapData*>(data);
163 int w = d->image.width();
164 int h = d->image.height();
165
166 HDC display_dc = GetDC(0);
167
168 // Define the header
169 BITMAPINFO bmi;
170 memset(&bmi, 0, sizeof(bmi));
171 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
172 bmi.bmiHeader.biWidth = w;
173 bmi.bmiHeader.biHeight = -h;
174 bmi.bmiHeader.biPlanes = 1;
175 bmi.bmiHeader.biBitCount = 32;
176 bmi.bmiHeader.biCompression = BI_RGB;
177 bmi.bmiHeader.biSizeImage = w * h * 4;
178
179 // Create the pixmap
180 uchar *pixels = 0;
181 bitmap = CreateDIBSection(display_dc, &bmi, DIB_RGB_COLORS, (void **) &pixels, 0, 0);
182 ReleaseDC(0, display_dc);
183 if (!bitmap) {
184 qErrnoWarning("QPixmap::toWinHBITMAP(), failed to create dibsection");
185 return 0;
186 }
187 if (!pixels) {
188 qErrnoWarning("QPixmap::toWinHBITMAP(), did not allocate pixel data");
189 return 0;
190 }
191
192 // Copy over the data
193 QImage::Format imageFormat = QImage::Format_ARGB32;
194 if (format == NoAlpha)
195 imageFormat = QImage::Format_RGB32;
196 else if (format == PremultipliedAlpha)
197 imageFormat = QImage::Format_ARGB32_Premultiplied;
198 const QImage image = d->image.convertToFormat(imageFormat);
199 int bytes_per_line = w * 4;
200 for (int y=0; y<h; ++y)
201 memcpy(pixels + y * bytes_per_line, image.scanLine(y), bytes_per_line);
202
203 } else {
204 QPixmapData *data = new QRasterPixmapData(depth() == 1 ?
205 QPixmapData::BitmapType : QPixmapData::PixmapType);
206 data->fromImage(toImage(), Qt::AutoColor);
207 return QPixmap(data).toWinHBITMAP(format);
208 }
209 return bitmap;
210}
211
212/*!
213 Returns a QPixmap that is equivalent to the given \a bitmap. The
214 conversion is based on the specified \a format.
215
216 \warning This function is only available on Windows.
217
218 \sa toWinHBITMAP(), {QPixmap#Pixmap Conversion}{Pixmap Conversion}
219
220*/
221QPixmap QPixmap::fromWinHBITMAP(HBITMAP bitmap, HBitmapFormat format)
222{
223 // Verify size
224 BITMAP bitmap_info;
225 memset(&bitmap_info, 0, sizeof(BITMAP));
226
227 int res;
228 QT_WA({
229 res = GetObjectW(bitmap, sizeof(BITMAP), &bitmap_info);
230 } , {
231 res = GetObjectA(bitmap, sizeof(BITMAP), &bitmap_info);
232 });
233
234 if (!res) {
235 qErrnoWarning("QPixmap::fromWinHBITMAP(), failed to get bitmap info");
236 return QPixmap();
237 }
238 int w = bitmap_info.bmWidth;
239 int h = bitmap_info.bmHeight;
240
241 BITMAPINFO bmi;
242 memset(&bmi, 0, sizeof(bmi));
243 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
244 bmi.bmiHeader.biWidth = w;
245 bmi.bmiHeader.biHeight = -h;
246 bmi.bmiHeader.biPlanes = 1;
247 bmi.bmiHeader.biBitCount = 32;
248 bmi.bmiHeader.biCompression = BI_RGB;
249 bmi.bmiHeader.biSizeImage = w * h * 4;
250
251 QImage result;
252 // Get bitmap bits
253 uchar *data = (uchar *) qMalloc(bmi.bmiHeader.biSizeImage);
254
255 HDC display_dc = GetDC(0);
256 if (GetDIBits(display_dc, bitmap, 0, h, data, &bmi, DIB_RGB_COLORS)) {
257
258 QImage::Format imageFormat = QImage::Format_ARGB32_Premultiplied;
259 uint mask = 0;
260 if (format == NoAlpha) {
261 imageFormat = QImage::Format_RGB32;
262 mask = 0xff000000;
263 }
264
265 // Create image and copy data into image.
266 QImage image(w, h, imageFormat);
267 if (!image.isNull()) { // failed to alloc?
268 int bytes_per_line = w * sizeof(QRgb);
269 for (int y=0; y<h; ++y) {
270 QRgb *dest = (QRgb *) image.scanLine(y);
271 const QRgb *src = (const QRgb *) (data + y * bytes_per_line);
272 for (int x=0; x<w; ++x) {
273 const uint pixel = src[x];
274 if ((pixel & 0xff000000) == 0 && (pixel & 0x00ffffff) != 0)
275 dest[x] = pixel | 0xff000000;
276 else
277 dest[x] = pixel | mask;
278 }
279 }
280 }
281 result = image;
282 } else {
283 qWarning("QPixmap::fromWinHBITMAP(), failed to get bitmap bits");
284 }
285 ReleaseDC(0, display_dc);
286 qFree(data);
287 return fromImage(result);
288}
289
290#ifdef Q_WS_WIN
291#ifndef Q_OS_WINCE
292
293static QImage qt_fromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
294{
295 BITMAPINFO bmi;
296 memset(&bmi, 0, sizeof(bmi));
297 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
298 bmi.bmiHeader.biWidth = w;
299 bmi.bmiHeader.biHeight = -h;
300 bmi.bmiHeader.biPlanes = 1;
301 bmi.bmiHeader.biBitCount = 32;
302 bmi.bmiHeader.biCompression = BI_RGB;
303 bmi.bmiHeader.biSizeImage = w * h * 4;
304
305 QImage image(w, h, QImage::Format_ARGB32_Premultiplied);
306 if (image.isNull())
307 return image;
308
309 // Get bitmap bits
310 uchar *data = (uchar *) qMalloc(bmi.bmiHeader.biSizeImage);
311
312 if (GetDIBits(hdc, bitmap, 0, h, data, &bmi, DIB_RGB_COLORS)) {
313 // Create image and copy data into image.
314 for (int y=0; y<h; ++y) {
315 void *dest = (void *) image.scanLine(y);
316 void *src = data + y * image.bytesPerLine();
317 memcpy(dest, src, image.bytesPerLine());
318 }
319 } else {
320 qWarning("qt_fromWinHBITMAP(), failed to get bitmap bits");
321 }
322
323 return image;
324}
325
326QPixmap convertHIconToPixmap( const HICON icon)
327{
328 bool foundAlpha = false;
329 HDC screenDevice = GetDC(0);
330 HDC hdc = CreateCompatibleDC(screenDevice);
331 ReleaseDC(0, screenDevice);
332
333 ICONINFO iconinfo;
334 bool result = GetIconInfo(icon, &iconinfo); //x and y Hotspot describes the icon center
335 if (!result)
336 qWarning("convertHIconToPixmap(), failed to GetIconInfo()");
337
338 int w = iconinfo.xHotspot * 2;
339 int h = iconinfo.yHotspot * 2;
340
341 BITMAPINFOHEADER bitmapInfo;
342 bitmapInfo.biSize = sizeof(BITMAPINFOHEADER);
343 bitmapInfo.biWidth = w;
344 bitmapInfo.biHeight = h;
345 bitmapInfo.biPlanes = 1;
346 bitmapInfo.biBitCount = 32;
347 bitmapInfo.biCompression = BI_RGB;
348 bitmapInfo.biSizeImage = 0;
349 bitmapInfo.biXPelsPerMeter = 0;
350 bitmapInfo.biYPelsPerMeter = 0;
351 bitmapInfo.biClrUsed = 0;
352 bitmapInfo.biClrImportant = 0;
353 DWORD* bits;
354
355 HBITMAP winBitmap = CreateDIBSection(hdc, (BITMAPINFO*)&bitmapInfo, DIB_RGB_COLORS, (VOID**)&bits, NULL, 0);
356 HGDIOBJ oldhdc = (HBITMAP)SelectObject(hdc, winBitmap);
357 DrawIconEx( hdc, 0, 0, icon, iconinfo.xHotspot * 2, iconinfo.yHotspot * 2, 0, 0, DI_NORMAL);
358 QImage image = qt_fromWinHBITMAP(hdc, winBitmap, w, h);
359
360 for (int y = 0 ; y < h && !foundAlpha ; y++) {
361 QRgb *scanLine= reinterpret_cast<QRgb *>(image.scanLine(y));
362 for (int x = 0; x < w ; x++) {
363 if (qAlpha(scanLine[x]) != 0) {
364 foundAlpha = true;
365 break;
366 }
367 }
368 }
369 if (!foundAlpha) {
370 //If no alpha was found, we use the mask to set alpha values
371 DrawIconEx( hdc, 0, 0, icon, w, h, 0, 0, DI_MASK);
372 QImage mask = qt_fromWinHBITMAP(hdc, winBitmap, w, h);
373
374 for (int y = 0 ; y < h ; y++){
375 QRgb *scanlineImage = reinterpret_cast<QRgb *>(image.scanLine(y));
376 QRgb *scanlineMask = mask.isNull() ? 0 : reinterpret_cast<QRgb *>(mask.scanLine(y));
377 for (int x = 0; x < w ; x++){
378 if (scanlineMask && qRed(scanlineMask[x]) != 0)
379 scanlineImage[x] = 0; //mask out this pixel
380 else
381 scanlineImage[x] |= 0xff000000; // set the alpha channel to 255
382 }
383 }
384 }
385 //dispose resources created by iconinfo call
386 DeleteObject(iconinfo.hbmMask);
387 DeleteObject(iconinfo.hbmColor);
388
389 SelectObject(hdc, oldhdc); //restore state
390 DeleteObject(winBitmap);
391 DeleteDC(hdc);
392 return QPixmap::fromImage(image);
393}
394#else //ifndef Q_OS_WINCE
395QPixmap convertHIconToPixmap( const HICON icon, bool large)
396{
397 HDC screenDevice = GetDC(0);
398 HDC hdc = CreateCompatibleDC(screenDevice);
399 ReleaseDC(0, screenDevice);
400
401 int size = large ? 64 : 32;
402
403 BITMAPINFO bmi;
404 memset(&bmi, 0, sizeof(bmi));
405 bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
406 bmi.bmiHeader.biWidth = size;
407 bmi.bmiHeader.biHeight = -size;
408 bmi.bmiHeader.biPlanes = 1;
409 bmi.bmiHeader.biBitCount = 32;
410 bmi.bmiHeader.biCompression = BI_RGB;
411 bmi.bmiHeader.biSizeImage = size*size*4;
412
413 uchar* bits;
414
415 HBITMAP winBitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**) &bits, 0, 0);
416 if (winBitmap )
417 memset(bits, 0xff, size*size*4);
418 if (!winBitmap) {
419 qWarning("convertHIconToPixmap(), failed to CreateDIBSection()");
420 return QPixmap();
421 }
422
423 HGDIOBJ oldhdc = (HBITMAP)SelectObject(hdc, winBitmap);
424 if (!DrawIconEx( hdc, 0, 0, icon, size, size, 0, 0, DI_NORMAL))
425 qWarning("convertHIconToPixmap(), failed to DrawIcon()");
426
427 uint mask = 0xff000000;
428 // Create image and copy data into image.
429 QImage image(size, size, QImage::Format_ARGB32);
430
431 if (!image.isNull()) { // failed to alloc?
432 int bytes_per_line = size * sizeof(QRgb);
433 for (int y=0; y<size; ++y) {
434 QRgb *dest = (QRgb *) image.scanLine(y);
435 const QRgb *src = (const QRgb *) (bits + y * bytes_per_line);
436 for (int x=0; x<size; ++x) {
437 dest[x] = src[x];
438 }
439 }
440 }
441 if (!DrawIconEx( hdc, 0, 0, icon, size, size, 0, 0, DI_MASK))
442 qWarning("convertHIconToPixmap(), failed to DrawIcon()");
443 if (!image.isNull()) { // failed to alloc?
444 int bytes_per_line = size * sizeof(QRgb);
445 for (int y=0; y<size; ++y) {
446 QRgb *dest = (QRgb *) image.scanLine(y);
447 const QRgb *src = (const QRgb *) (bits + y * bytes_per_line);
448 for (int x=0; x<size; ++x) {
449 if (!src[x])
450 dest[x] = dest[x] | mask;
451 }
452 }
453 }
454 SelectObject(hdc, oldhdc); //restore state
455 DeleteObject(winBitmap);
456 DeleteDC(hdc);
457 return QPixmap::fromImage(image);
458}
459#endif //ifndef Q_OS_WINCE
460
461QPixmap loadIconFromShell32( int resourceId, int size )
462{
463#ifdef Q_OS_WINCE
464 HMODULE hmod = LoadLibrary((const wchar_t *) QString::fromLatin1("ceshell.dll").utf16());
465#else
466 HMODULE hmod = LoadLibraryA("shell32.dll");
467#endif
468 if( hmod ) {
469 HICON iconHandle = (HICON)LoadImage(hmod, MAKEINTRESOURCE(resourceId), IMAGE_ICON, size, size, 0);
470 if( iconHandle ) {
471 QPixmap iconpixmap = convertHIconToPixmap( iconHandle );
472 DestroyIcon(iconHandle);
473 return iconpixmap;
474 }
475 }
476 return QPixmap();
477}
478
479#endif
480
481QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.