Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/comctl32/imagelist.c
8713 views
1
/*
2
* ImageList implementation
3
*
4
* Copyright 1998 Eric Kohl
5
* Copyright 2000 Jason Mawdsley
6
* Copyright 2001, 2004 Michael Stefaniuc
7
* Copyright 2001 Charles Loep for CodeWeavers
8
* Copyright 2002 Dimitrie O. Paun
9
* Copyright 2009 Owen Rudge for CodeWeavers
10
*
11
* This library is free software; you can redistribute it and/or
12
* modify it under the terms of the GNU Lesser General Public
13
* License as published by the Free Software Foundation; either
14
* version 2.1 of the License, or (at your option) any later version.
15
*
16
* This library is distributed in the hope that it will be useful,
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19
* Lesser General Public License for more details.
20
*
21
* You should have received a copy of the GNU Lesser General Public
22
* License along with this library; if not, write to the Free Software
23
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24
*
25
* TODO:
26
* - Add support for ILD_SCALE, ILD_DPISCALE
27
* - Add support for ILS_GLOW, ILS_SHADOW
28
* - Thread-safe locking
29
*/
30
31
#include <stdarg.h>
32
#include <stdlib.h>
33
#include <string.h>
34
35
#define COBJMACROS
36
37
#include "winerror.h"
38
#include "windef.h"
39
#include "winbase.h"
40
#include "objbase.h"
41
#include "wingdi.h"
42
#include "winuser.h"
43
#include "commctrl.h"
44
#include "comctl32.h"
45
#include "commoncontrols.h"
46
#include "wine/debug.h"
47
#include "wine/exception.h"
48
49
WINE_DEFAULT_DEBUG_CHANNEL(imagelist);
50
51
#define MAX_OVERLAYIMAGE 15
52
53
struct _IMAGELIST
54
{
55
IImageList2 IImageList2_iface; /* 00: IImageList vtable */
56
INT cCurImage; /* 04: ImageCount */
57
INT cMaxImage; /* 08: maximages */
58
INT cGrow; /* 0C: cGrow */
59
INT cx; /* 10: cx */
60
INT cy; /* 14: cy */
61
DWORD x4;
62
UINT flags; /* 1C: flags */
63
COLORREF clrFg; /* 20: foreground color */
64
COLORREF clrBk; /* 24: background color */
65
66
67
HBITMAP hbmImage; /* 28: images Bitmap */
68
HBITMAP hbmMask; /* 2C: masks Bitmap */
69
HDC hdcImage; /* 30: images MemDC */
70
HDC hdcMask; /* 34: masks MemDC */
71
INT nOvlIdx[MAX_OVERLAYIMAGE]; /* 38: overlay images index */
72
73
/* not yet found out */
74
DWORD magic;
75
HBRUSH hbrBlend25;
76
HBRUSH hbrBlend50;
77
INT cInitial;
78
UINT uBitsPixel;
79
DWORD *item_flags;
80
BOOL color_table_set;
81
82
LONG ref; /* reference count */
83
};
84
85
#define IMAGELIST_MAGIC 0x53414D58
86
87
/* Header used by ImageList_Read() and ImageList_Write() */
88
#pragma pack(push,2)
89
typedef struct _ILHEAD
90
{
91
USHORT usMagic;
92
USHORT usVersion;
93
WORD cCurImage;
94
WORD cMaxImage;
95
WORD cGrow;
96
WORD cx;
97
WORD cy;
98
COLORREF bkcolor;
99
WORD flags;
100
SHORT ovls[4];
101
} ILHEAD;
102
#pragma pack(pop)
103
104
/* internal image list data used for Drag & Drop operations */
105
typedef struct
106
{
107
HWND hwnd;
108
HIMAGELIST himl;
109
HIMAGELIST himlNoCursor;
110
/* position of the drag image relative to the window */
111
INT x;
112
INT y;
113
/* offset of the hotspot relative to the origin of the image */
114
INT dxHotspot;
115
INT dyHotspot;
116
/* is the drag image visible */
117
BOOL bShow;
118
/* saved background */
119
HBITMAP hbmBg;
120
} INTERNALDRAG;
121
122
static INTERNALDRAG InternalDrag = { 0, 0, 0, 0, 0, 0, 0, FALSE, 0 };
123
124
static inline HIMAGELIST impl_from_IImageList2(IImageList2 *iface)
125
{
126
return CONTAINING_RECORD(iface, struct _IMAGELIST, IImageList2_iface);
127
}
128
129
static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT count);
130
static HRESULT ImageListImpl_CreateInstance(const IUnknown *pUnkOuter, REFIID iid, void** ppv);
131
static BOOL is_valid(HIMAGELIST himl);
132
133
/*
134
* An imagelist with N images is tiled like this:
135
*
136
* N/4 ->
137
*
138
* 4 048C..
139
* 159D..
140
* | 26AE.N
141
* V 37BF.
142
*/
143
144
#define TILE_COUNT 4
145
146
BOOL imagelist_has_alpha( HIMAGELIST himl, UINT index )
147
{
148
return himl->item_flags[index] & ILIF_ALPHA;
149
}
150
151
static inline UINT imagelist_height( UINT count )
152
{
153
return ((count + TILE_COUNT - 1)/TILE_COUNT);
154
}
155
156
static inline void imagelist_point_from_index( HIMAGELIST himl, UINT index, LPPOINT pt )
157
{
158
pt->x = (index%TILE_COUNT) * himl->cx;
159
pt->y = (index/TILE_COUNT) * himl->cy;
160
}
161
162
static inline void imagelist_get_bitmap_size( HIMAGELIST himl, UINT count, SIZE *sz )
163
{
164
sz->cx = himl->cx * TILE_COUNT;
165
sz->cy = imagelist_height( count ) * himl->cy;
166
}
167
168
static inline int get_dib_stride( int width, int bpp )
169
{
170
return ((width * bpp + 31) >> 3) & ~3;
171
}
172
173
static inline int get_dib_image_size( const BITMAPINFO *info )
174
{
175
return get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount )
176
* abs( info->bmiHeader.biHeight );
177
}
178
179
/*
180
* imagelist_copy_images()
181
*
182
* Copies a block of count images from offset src in the list to offset dest.
183
* Images are copied a row at at time. Assumes hdcSrc and hdcDest are different.
184
*/
185
static inline void imagelist_copy_images( HIMAGELIST himl, HDC hdcSrc, HDC hdcDest,
186
UINT src, UINT count, UINT dest )
187
{
188
POINT ptSrc, ptDest;
189
SIZE sz;
190
UINT i;
191
192
for ( i=0; i<TILE_COUNT; i++ )
193
{
194
imagelist_point_from_index( himl, src+i, &ptSrc );
195
imagelist_point_from_index( himl, dest+i, &ptDest );
196
sz.cx = himl->cx;
197
sz.cy = himl->cy * imagelist_height( count - i );
198
199
BitBlt( hdcDest, ptDest.x, ptDest.y, sz.cx, sz.cy,
200
hdcSrc, ptSrc.x, ptSrc.y, SRCCOPY );
201
}
202
}
203
204
static void add_dib_bits( HIMAGELIST himl, int pos, int count, int width, int height,
205
BITMAPINFO *info, BITMAPINFO *mask_info, DWORD *bits, BYTE *mask_bits )
206
{
207
int i, j, n;
208
POINT pt;
209
int stride = info->bmiHeader.biWidth;
210
int mask_stride = (info->bmiHeader.biWidth + 31) / 32 * 4;
211
212
for (n = 0; n < count; n++)
213
{
214
BOOL has_alpha = FALSE;
215
216
imagelist_point_from_index( himl, pos + n, &pt );
217
218
/* check if bitmap has an alpha channel */
219
for (i = 0; i < height && !has_alpha; i++)
220
for (j = n * width; j < (n + 1) * width; j++)
221
if ((has_alpha = ((bits[i * stride + j] & 0xff000000) != 0))) break;
222
223
if (has_alpha)
224
{
225
himl->item_flags[pos + n] = ILIF_ALPHA;
226
227
if (mask_info && himl->hbmMask) /* generate the mask from the alpha channel */
228
{
229
for (i = 0; i < height; i++)
230
for (j = n * width; j < (n + 1) * width; j++)
231
if ((bits[i * stride + j] >> 24) > 25) /* more than 10% alpha */
232
mask_bits[i * mask_stride + j / 8] &= ~(0x80 >> (j % 8));
233
else
234
mask_bits[i * mask_stride + j / 8] |= 0x80 >> (j % 8);
235
}
236
}
237
else if (mask_info) /* mask out the background */
238
{
239
for (i = 0; i < height; i++)
240
for (j = n * width; j < (n + 1) * width; j++)
241
if ((mask_bits[i * mask_stride + j / 8] << (j % 8)) & 0x80)
242
bits[i * stride + j] = 0;
243
}
244
StretchDIBits( himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy,
245
n * width, 0, width, height, bits, info, DIB_RGB_COLORS, SRCCOPY );
246
if (mask_info)
247
StretchDIBits( himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy,
248
n * width, 0, width, height, mask_bits, mask_info, DIB_RGB_COLORS, SRCCOPY );
249
}
250
}
251
252
/* add images with an alpha channel when the image list is 32 bpp */
253
static BOOL add_with_alpha( HIMAGELIST himl, HDC hdc, int pos, int count,
254
int width, int height, HBITMAP hbmImage, HBITMAP hbmMask )
255
{
256
BOOL ret = FALSE;
257
BITMAP bm;
258
BITMAPINFO *info, *mask_info = NULL;
259
DWORD *bits = NULL;
260
BYTE *mask_bits = NULL;
261
DWORD mask_width;
262
263
if (!GetObjectW( hbmImage, sizeof(bm), &bm )) return FALSE;
264
265
/* if either the imagelist or the source bitmap don't have an alpha channel, bail out now */
266
if ((himl->flags & 0xfe) != ILC_COLOR32) return FALSE;
267
if (bm.bmBitsPixel != 32) return FALSE;
268
269
SelectObject( hdc, hbmImage );
270
mask_width = (bm.bmWidth + 31) / 32 * 4;
271
272
if (!(info = Alloc( FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done;
273
info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
274
info->bmiHeader.biWidth = bm.bmWidth;
275
info->bmiHeader.biHeight = -height;
276
info->bmiHeader.biPlanes = 1;
277
info->bmiHeader.biBitCount = 32;
278
info->bmiHeader.biCompression = BI_RGB;
279
info->bmiHeader.biSizeImage = bm.bmWidth * height * 4;
280
info->bmiHeader.biXPelsPerMeter = 0;
281
info->bmiHeader.biYPelsPerMeter = 0;
282
info->bmiHeader.biClrUsed = 0;
283
info->bmiHeader.biClrImportant = 0;
284
if (!(bits = Alloc( info->bmiHeader.biSizeImage ))) goto done;
285
if (!GetDIBits( hdc, hbmImage, 0, height, bits, info, DIB_RGB_COLORS )) goto done;
286
287
if (hbmMask)
288
{
289
if (!(mask_info = Alloc( FIELD_OFFSET( BITMAPINFO, bmiColors[2] ))))
290
goto done;
291
mask_info->bmiHeader = info->bmiHeader;
292
mask_info->bmiHeader.biBitCount = 1;
293
mask_info->bmiHeader.biSizeImage = mask_width * height;
294
if (!(mask_bits = Alloc( mask_info->bmiHeader.biSizeImage )))
295
goto done;
296
if (!GetDIBits( hdc, hbmMask, 0, height, mask_bits, mask_info, DIB_RGB_COLORS )) goto done;
297
}
298
299
add_dib_bits( himl, pos, count, width, height, info, mask_info, bits, mask_bits );
300
ret = TRUE;
301
302
done:
303
Free( info );
304
Free( mask_info );
305
Free( bits );
306
Free( mask_bits );
307
return ret;
308
}
309
310
UINT WINAPI
311
ImageList_SetColorTable(HIMAGELIST himl, UINT uStartIndex, UINT cEntries, const RGBQUAD *prgb);
312
313
/*************************************************************************
314
* IMAGELIST_InternalExpandBitmaps [Internal]
315
*
316
* Expands the bitmaps of an image list by the given number of images.
317
*
318
* PARAMS
319
* himl [I] handle to image list
320
* nImageCount [I] number of images to add
321
*
322
* RETURNS
323
* nothing
324
*
325
* NOTES
326
* This function CANNOT be used to reduce the number of images.
327
*/
328
static void
329
IMAGELIST_InternalExpandBitmaps(HIMAGELIST himl, INT nImageCount)
330
{
331
HDC hdcBitmap;
332
HBITMAP hbmNewBitmap, hbmNull;
333
INT nNewCount;
334
SIZE sz;
335
336
TRACE("%p has allocated %d, max %d, grow %d images\n", himl, himl->cCurImage, himl->cMaxImage, himl->cGrow);
337
338
if (himl->cCurImage + nImageCount < himl->cMaxImage)
339
return;
340
341
nNewCount = himl->cMaxImage + max(nImageCount, himl->cGrow) + 1;
342
343
imagelist_get_bitmap_size(himl, nNewCount, &sz);
344
345
TRACE("Create expanded bitmaps : himl=%p x=%ld y=%ld count=%d\n", himl, sz.cx, sz.cy, nNewCount);
346
hdcBitmap = CreateCompatibleDC (0);
347
348
hbmNewBitmap = ImageList_CreateImage(hdcBitmap, himl, nNewCount);
349
350
if (hbmNewBitmap == 0)
351
ERR("creating new image bitmap (x=%ld y=%ld)!\n", sz.cx, sz.cy);
352
353
if (himl->cCurImage)
354
{
355
hbmNull = SelectObject (hdcBitmap, hbmNewBitmap);
356
BitBlt (hdcBitmap, 0, 0, sz.cx, sz.cy,
357
himl->hdcImage, 0, 0, SRCCOPY);
358
SelectObject (hdcBitmap, hbmNull);
359
}
360
SelectObject (himl->hdcImage, hbmNewBitmap);
361
DeleteObject (himl->hbmImage);
362
himl->hbmImage = hbmNewBitmap;
363
364
if (himl->flags & ILC_MASK)
365
{
366
hbmNewBitmap = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
367
368
if (hbmNewBitmap == 0)
369
ERR("creating new mask bitmap!\n");
370
371
if(himl->cCurImage)
372
{
373
hbmNull = SelectObject (hdcBitmap, hbmNewBitmap);
374
BitBlt (hdcBitmap, 0, 0, sz.cx, sz.cy,
375
himl->hdcMask, 0, 0, SRCCOPY);
376
SelectObject (hdcBitmap, hbmNull);
377
}
378
SelectObject (himl->hdcMask, hbmNewBitmap);
379
DeleteObject (himl->hbmMask);
380
himl->hbmMask = hbmNewBitmap;
381
}
382
383
himl->item_flags = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, himl->item_flags,
384
nNewCount * sizeof(*himl->item_flags));
385
himl->cMaxImage = nNewCount;
386
387
DeleteDC (hdcBitmap);
388
}
389
390
391
/*************************************************************************
392
* ImageList_Add [COMCTL32.@]
393
*
394
* Add an image or images to an image list.
395
*
396
* PARAMS
397
* himl [I] handle to image list
398
* hbmImage [I] handle to image bitmap
399
* hbmMask [I] handle to mask bitmap
400
*
401
* RETURNS
402
* Success: Index of the first new image.
403
* Failure: -1
404
*/
405
406
INT WINAPI
407
ImageList_Add (HIMAGELIST himl, HBITMAP hbmImage, HBITMAP hbmMask)
408
{
409
HDC hdcBitmap, hdcTemp = 0;
410
INT nFirstIndex, nImageCount, i;
411
BITMAP bmp;
412
POINT pt;
413
414
TRACE("himl=%p hbmimage=%p hbmmask=%p\n", himl, hbmImage, hbmMask);
415
if (!is_valid(himl))
416
return -1;
417
418
if (!GetObjectW(hbmImage, sizeof(BITMAP), &bmp))
419
return -1;
420
421
TRACE("himl %p, cCurImage %d, cMaxImage %d, cGrow %d, cx %d, cy %d\n",
422
himl, himl->cCurImage, himl->cMaxImage, himl->cGrow, himl->cx, himl->cy);
423
424
nImageCount = bmp.bmWidth / himl->cx;
425
426
TRACE("%p has %d images (%d x %d) bpp %d\n", hbmImage, nImageCount, bmp.bmWidth, bmp.bmHeight,
427
bmp.bmBitsPixel);
428
429
IMAGELIST_InternalExpandBitmaps(himl, nImageCount);
430
431
hdcBitmap = CreateCompatibleDC(0);
432
433
SelectObject(hdcBitmap, hbmImage);
434
435
if (add_with_alpha( himl, hdcBitmap, himl->cCurImage, nImageCount,
436
himl->cx, min( himl->cy, bmp.bmHeight), hbmImage, hbmMask ))
437
goto done;
438
439
if (himl->hbmMask)
440
{
441
hdcTemp = CreateCompatibleDC(0);
442
SelectObject(hdcTemp, hbmMask);
443
}
444
445
if (himl->uBitsPixel <= 8 && bmp.bmBitsPixel <= 8 &&
446
!himl->color_table_set && himl->cCurImage == 0)
447
{
448
RGBQUAD colors[256];
449
UINT num = GetDIBColorTable( hdcBitmap, 0, 1 << bmp.bmBitsPixel, colors );
450
if (num) ImageList_SetColorTable( himl, 0, num, colors );
451
}
452
453
for (i=0; i<nImageCount; i++)
454
{
455
imagelist_point_from_index( himl, himl->cCurImage + i, &pt );
456
457
/* Copy result to the imagelist
458
*/
459
BitBlt( himl->hdcImage, pt.x, pt.y, himl->cx, bmp.bmHeight,
460
hdcBitmap, i*himl->cx, 0, SRCCOPY );
461
462
if (!himl->hbmMask)
463
continue;
464
465
BitBlt( himl->hdcMask, pt.x, pt.y, himl->cx, bmp.bmHeight,
466
hdcTemp, i*himl->cx, 0, SRCCOPY );
467
468
/* Remove the background from the image
469
*/
470
BitBlt( himl->hdcImage, pt.x, pt.y, himl->cx, bmp.bmHeight,
471
himl->hdcMask, pt.x, pt.y, 0x220326 ); /* NOTSRCAND */
472
}
473
if (hdcTemp) DeleteDC(hdcTemp);
474
475
done:
476
DeleteDC(hdcBitmap);
477
478
nFirstIndex = himl->cCurImage;
479
himl->cCurImage += nImageCount;
480
481
return nFirstIndex;
482
}
483
484
485
/*************************************************************************
486
* ImageList_AddIcon [COMCTL32.@]
487
*
488
* Adds an icon to an image list.
489
*
490
* PARAMS
491
* himl [I] handle to image list
492
* hIcon [I] handle to icon
493
*
494
* RETURNS
495
* Success: index of the new image
496
* Failure: -1
497
*/
498
#undef ImageList_AddIcon
499
INT WINAPI ImageList_AddIcon (HIMAGELIST himl, HICON hIcon)
500
{
501
return ImageList_ReplaceIcon (himl, -1, hIcon);
502
}
503
504
505
/*************************************************************************
506
* ImageList_AddMasked [COMCTL32.@]
507
*
508
* Adds an image or images to an image list and creates a mask from the
509
* specified bitmap using the mask color.
510
*
511
* PARAMS
512
* himl [I] handle to image list.
513
* hBitmap [I] handle to bitmap
514
* clrMask [I] mask color.
515
*
516
* RETURNS
517
* Success: Index of the first new image.
518
* Failure: -1
519
*/
520
521
INT WINAPI
522
ImageList_AddMasked (HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
523
{
524
HDC hdcMask, hdcBitmap;
525
INT ret;
526
BITMAP bmp;
527
HBITMAP hMaskBitmap;
528
COLORREF bkColor;
529
530
TRACE("himl %p, hbitmap %p, clrmask %#lx\n", himl, hBitmap, clrMask);
531
532
if (!is_valid(himl))
533
return -1;
534
535
if (!GetObjectW(hBitmap, sizeof(BITMAP), &bmp))
536
return -1;
537
538
hdcBitmap = CreateCompatibleDC(0);
539
SelectObject(hdcBitmap, hBitmap);
540
541
/* Create a temp Mask so we can remove the background of the Image */
542
hdcMask = CreateCompatibleDC(0);
543
hMaskBitmap = CreateBitmap(bmp.bmWidth, bmp.bmHeight, 1, 1, NULL);
544
SelectObject(hdcMask, hMaskBitmap);
545
546
/* create monochrome image to the mask bitmap */
547
bkColor = (clrMask != CLR_DEFAULT) ? clrMask : GetPixel (hdcBitmap, 0, 0);
548
SetBkColor (hdcBitmap, bkColor);
549
BitBlt (hdcMask, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcBitmap, 0, 0, SRCCOPY);
550
551
/*
552
* Remove the background from the image
553
*
554
* WINDOWS BUG ALERT!!!!!!
555
* The statement below should not be done in common practice
556
* but this is how ImageList_AddMasked works in Windows.
557
* It overwrites the original bitmap passed, this was discovered
558
* by using the same bitmap to iterate the different styles
559
* on windows where it failed (BUT ImageList_Add is OK)
560
* This is here in case some apps rely on this bug
561
*
562
* Blt mode 0x220326 is NOTSRCAND
563
*/
564
if (bmp.bmBitsPixel > 8) /* NOTSRCAND can't work with palettes */
565
{
566
SetBkColor(hdcBitmap, RGB(255,255,255));
567
BitBlt(hdcBitmap, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcMask, 0, 0, 0x220326);
568
}
569
570
DeleteDC(hdcBitmap);
571
DeleteDC(hdcMask);
572
573
ret = ImageList_Add( himl, hBitmap, hMaskBitmap );
574
575
DeleteObject(hMaskBitmap);
576
return ret;
577
}
578
579
580
/*************************************************************************
581
* ImageList_BeginDrag [COMCTL32.@]
582
*
583
* Creates a temporary image list that contains one image. It will be used
584
* as a drag image.
585
*
586
* PARAMS
587
* himlTrack [I] handle to the source image list
588
* iTrack [I] index of the drag image in the source image list
589
* dxHotspot [I] X position of the hot spot of the drag image
590
* dyHotspot [I] Y position of the hot spot of the drag image
591
*
592
* RETURNS
593
* Success: TRUE
594
* Failure: FALSE
595
*/
596
597
BOOL WINAPI
598
ImageList_BeginDrag (HIMAGELIST himlTrack, INT iTrack,
599
INT dxHotspot, INT dyHotspot)
600
{
601
INT cx, cy;
602
POINT src, dst;
603
604
TRACE("(himlTrack=%p iTrack=%d dx=%d dy=%d)\n", himlTrack, iTrack,
605
dxHotspot, dyHotspot);
606
607
if (!is_valid(himlTrack))
608
return FALSE;
609
610
if (iTrack >= himlTrack->cCurImage)
611
return FALSE;
612
613
if (InternalDrag.himl)
614
return FALSE;
615
616
cx = himlTrack->cx;
617
cy = himlTrack->cy;
618
619
InternalDrag.himlNoCursor = InternalDrag.himl = ImageList_Create (cx, cy, himlTrack->flags, 1, 1);
620
if (InternalDrag.himl == NULL) {
621
WARN("Error creating drag image list!\n");
622
return FALSE;
623
}
624
625
InternalDrag.dxHotspot = dxHotspot;
626
InternalDrag.dyHotspot = dyHotspot;
627
628
/* copy image */
629
imagelist_point_from_index(InternalDrag.himl, 0, &dst);
630
imagelist_point_from_index(himlTrack, iTrack, &src);
631
BitBlt(InternalDrag.himl->hdcImage, dst.x, dst.y, cx, cy, himlTrack->hdcImage, src.x, src.y,
632
SRCCOPY);
633
BitBlt(InternalDrag.himl->hdcMask, dst.x, dst.y, cx, cy, himlTrack->hdcMask, src.x, src.y,
634
SRCCOPY);
635
636
InternalDrag.himl->cCurImage = 1;
637
638
return TRUE;
639
}
640
641
642
/*************************************************************************
643
* ImageList_Copy [COMCTL32.@]
644
*
645
* Copies an image of the source image list to an image of the
646
* destination image list. Images can be copied or swapped.
647
*
648
* PARAMS
649
* himlDst [I] handle to the destination image list
650
* iDst [I] destination image index.
651
* himlSrc [I] handle to the source image list
652
* iSrc [I] source image index
653
* uFlags [I] flags for the copy operation
654
*
655
* RETURNS
656
* Success: TRUE
657
* Failure: FALSE
658
*
659
* NOTES
660
* Copying from one image list to another is possible. The original
661
* implementation just copies or swaps within one image list.
662
* Could this feature become a bug??? ;-)
663
*/
664
665
BOOL WINAPI
666
ImageList_Copy (HIMAGELIST himlDst, INT iDst, HIMAGELIST himlSrc,
667
INT iSrc, UINT uFlags)
668
{
669
POINT ptSrc, ptDst;
670
671
TRACE("himlDst=%p iDst=%d himlSrc=%p iSrc=%d\n", himlDst, iDst, himlSrc, iSrc);
672
673
if (!is_valid(himlSrc) || !is_valid(himlDst))
674
return FALSE;
675
if ((iDst < 0) || (iDst >= himlDst->cCurImage))
676
return FALSE;
677
if ((iSrc < 0) || (iSrc >= himlSrc->cCurImage))
678
return FALSE;
679
680
imagelist_point_from_index( himlDst, iDst, &ptDst );
681
imagelist_point_from_index( himlSrc, iSrc, &ptSrc );
682
683
if (uFlags & ILCF_SWAP) {
684
/* swap */
685
HDC hdcBmp;
686
HBITMAP hbmTempImage, hbmTempMask;
687
688
hdcBmp = CreateCompatibleDC (0);
689
690
/* create temporary bitmaps */
691
hbmTempImage = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
692
himlSrc->uBitsPixel, NULL);
693
hbmTempMask = CreateBitmap (himlSrc->cx, himlSrc->cy, 1,
694
1, NULL);
695
696
/* copy (and stretch) destination to temporary bitmaps.(save) */
697
/* image */
698
SelectObject (hdcBmp, hbmTempImage);
699
StretchBlt (hdcBmp, 0, 0, himlSrc->cx, himlSrc->cy,
700
himlDst->hdcImage, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
701
SRCCOPY);
702
/* mask */
703
SelectObject (hdcBmp, hbmTempMask);
704
StretchBlt (hdcBmp, 0, 0, himlSrc->cx, himlSrc->cy,
705
himlDst->hdcMask, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
706
SRCCOPY);
707
708
/* copy (and stretch) source to destination */
709
/* image */
710
StretchBlt (himlDst->hdcImage, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
711
himlSrc->hdcImage, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
712
SRCCOPY);
713
/* mask */
714
StretchBlt (himlDst->hdcMask, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
715
himlSrc->hdcMask, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
716
SRCCOPY);
717
718
/* copy (without stretching) temporary bitmaps to source (restore) */
719
/* mask */
720
BitBlt (himlSrc->hdcMask, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
721
hdcBmp, 0, 0, SRCCOPY);
722
723
/* image */
724
SelectObject (hdcBmp, hbmTempImage);
725
BitBlt (himlSrc->hdcImage, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
726
hdcBmp, 0, 0, SRCCOPY);
727
/* delete temporary bitmaps */
728
DeleteObject (hbmTempMask);
729
DeleteObject (hbmTempImage);
730
DeleteDC(hdcBmp);
731
}
732
else {
733
/* copy image */
734
StretchBlt (himlDst->hdcImage, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
735
himlSrc->hdcImage, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
736
SRCCOPY);
737
738
/* copy mask */
739
StretchBlt (himlDst->hdcMask, ptDst.x, ptDst.y, himlDst->cx, himlDst->cy,
740
himlSrc->hdcMask, ptSrc.x, ptSrc.y, himlSrc->cx, himlSrc->cy,
741
SRCCOPY);
742
}
743
744
return TRUE;
745
}
746
747
748
/*************************************************************************
749
* ImageList_Create [COMCTL32.@]
750
*
751
* Creates a new image list.
752
*
753
* PARAMS
754
* cx [I] image height
755
* cy [I] image width
756
* flags [I] creation flags
757
* cInitial [I] initial number of images in the image list
758
* cGrow [I] number of images by which image list grows
759
*
760
* RETURNS
761
* Success: Handle to the created image list
762
* Failure: NULL
763
*/
764
HIMAGELIST WINAPI
765
ImageList_Create (INT cx, INT cy, UINT flags,
766
INT cInitial, INT cGrow)
767
{
768
IImageList2 *himl;
769
770
TRACE("(%d %d 0x%x %d %d)\n", cx, cy, flags, cInitial, cGrow);
771
772
/* Create the IImageList interface for the image list */
773
if (FAILED(ImageListImpl_CreateInstance(NULL, &IID_IImageList2, (void **)&himl)))
774
return NULL;
775
776
if (IImageList2_Initialize(himl, cx, cy, flags, cInitial, cGrow) == S_OK)
777
return (HIMAGELIST)himl;
778
779
IImageList2_Release(himl);
780
return NULL;
781
}
782
783
784
/*************************************************************************
785
* ImageList_Destroy [COMCTL32.@]
786
*
787
* Destroys an image list.
788
*
789
* PARAMS
790
* himl [I] handle to image list
791
*
792
* RETURNS
793
* Success: TRUE
794
* Failure: FALSE
795
*/
796
797
BOOL WINAPI
798
ImageList_Destroy (HIMAGELIST himl)
799
{
800
if (!is_valid(himl))
801
return FALSE;
802
803
IImageList_Release((IImageList *) himl);
804
return TRUE;
805
}
806
807
808
/*************************************************************************
809
* ImageList_DragEnter [COMCTL32.@]
810
*
811
* Locks window update and displays the drag image at the given position.
812
*
813
* PARAMS
814
* hwndLock [I] handle of the window that owns the drag image.
815
* x [I] X position of the drag image.
816
* y [I] Y position of the drag image.
817
*
818
* RETURNS
819
* Success: TRUE
820
* Failure: FALSE
821
*
822
* NOTES
823
* The position of the drag image is relative to the window, not
824
* the client area.
825
*/
826
827
BOOL WINAPI
828
ImageList_DragEnter (HWND hwndLock, INT x, INT y)
829
{
830
TRACE("(hwnd=%p x=%d y=%d)\n", hwndLock, x, y);
831
832
if (!is_valid(InternalDrag.himl))
833
return FALSE;
834
835
if (hwndLock)
836
InternalDrag.hwnd = hwndLock;
837
else
838
InternalDrag.hwnd = GetDesktopWindow ();
839
840
InternalDrag.x = x;
841
InternalDrag.y = y;
842
843
/* draw the drag image and save the background */
844
return ImageList_DragShowNolock(TRUE);
845
}
846
847
848
/*************************************************************************
849
* ImageList_DragLeave [COMCTL32.@]
850
*
851
* Unlocks window update and hides the drag image.
852
*
853
* PARAMS
854
* hwndLock [I] handle of the window that owns the drag image.
855
*
856
* RETURNS
857
* Success: TRUE
858
* Failure: FALSE
859
*/
860
861
BOOL WINAPI
862
ImageList_DragLeave (HWND hwndLock)
863
{
864
/* As we don't save drag info in the window this can lead to problems if
865
an app does not supply the same window as DragEnter */
866
/* if (hwndLock)
867
InternalDrag.hwnd = hwndLock;
868
else
869
InternalDrag.hwnd = GetDesktopWindow (); */
870
if(!hwndLock)
871
hwndLock = GetDesktopWindow();
872
if(InternalDrag.hwnd != hwndLock)
873
FIXME("DragLeave hWnd != DragEnter hWnd\n");
874
875
ImageList_DragShowNolock (FALSE);
876
877
return TRUE;
878
}
879
880
881
/*************************************************************************
882
* ImageList_InternalDragDraw [Internal]
883
*
884
* Draws the drag image.
885
*
886
* PARAMS
887
* hdc [I] device context to draw into.
888
* x [I] X position of the drag image.
889
* y [I] Y position of the drag image.
890
*
891
* RETURNS
892
* Success: TRUE
893
* Failure: FALSE
894
*
895
* NOTES
896
* The position of the drag image is relative to the window, not
897
* the client area.
898
*
899
*/
900
901
static inline void
902
ImageList_InternalDragDraw (HDC hdc, INT x, INT y)
903
{
904
IMAGELISTDRAWPARAMS imldp;
905
906
ZeroMemory (&imldp, sizeof(imldp));
907
imldp.cbSize = sizeof(imldp);
908
imldp.himl = InternalDrag.himl;
909
imldp.i = 0;
910
imldp.hdcDst = hdc;
911
imldp.x = x;
912
imldp.y = y;
913
imldp.rgbBk = CLR_DEFAULT;
914
imldp.rgbFg = CLR_DEFAULT;
915
imldp.fStyle = ILD_NORMAL;
916
imldp.fState = ILS_ALPHA;
917
imldp.Frame = 192;
918
ImageList_DrawIndirect (&imldp);
919
}
920
921
/*************************************************************************
922
* ImageList_DragMove [COMCTL32.@]
923
*
924
* Moves the drag image.
925
*
926
* PARAMS
927
* x [I] X position of the drag image.
928
* y [I] Y position of the drag image.
929
*
930
* RETURNS
931
* Success: TRUE
932
* Failure: FALSE
933
*
934
* NOTES
935
* The position of the drag image is relative to the window, not
936
* the client area.
937
*/
938
939
BOOL WINAPI
940
ImageList_DragMove (INT x, INT y)
941
{
942
TRACE("(x=%d y=%d)\n", x, y);
943
944
if (!is_valid(InternalDrag.himl))
945
return FALSE;
946
947
/* draw/update the drag image */
948
if (InternalDrag.bShow) {
949
HDC hdcDrag;
950
HDC hdcOffScreen;
951
HDC hdcBg;
952
HBITMAP hbmOffScreen;
953
INT origNewX, origNewY;
954
INT origOldX, origOldY;
955
INT origRegX, origRegY;
956
INT sizeRegX, sizeRegY;
957
958
959
/* calculate the update region */
960
origNewX = x - InternalDrag.dxHotspot;
961
origNewY = y - InternalDrag.dyHotspot;
962
origOldX = InternalDrag.x - InternalDrag.dxHotspot;
963
origOldY = InternalDrag.y - InternalDrag.dyHotspot;
964
origRegX = min(origNewX, origOldX);
965
origRegY = min(origNewY, origOldY);
966
sizeRegX = InternalDrag.himl->cx + abs(x - InternalDrag.x);
967
sizeRegY = InternalDrag.himl->cy + abs(y - InternalDrag.y);
968
969
hdcDrag = GetDCEx(InternalDrag.hwnd, 0,
970
DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
971
hdcOffScreen = CreateCompatibleDC(hdcDrag);
972
hdcBg = CreateCompatibleDC(hdcDrag);
973
974
hbmOffScreen = CreateCompatibleBitmap(hdcDrag, sizeRegX, sizeRegY);
975
SelectObject(hdcOffScreen, hbmOffScreen);
976
SelectObject(hdcBg, InternalDrag.hbmBg);
977
978
/* get the actual background of the update region */
979
BitBlt(hdcOffScreen, 0, 0, sizeRegX, sizeRegY, hdcDrag,
980
origRegX, origRegY, SRCCOPY);
981
/* erase the old image */
982
BitBlt(hdcOffScreen, origOldX - origRegX, origOldY - origRegY,
983
InternalDrag.himl->cx, InternalDrag.himl->cy, hdcBg, 0, 0,
984
SRCCOPY);
985
/* save the background */
986
BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy,
987
hdcOffScreen, origNewX - origRegX, origNewY - origRegY, SRCCOPY);
988
/* draw the image */
989
ImageList_InternalDragDraw(hdcOffScreen, origNewX - origRegX,
990
origNewY - origRegY);
991
/* draw the update region to the screen */
992
BitBlt(hdcDrag, origRegX, origRegY, sizeRegX, sizeRegY,
993
hdcOffScreen, 0, 0, SRCCOPY);
994
995
DeleteDC(hdcBg);
996
DeleteDC(hdcOffScreen);
997
DeleteObject(hbmOffScreen);
998
ReleaseDC(InternalDrag.hwnd, hdcDrag);
999
}
1000
1001
/* update the image position */
1002
InternalDrag.x = x;
1003
InternalDrag.y = y;
1004
1005
return TRUE;
1006
}
1007
1008
1009
/*************************************************************************
1010
* ImageList_DragShowNolock [COMCTL32.@]
1011
*
1012
* Shows or hides the drag image.
1013
*
1014
* PARAMS
1015
* bShow [I] TRUE shows the drag image, FALSE hides it.
1016
*
1017
* RETURNS
1018
* Success: TRUE
1019
* Failure: FALSE
1020
*/
1021
1022
BOOL WINAPI
1023
ImageList_DragShowNolock (BOOL bShow)
1024
{
1025
HDC hdcDrag;
1026
HDC hdcBg;
1027
INT x, y;
1028
1029
if (!is_valid(InternalDrag.himl))
1030
return FALSE;
1031
1032
TRACE("bShow=0x%X!\n", bShow);
1033
1034
/* DragImage is already visible/hidden */
1035
if ((InternalDrag.bShow && bShow) || (!InternalDrag.bShow && !bShow)) {
1036
return FALSE;
1037
}
1038
1039
/* position of the origin of the DragImage */
1040
x = InternalDrag.x - InternalDrag.dxHotspot;
1041
y = InternalDrag.y - InternalDrag.dyHotspot;
1042
1043
hdcDrag = GetDCEx (InternalDrag.hwnd, 0,
1044
DCX_WINDOW | DCX_CACHE | DCX_LOCKWINDOWUPDATE);
1045
if (!hdcDrag) {
1046
return FALSE;
1047
}
1048
1049
hdcBg = CreateCompatibleDC(hdcDrag);
1050
if (!InternalDrag.hbmBg) {
1051
InternalDrag.hbmBg = CreateCompatibleBitmap(hdcDrag,
1052
InternalDrag.himl->cx, InternalDrag.himl->cy);
1053
}
1054
SelectObject(hdcBg, InternalDrag.hbmBg);
1055
1056
if (bShow) {
1057
/* save the background */
1058
BitBlt(hdcBg, 0, 0, InternalDrag.himl->cx, InternalDrag.himl->cy,
1059
hdcDrag, x, y, SRCCOPY);
1060
/* show the image */
1061
ImageList_InternalDragDraw(hdcDrag, x, y);
1062
} else {
1063
/* hide the image */
1064
BitBlt(hdcDrag, x, y, InternalDrag.himl->cx, InternalDrag.himl->cy,
1065
hdcBg, 0, 0, SRCCOPY);
1066
}
1067
1068
InternalDrag.bShow = !InternalDrag.bShow;
1069
1070
DeleteDC(hdcBg);
1071
ReleaseDC (InternalDrag.hwnd, hdcDrag);
1072
return TRUE;
1073
}
1074
1075
1076
/*************************************************************************
1077
* ImageList_Draw [COMCTL32.@]
1078
*
1079
* Draws an image.
1080
*
1081
* PARAMS
1082
* himl [I] handle to image list
1083
* i [I] image index
1084
* hdc [I] handle to device context
1085
* x [I] x position
1086
* y [I] y position
1087
* fStyle [I] drawing flags
1088
*
1089
* RETURNS
1090
* Success: TRUE
1091
* Failure: FALSE
1092
*
1093
* SEE
1094
* ImageList_DrawEx.
1095
*/
1096
1097
BOOL WINAPI
1098
ImageList_Draw (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y, UINT fStyle)
1099
{
1100
return ImageList_DrawEx (himl, i, hdc, x, y, 0, 0,
1101
CLR_DEFAULT, CLR_DEFAULT, fStyle);
1102
}
1103
1104
1105
/*************************************************************************
1106
* ImageList_DrawEx [COMCTL32.@]
1107
*
1108
* Draws an image and allows using extended drawing features.
1109
*
1110
* PARAMS
1111
* himl [I] handle to image list
1112
* i [I] image index
1113
* hdc [I] handle to device context
1114
* x [I] X position
1115
* y [I] Y position
1116
* dx [I] X offset
1117
* dy [I] Y offset
1118
* rgbBk [I] background color
1119
* rgbFg [I] foreground color
1120
* fStyle [I] drawing flags
1121
*
1122
* RETURNS
1123
* Success: TRUE
1124
* Failure: FALSE
1125
*
1126
* NOTES
1127
* Calls ImageList_DrawIndirect.
1128
*
1129
* SEE
1130
* ImageList_DrawIndirect.
1131
*/
1132
1133
BOOL WINAPI
1134
ImageList_DrawEx (HIMAGELIST himl, INT i, HDC hdc, INT x, INT y,
1135
INT dx, INT dy, COLORREF rgbBk, COLORREF rgbFg,
1136
UINT fStyle)
1137
{
1138
IMAGELISTDRAWPARAMS imldp;
1139
1140
ZeroMemory (&imldp, sizeof(imldp));
1141
imldp.cbSize = sizeof(imldp);
1142
imldp.himl = himl;
1143
imldp.i = i;
1144
imldp.hdcDst = hdc;
1145
imldp.x = x;
1146
imldp.y = y;
1147
imldp.cx = dx;
1148
imldp.cy = dy;
1149
imldp.rgbBk = rgbBk;
1150
imldp.rgbFg = rgbFg;
1151
imldp.fStyle = fStyle;
1152
1153
return ImageList_DrawIndirect (&imldp);
1154
}
1155
1156
1157
static BOOL alpha_blend_image( HIMAGELIST himl, HDC dest_dc, int dest_x, int dest_y,
1158
int src_x, int src_y, int cx, int cy, UINT style, UINT state,
1159
DWORD frame, COLORREF blend_col, BOOL has_alpha )
1160
{
1161
BOOL ret = FALSE;
1162
HDC hdc;
1163
HBITMAP bmp = 0, mask = 0;
1164
BITMAPINFO *info;
1165
BLENDFUNCTION func;
1166
void *bits, *mask_bits;
1167
unsigned int *ptr;
1168
int i, j;
1169
1170
func.BlendOp = AC_SRC_OVER;
1171
func.BlendFlags = 0;
1172
func.SourceConstantAlpha = 255;
1173
func.AlphaFormat = AC_SRC_ALPHA;
1174
1175
if (!(hdc = CreateCompatibleDC( 0 ))) return FALSE;
1176
if (!(info = Alloc( FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done;
1177
info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1178
info->bmiHeader.biWidth = cx;
1179
info->bmiHeader.biHeight = cy;
1180
info->bmiHeader.biPlanes = 1;
1181
info->bmiHeader.biBitCount = 32;
1182
info->bmiHeader.biCompression = BI_RGB;
1183
info->bmiHeader.biSizeImage = cx * cy * 4;
1184
info->bmiHeader.biXPelsPerMeter = 0;
1185
info->bmiHeader.biYPelsPerMeter = 0;
1186
info->bmiHeader.biClrUsed = 0;
1187
info->bmiHeader.biClrImportant = 0;
1188
if (!(bmp = CreateDIBSection( himl->hdcImage, info, DIB_RGB_COLORS, &bits, 0, 0 ))) goto done;
1189
SelectObject( hdc, bmp );
1190
BitBlt( hdc, 0, 0, cx, cy, himl->hdcImage, src_x, src_y, SRCCOPY );
1191
1192
if (blend_col != CLR_NONE)
1193
{
1194
BYTE r = GetRValue( blend_col );
1195
BYTE g = GetGValue( blend_col );
1196
BYTE b = GetBValue( blend_col );
1197
1198
if (style & ILD_BLEND25)
1199
{
1200
for (i = 0, ptr = bits; i < cx * cy; i++, ptr++)
1201
*ptr = ((*ptr & 0xff000000) |
1202
((((*ptr & 0x00ff0000) * 3 + (r << 16)) / 4) & 0x00ff0000) |
1203
((((*ptr & 0x0000ff00) * 3 + (g << 8)) / 4) & 0x0000ff00) |
1204
((((*ptr & 0x000000ff) * 3 + (b << 0)) / 4) & 0x000000ff));
1205
}
1206
else if (style & ILD_BLEND50)
1207
{
1208
for (i = 0, ptr = bits; i < cx * cy; i++, ptr++)
1209
*ptr = ((*ptr & 0xff000000) |
1210
((((*ptr & 0x00ff0000) + (r << 16)) / 2) & 0x00ff0000) |
1211
((((*ptr & 0x0000ff00) + (g << 8)) / 2) & 0x0000ff00) |
1212
((((*ptr & 0x000000ff) + (b << 0)) / 2) & 0x000000ff));
1213
}
1214
}
1215
1216
1217
if (state & ILS_ALPHA)
1218
{
1219
func.SourceConstantAlpha = (BYTE)frame;
1220
}
1221
else if (state & ILS_SATURATE)
1222
{
1223
for (i = 0, ptr = bits; i < cx * cy; i++, ptr++)
1224
{
1225
DWORD gray = (((*ptr & 0x00ff0000) >> 16) * 299 +
1226
((*ptr & 0x0000ff00) >> 8) * 587 +
1227
((*ptr & 0x000000ff) >> 0) * 114 + 500) / 1000;
1228
if (has_alpha) gray = gray * (*ptr >> 24) / 255;
1229
*ptr = (*ptr & 0xff000000)| (gray << 16) | (gray << 8) | gray;
1230
}
1231
}
1232
else if (style & ILD_PRESERVEALPHA)
1233
{
1234
HBRUSH old_brush = SelectObject( dest_dc, GetStockObject(BLACK_BRUSH) );
1235
PatBlt( dest_dc, dest_x, dest_y, cx, cy, PATCOPY );
1236
SelectObject( dest_dc, old_brush );
1237
}
1238
1239
if (has_alpha) /* we already have an alpha channel in this case */
1240
{
1241
/* pre-multiply by the alpha channel */
1242
for (i = 0, ptr = bits; i < cx * cy; i++, ptr++)
1243
{
1244
DWORD alpha = *ptr >> 24;
1245
*ptr = ((*ptr & 0xff000000) |
1246
(((*ptr & 0x00ff0000) * alpha / 255) & 0x00ff0000) |
1247
(((*ptr & 0x0000ff00) * alpha / 255) & 0x0000ff00) |
1248
(((*ptr & 0x000000ff) * alpha / 255)));
1249
}
1250
}
1251
else if (himl->hbmMask)
1252
{
1253
unsigned int width_bytes = (cx + 31) / 32 * 4;
1254
/* generate alpha channel from the mask */
1255
info->bmiHeader.biBitCount = 1;
1256
info->bmiHeader.biSizeImage = width_bytes * cy;
1257
info->bmiColors[0].rgbRed = 0;
1258
info->bmiColors[0].rgbGreen = 0;
1259
info->bmiColors[0].rgbBlue = 0;
1260
info->bmiColors[0].rgbReserved = 0;
1261
info->bmiColors[1].rgbRed = 0xff;
1262
info->bmiColors[1].rgbGreen = 0xff;
1263
info->bmiColors[1].rgbBlue = 0xff;
1264
info->bmiColors[1].rgbReserved = 0;
1265
if (!(mask = CreateDIBSection( himl->hdcMask, info, DIB_RGB_COLORS, &mask_bits, 0, 0 )))
1266
goto done;
1267
SelectObject( hdc, mask );
1268
BitBlt( hdc, 0, 0, cx, cy, himl->hdcMask, src_x, src_y, SRCCOPY );
1269
SelectObject( hdc, bmp );
1270
for (i = 0, ptr = bits; i < cy; i++)
1271
for (j = 0; j < cx; j++, ptr++)
1272
if ((((BYTE *)mask_bits)[i * width_bytes + j / 8] << (j % 8)) & 0x80) *ptr = 0;
1273
else *ptr |= 0xff000000;
1274
}
1275
else
1276
{
1277
for (i = 0, ptr = bits; i < cx * cy; i++, ptr++)
1278
*ptr |= 0xff000000;
1279
}
1280
1281
ret = GdiAlphaBlend( dest_dc, dest_x, dest_y, cx, cy, hdc, 0, 0, cx, cy, func );
1282
1283
done:
1284
DeleteDC( hdc );
1285
if (bmp) DeleteObject( bmp );
1286
if (mask) DeleteObject( mask );
1287
Free( info );
1288
return ret;
1289
}
1290
1291
/*************************************************************************
1292
* ImageList_DrawIndirect [COMCTL32.@]
1293
*
1294
* Draws an image using various parameters specified in pimldp.
1295
*
1296
* PARAMS
1297
* pimldp [I] pointer to IMAGELISTDRAWPARAMS structure.
1298
*
1299
* RETURNS
1300
* Success: TRUE
1301
* Failure: FALSE
1302
*/
1303
1304
BOOL WINAPI
1305
ImageList_DrawIndirect (IMAGELISTDRAWPARAMS *pimldp)
1306
{
1307
INT cx, cy, nOvlIdx;
1308
DWORD fState, dwRop;
1309
UINT fStyle;
1310
COLORREF oldImageBk, oldImageFg;
1311
HDC hImageDC, hImageListDC, hMaskListDC;
1312
HBITMAP hImageBmp, hOldImageBmp, hBlendMaskBmp;
1313
BOOL bIsTransparent, bBlend, bResult = FALSE, bMask;
1314
HIMAGELIST himl;
1315
HBRUSH hOldBrush;
1316
POINT pt;
1317
BOOL has_alpha;
1318
1319
if (!pimldp || !(himl = pimldp->himl)) return FALSE;
1320
if (!is_valid(himl)) return FALSE;
1321
if ((pimldp->i < 0) || (pimldp->i >= himl->cCurImage)) return FALSE;
1322
1323
imagelist_point_from_index( himl, pimldp->i, &pt );
1324
pt.x += pimldp->xBitmap;
1325
pt.y += pimldp->yBitmap;
1326
1327
fState = pimldp->cbSize < sizeof(IMAGELISTDRAWPARAMS) ? ILS_NORMAL : pimldp->fState;
1328
fStyle = pimldp->fStyle & ~ILD_OVERLAYMASK;
1329
cx = (pimldp->cx == 0) ? himl->cx : pimldp->cx;
1330
cy = (pimldp->cy == 0) ? himl->cy : pimldp->cy;
1331
1332
bIsTransparent = (fStyle & ILD_TRANSPARENT);
1333
if( pimldp->rgbBk == CLR_NONE )
1334
bIsTransparent = TRUE;
1335
if( ( pimldp->rgbBk == CLR_DEFAULT ) && ( himl->clrBk == CLR_NONE ) )
1336
bIsTransparent = TRUE;
1337
bMask = (himl->flags & ILC_MASK) && (fStyle & ILD_MASK) ;
1338
bBlend = (fStyle & (ILD_BLEND25 | ILD_BLEND50) ) && !bMask;
1339
1340
TRACE("himl(%p) hbmMask(%p) iImage(%d) x(%d) y(%d) cx(%d) cy(%d)\n",
1341
himl, himl->hbmMask, pimldp->i, pimldp->x, pimldp->y, cx, cy);
1342
1343
/* we will use these DCs to access the images and masks in the ImageList */
1344
hImageListDC = himl->hdcImage;
1345
hMaskListDC = himl->hdcMask;
1346
1347
/* these will accumulate the image and mask for the image we're drawing */
1348
hImageDC = CreateCompatibleDC( pimldp->hdcDst );
1349
hImageBmp = CreateCompatibleBitmap( pimldp->hdcDst, cx, cy );
1350
hBlendMaskBmp = bBlend ? CreateBitmap(cx, cy, 1, 1, NULL) : 0;
1351
1352
/* Create a compatible DC. */
1353
if (!hImageListDC || !hImageDC || !hImageBmp ||
1354
(bBlend && !hBlendMaskBmp) || (himl->hbmMask && !hMaskListDC))
1355
goto cleanup;
1356
1357
hOldImageBmp = SelectObject(hImageDC, hImageBmp);
1358
1359
/*
1360
* To obtain a transparent look, background color should be set
1361
* to white and foreground color to black when blitting the
1362
* monochrome mask.
1363
*/
1364
oldImageFg = SetTextColor( hImageDC, RGB( 0, 0, 0 ) );
1365
oldImageBk = SetBkColor( hImageDC, RGB( 0xff, 0xff, 0xff ) );
1366
1367
has_alpha = himl->item_flags[pimldp->i] & ILIF_ALPHA;
1368
if (!bMask && (has_alpha || (fState & ILS_ALPHA) || (fState & ILS_SATURATE)))
1369
{
1370
COLORREF colour, blend_col = CLR_NONE;
1371
1372
if (bBlend)
1373
{
1374
blend_col = pimldp->rgbFg;
1375
if (blend_col == CLR_DEFAULT) blend_col = GetSysColor( COLOR_HIGHLIGHT );
1376
else if (blend_col == CLR_NONE) blend_col = GetTextColor( pimldp->hdcDst );
1377
}
1378
1379
if (bIsTransparent)
1380
{
1381
bResult = alpha_blend_image( himl, pimldp->hdcDst, pimldp->x, pimldp->y, pt.x, pt.y, cx, cy,
1382
fStyle, fState, pimldp->Frame, blend_col, has_alpha );
1383
goto end;
1384
}
1385
colour = pimldp->rgbBk;
1386
if (colour == CLR_DEFAULT) colour = himl->clrBk;
1387
if (colour == CLR_NONE) colour = GetBkColor( pimldp->hdcDst );
1388
1389
hOldBrush = SelectObject (hImageDC, CreateSolidBrush (colour));
1390
PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY );
1391
alpha_blend_image( himl, hImageDC, 0, 0, pt.x, pt.y, cx, cy, fStyle, fState,
1392
pimldp->Frame, blend_col, has_alpha );
1393
DeleteObject (SelectObject (hImageDC, hOldBrush));
1394
bResult = BitBlt( pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hImageDC, 0, 0, SRCCOPY );
1395
goto end;
1396
}
1397
1398
/*
1399
* Draw the initial image
1400
*/
1401
if( bMask ) {
1402
if (himl->hbmMask) {
1403
hOldBrush = SelectObject (hImageDC, CreateSolidBrush (GetTextColor(pimldp->hdcDst)));
1404
PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY );
1405
BitBlt(hImageDC, 0, 0, cx, cy, hMaskListDC, pt.x, pt.y, SRCPAINT);
1406
DeleteObject (SelectObject (hImageDC, hOldBrush));
1407
if( bIsTransparent )
1408
{
1409
BitBlt ( pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hImageDC, 0, 0, SRCAND);
1410
bResult = TRUE;
1411
goto end;
1412
}
1413
} else {
1414
hOldBrush = SelectObject (hImageDC, GetStockObject(BLACK_BRUSH));
1415
PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY);
1416
SelectObject(hImageDC, hOldBrush);
1417
}
1418
} else {
1419
/* blend the image with the needed solid background */
1420
COLORREF colour = RGB(0,0,0);
1421
1422
if( !bIsTransparent )
1423
{
1424
colour = pimldp->rgbBk;
1425
if( colour == CLR_DEFAULT )
1426
colour = himl->clrBk;
1427
if( colour == CLR_NONE )
1428
colour = GetBkColor(pimldp->hdcDst);
1429
}
1430
1431
hOldBrush = SelectObject (hImageDC, CreateSolidBrush (colour));
1432
PatBlt( hImageDC, 0, 0, cx, cy, PATCOPY );
1433
if (himl->hbmMask)
1434
{
1435
BitBlt( hImageDC, 0, 0, cx, cy, hMaskListDC, pt.x, pt.y, SRCAND );
1436
BitBlt( hImageDC, 0, 0, cx, cy, hImageListDC, pt.x, pt.y, SRCPAINT );
1437
}
1438
else
1439
BitBlt( hImageDC, 0, 0, cx, cy, hImageListDC, pt.x, pt.y, SRCCOPY);
1440
DeleteObject (SelectObject (hImageDC, hOldBrush));
1441
}
1442
1443
/* Time for blending, if required */
1444
if (bBlend) {
1445
HBRUSH hBlendBrush;
1446
COLORREF clrBlend = pimldp->rgbFg;
1447
HDC hBlendMaskDC = hImageListDC;
1448
HBITMAP hOldBitmap;
1449
1450
/* Create the blend Mask */
1451
hOldBitmap = SelectObject(hBlendMaskDC, hBlendMaskBmp);
1452
hBlendBrush = fStyle & ILD_BLEND50 ? himl->hbrBlend50 : himl->hbrBlend25;
1453
hOldBrush = SelectObject(hBlendMaskDC, hBlendBrush);
1454
PatBlt(hBlendMaskDC, 0, 0, cx, cy, PATCOPY);
1455
SelectObject(hBlendMaskDC, hOldBrush);
1456
1457
/* Modify the blend mask if an Image Mask exist */
1458
if(himl->hbmMask) {
1459
BitBlt(hBlendMaskDC, 0, 0, cx, cy, hMaskListDC, pt.x, pt.y, 0x220326); /* NOTSRCAND */
1460
BitBlt(hBlendMaskDC, 0, 0, cx, cy, hBlendMaskDC, 0, 0, NOTSRCCOPY);
1461
}
1462
1463
/* now apply blend to the current image given the BlendMask */
1464
if (clrBlend == CLR_DEFAULT) clrBlend = GetSysColor (COLOR_HIGHLIGHT);
1465
else if (clrBlend == CLR_NONE) clrBlend = GetTextColor (pimldp->hdcDst);
1466
hOldBrush = SelectObject (hImageDC, CreateSolidBrush(clrBlend));
1467
BitBlt (hImageDC, 0, 0, cx, cy, hBlendMaskDC, 0, 0, 0xB8074A); /* PSDPxax */
1468
DeleteObject(SelectObject(hImageDC, hOldBrush));
1469
SelectObject(hBlendMaskDC, hOldBitmap);
1470
}
1471
1472
/* Now do the overlay image, if any */
1473
nOvlIdx = (pimldp->fStyle & ILD_OVERLAYMASK) >> 8;
1474
if ( (nOvlIdx >= 1) && (nOvlIdx <= MAX_OVERLAYIMAGE)) {
1475
nOvlIdx = himl->nOvlIdx[nOvlIdx - 1];
1476
if ((nOvlIdx >= 0) && (nOvlIdx < himl->cCurImage)) {
1477
POINT ptOvl;
1478
imagelist_point_from_index( himl, nOvlIdx, &ptOvl );
1479
ptOvl.x += pimldp->xBitmap;
1480
if (himl->hbmMask && !(fStyle & ILD_IMAGE))
1481
BitBlt (hImageDC, 0, 0, cx, cy, hMaskListDC, ptOvl.x, ptOvl.y, SRCAND);
1482
BitBlt (hImageDC, 0, 0, cx, cy, hImageListDC, ptOvl.x, ptOvl.y, SRCPAINT);
1483
}
1484
}
1485
1486
if (fState & ILS_GLOW) FIXME("ILS_GLOW: unimplemented!\n");
1487
if (fState & ILS_SHADOW) FIXME("ILS_SHADOW: unimplemented!\n");
1488
1489
if (fStyle & ILD_SCALE) FIXME("ILD_SCALE: unimplemented!\n");
1490
if (fStyle & ILD_DPISCALE) FIXME("ILD_DPISCALE: unimplemented!\n");
1491
1492
/* now copy the image to the screen */
1493
dwRop = SRCCOPY;
1494
if (himl->hbmMask && bIsTransparent ) {
1495
COLORREF oldDstFg = SetTextColor(pimldp->hdcDst, RGB( 0, 0, 0 ) );
1496
COLORREF oldDstBk = SetBkColor(pimldp->hdcDst, RGB( 0xff, 0xff, 0xff ));
1497
BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hMaskListDC, pt.x, pt.y, SRCAND);
1498
SetBkColor(pimldp->hdcDst, oldDstBk);
1499
SetTextColor(pimldp->hdcDst, oldDstFg);
1500
dwRop = SRCPAINT;
1501
}
1502
if (fStyle & ILD_ROP) dwRop = pimldp->dwRop;
1503
BitBlt (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy, hImageDC, 0, 0, dwRop);
1504
1505
bResult = TRUE;
1506
end:
1507
/* cleanup the mess */
1508
SetBkColor(hImageDC, oldImageBk);
1509
SetTextColor(hImageDC, oldImageFg);
1510
SelectObject(hImageDC, hOldImageBmp);
1511
cleanup:
1512
DeleteObject(hBlendMaskBmp);
1513
DeleteObject(hImageBmp);
1514
DeleteDC(hImageDC);
1515
1516
return bResult;
1517
}
1518
1519
1520
/*************************************************************************
1521
* ImageList_Duplicate [COMCTL32.@]
1522
*
1523
* Duplicates an image list.
1524
*
1525
* PARAMS
1526
* himlSrc [I] source image list handle
1527
*
1528
* RETURNS
1529
* Success: Handle of duplicated image list.
1530
* Failure: NULL
1531
*/
1532
1533
HIMAGELIST WINAPI
1534
ImageList_Duplicate (HIMAGELIST himlSrc)
1535
{
1536
HIMAGELIST himlDst;
1537
1538
if (!is_valid(himlSrc)) {
1539
ERR("Invalid image list handle!\n");
1540
return NULL;
1541
}
1542
1543
himlDst = ImageList_Create (himlSrc->cx, himlSrc->cy, himlSrc->flags,
1544
himlSrc->cCurImage, himlSrc->cGrow);
1545
1546
if (himlDst)
1547
{
1548
SIZE sz;
1549
1550
imagelist_get_bitmap_size(himlSrc, himlSrc->cCurImage, &sz);
1551
BitBlt (himlDst->hdcImage, 0, 0, sz.cx, sz.cy,
1552
himlSrc->hdcImage, 0, 0, SRCCOPY);
1553
1554
if (himlDst->hbmMask)
1555
BitBlt (himlDst->hdcMask, 0, 0, sz.cx, sz.cy,
1556
himlSrc->hdcMask, 0, 0, SRCCOPY);
1557
1558
himlDst->cCurImage = himlSrc->cCurImage;
1559
memcpy( himlDst->item_flags, himlSrc->item_flags, himlDst->cCurImage * sizeof(*himlDst->item_flags) );
1560
}
1561
return himlDst;
1562
}
1563
1564
1565
/*************************************************************************
1566
* ImageList_EndDrag [COMCTL32.@]
1567
*
1568
* Finishes a drag operation.
1569
*
1570
* PARAMS
1571
* no Parameters
1572
*
1573
* RETURNS
1574
* Success: TRUE
1575
* Failure: FALSE
1576
*/
1577
1578
VOID WINAPI
1579
ImageList_EndDrag (void)
1580
{
1581
/* cleanup the InternalDrag struct */
1582
InternalDrag.hwnd = 0;
1583
if (InternalDrag.himl != InternalDrag.himlNoCursor)
1584
ImageList_Destroy (InternalDrag.himlNoCursor);
1585
ImageList_Destroy (InternalDrag.himl);
1586
InternalDrag.himlNoCursor = InternalDrag.himl = 0;
1587
InternalDrag.x= 0;
1588
InternalDrag.y= 0;
1589
InternalDrag.dxHotspot = 0;
1590
InternalDrag.dyHotspot = 0;
1591
InternalDrag.bShow = FALSE;
1592
DeleteObject(InternalDrag.hbmBg);
1593
InternalDrag.hbmBg = 0;
1594
}
1595
1596
1597
/*************************************************************************
1598
* ImageList_GetBkColor [COMCTL32.@]
1599
*
1600
* Returns the background color of an image list.
1601
*
1602
* PARAMS
1603
* himl [I] Image list handle.
1604
*
1605
* RETURNS
1606
* Success: background color
1607
* Failure: CLR_NONE
1608
*/
1609
1610
COLORREF WINAPI
1611
ImageList_GetBkColor (HIMAGELIST himl)
1612
{
1613
return himl ? himl->clrBk : CLR_NONE;
1614
}
1615
1616
1617
/*************************************************************************
1618
* ImageList_GetDragImage [COMCTL32.@]
1619
*
1620
* Returns the handle to the internal drag image list.
1621
*
1622
* PARAMS
1623
* ppt [O] Pointer to the drag position. Can be NULL.
1624
* pptHotspot [O] Pointer to the position of the hot spot. Can be NULL.
1625
*
1626
* RETURNS
1627
* Success: Handle of the drag image list.
1628
* Failure: NULL.
1629
*/
1630
1631
HIMAGELIST WINAPI
1632
ImageList_GetDragImage (POINT *ppt, POINT *pptHotspot)
1633
{
1634
if (is_valid(InternalDrag.himl)) {
1635
if (ppt) {
1636
ppt->x = InternalDrag.x;
1637
ppt->y = InternalDrag.y;
1638
}
1639
if (pptHotspot) {
1640
pptHotspot->x = InternalDrag.dxHotspot;
1641
pptHotspot->y = InternalDrag.dyHotspot;
1642
}
1643
return (InternalDrag.himl);
1644
}
1645
1646
return NULL;
1647
}
1648
1649
1650
/*************************************************************************
1651
* ImageList_GetFlags [COMCTL32.@]
1652
*
1653
* Gets the flags of the specified image list.
1654
*
1655
* PARAMS
1656
* himl [I] Handle to image list
1657
*
1658
* RETURNS
1659
* Image list flags.
1660
*
1661
* BUGS
1662
* Stub.
1663
*/
1664
1665
DWORD WINAPI
1666
ImageList_GetFlags(HIMAGELIST himl)
1667
{
1668
TRACE("%p\n", himl);
1669
1670
return is_valid(himl) ? himl->flags : 0;
1671
}
1672
1673
1674
/*************************************************************************
1675
* ImageList_GetIcon [COMCTL32.@]
1676
*
1677
* Creates an icon from a masked image of an image list.
1678
*
1679
* PARAMS
1680
* himl [I] handle to image list
1681
* i [I] image index
1682
* flags [I] drawing style flags
1683
*
1684
* RETURNS
1685
* Success: icon handle
1686
* Failure: NULL
1687
*/
1688
1689
HICON WINAPI
1690
ImageList_GetIcon (HIMAGELIST himl, INT i, UINT fStyle)
1691
{
1692
ICONINFO ii;
1693
HICON hIcon;
1694
HBITMAP hOldDstBitmap;
1695
HDC hdcDst;
1696
POINT pt;
1697
1698
TRACE("%p %d %d\n", himl, i, fStyle);
1699
if (!is_valid(himl) || (i < 0) || (i >= himl->cCurImage)) return NULL;
1700
1701
ii.fIcon = TRUE;
1702
ii.xHotspot = 0;
1703
ii.yHotspot = 0;
1704
1705
/* create colour bitmap */
1706
hdcDst = GetDC(0);
1707
ii.hbmColor = CreateCompatibleBitmap(hdcDst, himl->cx, himl->cy);
1708
ReleaseDC(0, hdcDst);
1709
1710
hdcDst = CreateCompatibleDC(0);
1711
1712
imagelist_point_from_index( himl, i, &pt );
1713
1714
/* draw mask*/
1715
ii.hbmMask = CreateBitmap (himl->cx, himl->cy, 1, 1, NULL);
1716
hOldDstBitmap = SelectObject (hdcDst, ii.hbmMask);
1717
if (himl->hbmMask) {
1718
BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1719
himl->hdcMask, pt.x, pt.y, SRCCOPY);
1720
}
1721
else
1722
PatBlt (hdcDst, 0, 0, himl->cx, himl->cy, BLACKNESS);
1723
1724
/* draw image*/
1725
SelectObject (hdcDst, ii.hbmColor);
1726
BitBlt (hdcDst, 0, 0, himl->cx, himl->cy,
1727
himl->hdcImage, pt.x, pt.y, SRCCOPY);
1728
1729
/*
1730
* CreateIconIndirect requires us to deselect the bitmaps from
1731
* the DCs before calling
1732
*/
1733
SelectObject(hdcDst, hOldDstBitmap);
1734
1735
hIcon = CreateIconIndirect (&ii);
1736
1737
DeleteObject (ii.hbmMask);
1738
DeleteObject (ii.hbmColor);
1739
DeleteDC (hdcDst);
1740
1741
return hIcon;
1742
}
1743
1744
1745
/*************************************************************************
1746
* ImageList_GetIconSize [COMCTL32.@]
1747
*
1748
* Retrieves the size of an image in an image list.
1749
*
1750
* PARAMS
1751
* himl [I] handle to image list
1752
* cx [O] pointer to the image width.
1753
* cy [O] pointer to the image height.
1754
*
1755
* RETURNS
1756
* Success: TRUE
1757
* Failure: FALSE
1758
*
1759
* NOTES
1760
* All images in an image list have the same size.
1761
*/
1762
1763
BOOL WINAPI
1764
ImageList_GetIconSize (HIMAGELIST himl, INT *cx, INT *cy)
1765
{
1766
if (!is_valid(himl) || !cx || !cy)
1767
return FALSE;
1768
1769
*cx = himl->cx;
1770
*cy = himl->cy;
1771
1772
return TRUE;
1773
}
1774
1775
1776
/*************************************************************************
1777
* ImageList_GetImageCount [COMCTL32.@]
1778
*
1779
* Returns the number of images in an image list.
1780
*
1781
* PARAMS
1782
* himl [I] handle to image list
1783
*
1784
* RETURNS
1785
* Success: Number of images.
1786
* Failure: 0
1787
*/
1788
1789
INT WINAPI
1790
ImageList_GetImageCount (HIMAGELIST himl)
1791
{
1792
if (!is_valid(himl))
1793
return 0;
1794
1795
return himl->cCurImage;
1796
}
1797
1798
1799
/*************************************************************************
1800
* ImageList_GetImageInfo [COMCTL32.@]
1801
*
1802
* Returns information about an image in an image list.
1803
*
1804
* PARAMS
1805
* himl [I] handle to image list
1806
* i [I] image index
1807
* pImageInfo [O] pointer to the image information
1808
*
1809
* RETURNS
1810
* Success: TRUE
1811
* Failure: FALSE
1812
*/
1813
1814
BOOL WINAPI
1815
ImageList_GetImageInfo (HIMAGELIST himl, INT i, IMAGEINFO *pImageInfo)
1816
{
1817
POINT pt;
1818
1819
if (!is_valid(himl) || (pImageInfo == NULL))
1820
return FALSE;
1821
if ((i < 0) || (i >= himl->cCurImage))
1822
return FALSE;
1823
1824
pImageInfo->hbmImage = himl->hbmImage;
1825
pImageInfo->hbmMask = himl->hbmMask;
1826
1827
imagelist_point_from_index( himl, i, &pt );
1828
pImageInfo->rcImage.top = pt.y;
1829
pImageInfo->rcImage.bottom = pt.y + himl->cy;
1830
pImageInfo->rcImage.left = pt.x;
1831
pImageInfo->rcImage.right = pt.x + himl->cx;
1832
1833
return TRUE;
1834
}
1835
1836
1837
/*************************************************************************
1838
* ImageList_GetImageRect [COMCTL32.@]
1839
*
1840
* Retrieves the rectangle of the specified image in an image list.
1841
*
1842
* PARAMS
1843
* himl [I] handle to image list
1844
* i [I] image index
1845
* lpRect [O] pointer to the image rectangle
1846
*
1847
* RETURNS
1848
* Success: TRUE
1849
* Failure: FALSE
1850
*
1851
* NOTES
1852
* This is an UNDOCUMENTED function!!!
1853
*/
1854
1855
BOOL WINAPI
1856
ImageList_GetImageRect (HIMAGELIST himl, INT i, LPRECT lpRect)
1857
{
1858
POINT pt;
1859
1860
if (!is_valid(himl) || (lpRect == NULL))
1861
return FALSE;
1862
if ((i < 0) || (i >= himl->cCurImage))
1863
return FALSE;
1864
1865
imagelist_point_from_index( himl, i, &pt );
1866
lpRect->left = pt.x;
1867
lpRect->top = pt.y;
1868
lpRect->right = pt.x + himl->cx;
1869
lpRect->bottom = pt.y + himl->cy;
1870
1871
return TRUE;
1872
}
1873
1874
1875
/*************************************************************************
1876
* ImageList_LoadImage [COMCTL32.@]
1877
* ImageList_LoadImageA [COMCTL32.@]
1878
*
1879
* Creates an image list from a bitmap, icon or cursor.
1880
*
1881
* See ImageList_LoadImageW.
1882
*/
1883
1884
HIMAGELIST WINAPI
1885
ImageList_LoadImageA (HINSTANCE hi, LPCSTR lpbmp, INT cx, INT cGrow,
1886
COLORREF clrMask, UINT uType, UINT uFlags)
1887
{
1888
HIMAGELIST himl;
1889
LPWSTR lpbmpW;
1890
DWORD len;
1891
1892
if (IS_INTRESOURCE(lpbmp))
1893
return ImageList_LoadImageW(hi, (LPCWSTR)lpbmp, cx, cGrow, clrMask,
1894
uType, uFlags);
1895
1896
len = MultiByteToWideChar(CP_ACP, 0, lpbmp, -1, NULL, 0);
1897
lpbmpW = Alloc(len * sizeof(WCHAR));
1898
MultiByteToWideChar(CP_ACP, 0, lpbmp, -1, lpbmpW, len);
1899
1900
himl = ImageList_LoadImageW(hi, lpbmpW, cx, cGrow, clrMask, uType, uFlags);
1901
Free (lpbmpW);
1902
return himl;
1903
}
1904
1905
1906
/*************************************************************************
1907
* ImageList_LoadImageW [COMCTL32.@]
1908
*
1909
* Creates an image list from a bitmap, icon or cursor.
1910
*
1911
* PARAMS
1912
* hi [I] instance handle
1913
* lpbmp [I] name or id of the image
1914
* cx [I] width of each image
1915
* cGrow [I] number of images to expand
1916
* clrMask [I] mask color
1917
* uType [I] type of image to load
1918
* uFlags [I] loading flags
1919
*
1920
* RETURNS
1921
* Success: handle to the loaded image list
1922
* Failure: NULL
1923
*
1924
* SEE
1925
* LoadImage ()
1926
*/
1927
1928
HIMAGELIST WINAPI
1929
ImageList_LoadImageW (HINSTANCE hi, LPCWSTR lpbmp, INT cx, INT cGrow,
1930
COLORREF clrMask, UINT uType, UINT uFlags)
1931
{
1932
HIMAGELIST himl = NULL;
1933
HANDLE handle;
1934
INT nImageCount;
1935
1936
handle = LoadImageW (hi, lpbmp, uType, 0, 0, uFlags);
1937
if (!handle) {
1938
WARN("Couldn't load image\n");
1939
return NULL;
1940
}
1941
1942
if (uType == IMAGE_BITMAP) {
1943
DIBSECTION dib;
1944
UINT color;
1945
1946
if (GetObjectW (handle, sizeof(dib), &dib) == sizeof(BITMAP)) color = ILC_COLOR;
1947
else color = dib.dsBm.bmBitsPixel;
1948
1949
/* To match windows behavior, if cx is set to zero and
1950
the flag DI_DEFAULTSIZE is specified, cx becomes the
1951
system metric value for icons. If the flag is not specified
1952
the function sets the size to the height of the bitmap */
1953
if (cx == 0)
1954
{
1955
if (uFlags & DI_DEFAULTSIZE)
1956
cx = GetSystemMetrics (SM_CXICON);
1957
else
1958
cx = dib.dsBm.bmHeight;
1959
}
1960
1961
nImageCount = dib.dsBm.bmWidth / cx;
1962
1963
if (clrMask != CLR_NONE) color |= ILC_MASK;
1964
himl = ImageList_Create (cx, dib.dsBm.bmHeight, color, nImageCount, cGrow);
1965
if (!himl) {
1966
DeleteObject (handle);
1967
return NULL;
1968
}
1969
ImageList_AddMasked (himl, handle, clrMask);
1970
}
1971
else if ((uType == IMAGE_ICON) || (uType == IMAGE_CURSOR)) {
1972
ICONINFO ii;
1973
BITMAP bmp;
1974
1975
GetIconInfo (handle, &ii);
1976
GetObjectW (ii.hbmColor, sizeof(BITMAP), &bmp);
1977
himl = ImageList_Create (bmp.bmWidth, bmp.bmHeight,
1978
ILC_MASK | ILC_COLOR, 1, cGrow);
1979
if (!himl) {
1980
DeleteObject (ii.hbmColor);
1981
DeleteObject (ii.hbmMask);
1982
DeleteObject (handle);
1983
return NULL;
1984
}
1985
ImageList_Add (himl, ii.hbmColor, ii.hbmMask);
1986
DeleteObject (ii.hbmColor);
1987
DeleteObject (ii.hbmMask);
1988
}
1989
1990
DeleteObject (handle);
1991
1992
return himl;
1993
}
1994
1995
1996
/*************************************************************************
1997
* ImageList_Merge [COMCTL32.@]
1998
*
1999
* Create an image list containing a merged image from two image lists.
2000
*
2001
* PARAMS
2002
* himl1 [I] handle to first image list
2003
* i1 [I] first image index
2004
* himl2 [I] handle to second image list
2005
* i2 [I] second image index
2006
* dx [I] X offset of the second image relative to the first.
2007
* dy [I] Y offset of the second image relative to the first.
2008
*
2009
* RETURNS
2010
* Success: The newly created image list. It contains a single image
2011
* consisting of the second image merged with the first.
2012
* Failure: NULL, if either himl1 or himl2 is invalid.
2013
*
2014
* NOTES
2015
* - The returned image list should be deleted by the caller using
2016
* ImageList_Destroy() when it is no longer required.
2017
* - If either i1 or i2 is not a valid image index, they will be treated
2018
* as blank images.
2019
*/
2020
HIMAGELIST WINAPI
2021
ImageList_Merge (HIMAGELIST himl1, INT i1, HIMAGELIST himl2, INT i2,
2022
INT dx, INT dy)
2023
{
2024
HIMAGELIST himlDst = NULL;
2025
INT cxDst, cyDst;
2026
INT xOff1, yOff1, xOff2, yOff2;
2027
POINT pt1, pt2;
2028
INT newFlags;
2029
2030
TRACE("(himl1=%p i1=%d himl2=%p i2=%d dx=%d dy=%d)\n", himl1, i1, himl2,
2031
i2, dx, dy);
2032
2033
if (!is_valid(himl1) || !is_valid(himl2))
2034
return NULL;
2035
2036
if (dx > 0) {
2037
cxDst = max (himl1->cx, dx + himl2->cx);
2038
xOff1 = 0;
2039
xOff2 = dx;
2040
}
2041
else if (dx < 0) {
2042
cxDst = max (himl2->cx, himl1->cx - dx);
2043
xOff1 = -dx;
2044
xOff2 = 0;
2045
}
2046
else {
2047
cxDst = max (himl1->cx, himl2->cx);
2048
xOff1 = 0;
2049
xOff2 = 0;
2050
}
2051
2052
if (dy > 0) {
2053
cyDst = max (himl1->cy, dy + himl2->cy);
2054
yOff1 = 0;
2055
yOff2 = dy;
2056
}
2057
else if (dy < 0) {
2058
cyDst = max (himl2->cy, himl1->cy - dy);
2059
yOff1 = -dy;
2060
yOff2 = 0;
2061
}
2062
else {
2063
cyDst = max (himl1->cy, himl2->cy);
2064
yOff1 = 0;
2065
yOff2 = 0;
2066
}
2067
2068
newFlags = (himl1->flags > himl2->flags ? himl1->flags : himl2->flags) & ILC_COLORDDB;
2069
if (newFlags == ILC_COLORDDB && (himl1->flags & ILC_COLORDDB) == ILC_COLOR16)
2070
newFlags = ILC_COLOR16; /* this is what native (at least v5) does, don't know why */
2071
himlDst = ImageList_Create (cxDst, cyDst, ILC_MASK | newFlags, 1, 1);
2072
2073
if (himlDst)
2074
{
2075
imagelist_point_from_index( himl1, i1, &pt1 );
2076
imagelist_point_from_index( himl2, i2, &pt2 );
2077
2078
/* copy image */
2079
BitBlt (himlDst->hdcImage, 0, 0, cxDst, cyDst, himl1->hdcImage, 0, 0, BLACKNESS);
2080
if (i1 >= 0 && i1 < himl1->cCurImage)
2081
BitBlt (himlDst->hdcImage, xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcImage, pt1.x, pt1.y, SRCCOPY);
2082
if (i2 >= 0 && i2 < himl2->cCurImage)
2083
{
2084
if (himl2->flags & ILC_MASK)
2085
{
2086
BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask , pt2.x, pt2.y, SRCAND);
2087
BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcImage, pt2.x, pt2.y, SRCPAINT);
2088
}
2089
else
2090
BitBlt (himlDst->hdcImage, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcImage, pt2.x, pt2.y, SRCCOPY);
2091
}
2092
2093
/* copy mask */
2094
BitBlt (himlDst->hdcMask, 0, 0, cxDst, cyDst, himl1->hdcMask, 0, 0, WHITENESS);
2095
if (i1 >= 0 && i1 < himl1->cCurImage)
2096
BitBlt (himlDst->hdcMask, xOff1, yOff1, himl1->cx, himl1->cy, himl1->hdcMask, pt1.x, pt1.y, SRCCOPY);
2097
if (i2 >= 0 && i2 < himl2->cCurImage)
2098
BitBlt (himlDst->hdcMask, xOff2, yOff2, himl2->cx, himl2->cy, himl2->hdcMask, pt2.x, pt2.y, SRCAND);
2099
2100
himlDst->cCurImage = 1;
2101
}
2102
2103
return himlDst;
2104
}
2105
2106
2107
/* helper for ImageList_Read, see comments below */
2108
static void *read_bitmap(IStream *pstm, BITMAPINFO *bmi)
2109
{
2110
BITMAPFILEHEADER bmfh;
2111
int bitsperpixel, palspace;
2112
void *bits;
2113
2114
if (FAILED(IStream_Read ( pstm, &bmfh, sizeof(bmfh), NULL)))
2115
return NULL;
2116
2117
if (bmfh.bfType != (('M'<<8)|'B'))
2118
return NULL;
2119
2120
if (FAILED(IStream_Read ( pstm, &bmi->bmiHeader, sizeof(bmi->bmiHeader), NULL)))
2121
return NULL;
2122
2123
if ((bmi->bmiHeader.biSize != sizeof(bmi->bmiHeader)))
2124
return NULL;
2125
2126
TRACE("width %lu, height %lu, planes %u, bpp %u\n",
2127
bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight,
2128
bmi->bmiHeader.biPlanes, bmi->bmiHeader.biBitCount);
2129
2130
bitsperpixel = bmi->bmiHeader.biPlanes * bmi->bmiHeader.biBitCount;
2131
if (bitsperpixel<=8)
2132
palspace = (1<<bitsperpixel)*sizeof(RGBQUAD);
2133
else
2134
palspace = 0;
2135
2136
bmi->bmiHeader.biSizeImage = get_dib_image_size( bmi );
2137
2138
/* read the palette right after the end of the bitmapinfoheader */
2139
if (palspace && FAILED(IStream_Read(pstm, bmi->bmiColors, palspace, NULL)))
2140
return NULL;
2141
2142
bits = Alloc(bmi->bmiHeader.biSizeImage);
2143
if (!bits) return NULL;
2144
2145
if (FAILED(IStream_Read(pstm, bits, bmi->bmiHeader.biSizeImage, NULL)))
2146
{
2147
Free(bits);
2148
return NULL;
2149
}
2150
return bits;
2151
}
2152
2153
/*************************************************************************
2154
* ImageList_Read [COMCTL32.@]
2155
*
2156
* Reads an image list from a stream.
2157
*
2158
* PARAMS
2159
* pstm [I] pointer to a stream
2160
*
2161
* RETURNS
2162
* Success: handle to image list
2163
* Failure: NULL
2164
*
2165
* The format is like this:
2166
* ILHEAD ilheadstruct;
2167
*
2168
* for the color image part:
2169
* BITMAPFILEHEADER bmfh;
2170
* BITMAPINFOHEADER bmih;
2171
* only if it has a palette:
2172
* RGBQUAD rgbs[nr_of_paletted_colors];
2173
*
2174
* BYTE colorbits[imagesize];
2175
*
2176
* the following only if the ILC_MASK bit is set in ILHEAD.ilFlags:
2177
* BITMAPFILEHEADER bmfh_mask;
2178
* BITMAPINFOHEADER bmih_mask;
2179
* only if it has a palette (it usually does not):
2180
* RGBQUAD rgbs[nr_of_paletted_colors];
2181
*
2182
* BYTE maskbits[imagesize];
2183
*/
2184
HIMAGELIST WINAPI ImageList_Read(IStream *pstm)
2185
{
2186
char image_buf[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256];
2187
char mask_buf[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256];
2188
BITMAPINFO *image_info = (BITMAPINFO *)image_buf;
2189
BITMAPINFO *mask_info = (BITMAPINFO *)mask_buf;
2190
void *image_bits, *mask_bits = NULL;
2191
ILHEAD ilHead;
2192
HIMAGELIST himl;
2193
unsigned int i;
2194
2195
TRACE("%p\n", pstm);
2196
2197
if (FAILED(IStream_Read (pstm, &ilHead, sizeof(ILHEAD), NULL)))
2198
return NULL;
2199
if (ilHead.usMagic != (('L' << 8) | 'I'))
2200
return NULL;
2201
if (ilHead.usVersion != 0x101) /* probably version? */
2202
return NULL;
2203
2204
TRACE("cx %u, cy %u, flags 0x%04x, cCurImage %u, cMaxImage %u\n",
2205
ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
2206
2207
himl = ImageList_Create(ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cMaxImage, ilHead.cGrow);
2208
if (!himl)
2209
return NULL;
2210
2211
if (!(image_bits = read_bitmap(pstm, image_info)))
2212
{
2213
WARN("failed to read bitmap from stream\n");
2214
return NULL;
2215
}
2216
if (ilHead.flags & ILC_MASK)
2217
{
2218
if (!(mask_bits = read_bitmap(pstm, mask_info)))
2219
{
2220
WARN("failed to read mask bitmap from stream\n");
2221
return NULL;
2222
}
2223
}
2224
else mask_info = NULL;
2225
2226
if ((himl->flags & 0xfe) == ILC_COLOR32 && image_info->bmiHeader.biBitCount == 32)
2227
{
2228
DWORD *ptr = image_bits;
2229
BYTE *mask_ptr = mask_bits;
2230
int stride = himl->cy * image_info->bmiHeader.biWidth;
2231
2232
if (image_info->bmiHeader.biHeight > 0) /* bottom-up */
2233
{
2234
ptr += image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride;
2235
mask_ptr += (image_info->bmiHeader.biHeight * image_info->bmiHeader.biWidth - stride) / 8;
2236
stride = -stride;
2237
image_info->bmiHeader.biHeight = himl->cy;
2238
}
2239
else image_info->bmiHeader.biHeight = -himl->cy;
2240
2241
for (i = 0; i < ilHead.cCurImage; i += TILE_COUNT)
2242
{
2243
add_dib_bits( himl, i, min( ilHead.cCurImage - i, TILE_COUNT ),
2244
himl->cx, himl->cy, image_info, mask_info, ptr, mask_ptr );
2245
ptr += stride;
2246
mask_ptr += stride / 8;
2247
}
2248
}
2249
else
2250
{
2251
StretchDIBits( himl->hdcImage, 0, 0, image_info->bmiHeader.biWidth, image_info->bmiHeader.biHeight,
2252
0, 0, image_info->bmiHeader.biWidth, image_info->bmiHeader.biHeight,
2253
image_bits, image_info, DIB_RGB_COLORS, SRCCOPY);
2254
if (mask_info)
2255
StretchDIBits( himl->hdcMask, 0, 0, mask_info->bmiHeader.biWidth, mask_info->bmiHeader.biHeight,
2256
0, 0, mask_info->bmiHeader.biWidth, mask_info->bmiHeader.biHeight,
2257
mask_bits, mask_info, DIB_RGB_COLORS, SRCCOPY);
2258
}
2259
Free( image_bits );
2260
Free( mask_bits );
2261
2262
himl->cCurImage = ilHead.cCurImage;
2263
himl->cMaxImage = ilHead.cMaxImage;
2264
2265
ImageList_SetBkColor(himl,ilHead.bkcolor);
2266
for (i=0;i<4;i++)
2267
ImageList_SetOverlayImage(himl,ilHead.ovls[i],i+1);
2268
return himl;
2269
}
2270
2271
2272
/*************************************************************************
2273
* ImageList_Remove [COMCTL32.@]
2274
*
2275
* Removes an image from an image list
2276
*
2277
* PARAMS
2278
* himl [I] image list handle
2279
* i [I] image index
2280
*
2281
* RETURNS
2282
* Success: TRUE
2283
* Failure: FALSE
2284
*
2285
* FIXME: as the image list storage test shows, native comctl32 simply shifts
2286
* images without creating a new bitmap.
2287
*/
2288
BOOL WINAPI
2289
ImageList_Remove (HIMAGELIST himl, INT i)
2290
{
2291
HBITMAP hbmNewImage, hbmNewMask;
2292
HDC hdcBmp;
2293
SIZE sz;
2294
2295
TRACE("(himl=%p i=%d)\n", himl, i);
2296
2297
if (!is_valid(himl)) {
2298
ERR("Invalid image list handle!\n");
2299
return FALSE;
2300
}
2301
2302
if ((i < -1) || (i >= himl->cCurImage)) {
2303
TRACE("index out of range! %d\n", i);
2304
return FALSE;
2305
}
2306
2307
if (i == -1) {
2308
INT nCount;
2309
2310
/* remove all */
2311
if (himl->cCurImage == 0) {
2312
/* remove all on empty ImageList is allowed */
2313
TRACE("remove all on empty ImageList!\n");
2314
return TRUE;
2315
}
2316
2317
himl->cMaxImage = himl->cGrow;
2318
himl->cCurImage = 0;
2319
for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2320
himl->nOvlIdx[nCount] = -1;
2321
2322
Free( himl->item_flags );
2323
himl->item_flags = Alloc( himl->cMaxImage * sizeof(*himl->item_flags) );
2324
2325
hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage);
2326
SelectObject (himl->hdcImage, hbmNewImage);
2327
DeleteObject (himl->hbmImage);
2328
himl->hbmImage = hbmNewImage;
2329
2330
if (himl->hbmMask) {
2331
2332
imagelist_get_bitmap_size(himl, himl->cMaxImage, &sz);
2333
hbmNewMask = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
2334
SelectObject (himl->hdcMask, hbmNewMask);
2335
DeleteObject (himl->hbmMask);
2336
himl->hbmMask = hbmNewMask;
2337
}
2338
}
2339
else {
2340
/* delete one image */
2341
TRACE("Remove single image! %d\n", i);
2342
2343
/* create new bitmap(s) */
2344
TRACE(" - Number of images: %d / %d (Old/New)\n",
2345
himl->cCurImage, himl->cCurImage - 1);
2346
2347
hbmNewImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage);
2348
2349
imagelist_get_bitmap_size(himl, himl->cMaxImage, &sz );
2350
if (himl->hbmMask)
2351
hbmNewMask = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
2352
else
2353
hbmNewMask = 0; /* Just to keep compiler happy! */
2354
2355
hdcBmp = CreateCompatibleDC (0);
2356
2357
/* copy all images and masks prior to the "removed" image */
2358
if (i > 0) {
2359
TRACE("Pre image copy: Copy %d images\n", i);
2360
2361
SelectObject (hdcBmp, hbmNewImage);
2362
imagelist_copy_images( himl, himl->hdcImage, hdcBmp, 0, i, 0 );
2363
2364
if (himl->hbmMask) {
2365
SelectObject (hdcBmp, hbmNewMask);
2366
imagelist_copy_images( himl, himl->hdcMask, hdcBmp, 0, i, 0 );
2367
}
2368
}
2369
2370
/* copy all images and masks behind the removed image */
2371
if (i < himl->cCurImage - 1) {
2372
TRACE("Post image copy!\n");
2373
2374
SelectObject (hdcBmp, hbmNewImage);
2375
imagelist_copy_images( himl, himl->hdcImage, hdcBmp, i + 1,
2376
(himl->cCurImage - i), i );
2377
2378
if (himl->hbmMask) {
2379
SelectObject (hdcBmp, hbmNewMask);
2380
imagelist_copy_images( himl, himl->hdcMask, hdcBmp, i + 1,
2381
(himl->cCurImage - i), i );
2382
}
2383
}
2384
2385
DeleteDC (hdcBmp);
2386
2387
/* delete old images and insert new ones */
2388
SelectObject (himl->hdcImage, hbmNewImage);
2389
DeleteObject (himl->hbmImage);
2390
himl->hbmImage = hbmNewImage;
2391
if (himl->hbmMask) {
2392
SelectObject (himl->hdcMask, hbmNewMask);
2393
DeleteObject (himl->hbmMask);
2394
himl->hbmMask = hbmNewMask;
2395
}
2396
2397
himl->cCurImage--;
2398
}
2399
2400
return TRUE;
2401
}
2402
2403
2404
/*************************************************************************
2405
* ImageList_Replace [COMCTL32.@]
2406
*
2407
* Replaces an image in an image list with a new image.
2408
*
2409
* PARAMS
2410
* himl [I] handle to image list
2411
* i [I] image index
2412
* hbmImage [I] handle to image bitmap
2413
* hbmMask [I] handle to mask bitmap. Can be NULL.
2414
*
2415
* RETURNS
2416
* Success: TRUE
2417
* Failure: FALSE
2418
*/
2419
2420
BOOL WINAPI
2421
ImageList_Replace (HIMAGELIST himl, INT i, HBITMAP hbmImage,
2422
HBITMAP hbmMask)
2423
{
2424
HDC hdcImage;
2425
BITMAP bmp;
2426
POINT pt;
2427
2428
TRACE("%p %d %p %p\n", himl, i, hbmImage, hbmMask);
2429
2430
if (!is_valid(himl)) {
2431
ERR("Invalid image list handle!\n");
2432
return FALSE;
2433
}
2434
2435
if ((i >= himl->cMaxImage) || (i < 0)) {
2436
ERR("Invalid image index!\n");
2437
return FALSE;
2438
}
2439
2440
if (!GetObjectW(hbmImage, sizeof(BITMAP), &bmp))
2441
return FALSE;
2442
2443
hdcImage = CreateCompatibleDC (0);
2444
2445
/* Replace Image */
2446
SelectObject (hdcImage, hbmImage);
2447
2448
if (add_with_alpha( himl, hdcImage, i, 1, bmp.bmWidth, bmp.bmHeight, hbmImage, hbmMask ))
2449
goto done;
2450
2451
imagelist_point_from_index(himl, i, &pt);
2452
StretchBlt (himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy,
2453
hdcImage, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2454
2455
if (himl->hbmMask)
2456
{
2457
HDC hdcTemp;
2458
HBITMAP hOldBitmapTemp;
2459
2460
hdcTemp = CreateCompatibleDC(0);
2461
hOldBitmapTemp = SelectObject(hdcTemp, hbmMask);
2462
2463
StretchBlt (himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy,
2464
hdcTemp, 0, 0, bmp.bmWidth, bmp.bmHeight, SRCCOPY);
2465
SelectObject(hdcTemp, hOldBitmapTemp);
2466
DeleteDC(hdcTemp);
2467
2468
/* Remove the background from the image
2469
*/
2470
BitBlt (himl->hdcImage, pt.x, pt.y, bmp.bmWidth, bmp.bmHeight,
2471
himl->hdcMask, pt.x, pt.y, 0x220326); /* NOTSRCAND */
2472
}
2473
2474
done:
2475
DeleteDC (hdcImage);
2476
2477
return TRUE;
2478
}
2479
2480
2481
/*************************************************************************
2482
* ImageList_ReplaceIcon [COMCTL32.@]
2483
*
2484
* Replaces an image in an image list using an icon.
2485
*
2486
* PARAMS
2487
* himl [I] handle to image list
2488
* i [I] image index
2489
* hIcon [I] handle to icon
2490
*
2491
* RETURNS
2492
* Success: index of the replaced image
2493
* Failure: -1
2494
*/
2495
2496
INT WINAPI
2497
ImageList_ReplaceIcon (HIMAGELIST himl, INT nIndex, HICON hIcon)
2498
{
2499
HICON hBestFitIcon;
2500
ICONINFO ii;
2501
BITMAP bmp;
2502
BOOL ret;
2503
POINT pt;
2504
2505
TRACE("(%p %d %p)\n", himl, nIndex, hIcon);
2506
2507
if (!is_valid(himl)) {
2508
ERR("invalid image list\n");
2509
return -1;
2510
}
2511
if ((nIndex >= himl->cMaxImage) || (nIndex < -1)) {
2512
ERR("invalid image index %d / %d\n", nIndex, himl->cMaxImage);
2513
return -1;
2514
}
2515
2516
hBestFitIcon = CopyImage(
2517
hIcon, IMAGE_ICON,
2518
himl->cx, himl->cy,
2519
LR_COPYFROMRESOURCE);
2520
/* the above will fail if the icon wasn't loaded from a resource, so try
2521
* again without LR_COPYFROMRESOURCE flag */
2522
if (!hBestFitIcon)
2523
hBestFitIcon = CopyImage(
2524
hIcon, IMAGE_ICON,
2525
himl->cx, himl->cy,
2526
0);
2527
if (!hBestFitIcon)
2528
return -1;
2529
2530
if (nIndex == -1) {
2531
if (himl->cCurImage + 1 >= himl->cMaxImage)
2532
IMAGELIST_InternalExpandBitmaps(himl, 1);
2533
2534
nIndex = himl->cCurImage;
2535
himl->cCurImage++;
2536
}
2537
2538
if ((himl->flags & 0xfe) == ILC_COLOR32 && GetIconInfo (hBestFitIcon, &ii))
2539
{
2540
HDC hdcImage = CreateCompatibleDC( 0 );
2541
GetObjectW (ii.hbmMask, sizeof(BITMAP), &bmp);
2542
2543
if (!ii.hbmColor)
2544
{
2545
UINT height = bmp.bmHeight / 2;
2546
HDC hdcMask = CreateCompatibleDC( 0 );
2547
HBITMAP color = CreateBitmap( bmp.bmWidth, height, 1, 1, NULL );
2548
SelectObject( hdcImage, color );
2549
SelectObject( hdcMask, ii.hbmMask );
2550
BitBlt( hdcImage, 0, 0, bmp.bmWidth, height, hdcMask, 0, height, SRCCOPY );
2551
ret = add_with_alpha( himl, hdcImage, nIndex, 1, bmp.bmWidth, height, color, ii.hbmMask );
2552
DeleteDC( hdcMask );
2553
DeleteObject( color );
2554
}
2555
else ret = add_with_alpha( himl, hdcImage, nIndex, 1, bmp.bmWidth, bmp.bmHeight,
2556
ii.hbmColor, ii.hbmMask );
2557
2558
DeleteDC( hdcImage );
2559
DeleteObject (ii.hbmMask);
2560
if (ii.hbmColor) DeleteObject (ii.hbmColor);
2561
if (ret) goto done;
2562
}
2563
2564
imagelist_point_from_index(himl, nIndex, &pt);
2565
2566
if (himl->hbmMask)
2567
{
2568
DrawIconEx( himl->hdcImage, pt.x, pt.y, hBestFitIcon, himl->cx, himl->cy, 0, 0, DI_IMAGE );
2569
PatBlt( himl->hdcMask, pt.x, pt.y, himl->cx, himl->cy, WHITENESS );
2570
DrawIconEx( himl->hdcMask, pt.x, pt.y, hBestFitIcon, himl->cx, himl->cy, 0, 0, DI_MASK );
2571
}
2572
else
2573
{
2574
COLORREF color = himl->clrBk != CLR_NONE ? himl->clrBk : comctl32_color.clrWindow;
2575
HBRUSH brush = CreateSolidBrush( GetNearestColor( himl->hdcImage, color ));
2576
2577
SelectObject( himl->hdcImage, brush );
2578
PatBlt( himl->hdcImage, pt.x, pt.y, himl->cx, himl->cy, PATCOPY );
2579
SelectObject( himl->hdcImage, GetStockObject(BLACK_BRUSH) );
2580
DeleteObject( brush );
2581
DrawIconEx( himl->hdcImage, pt.x, pt.y, hBestFitIcon, himl->cx, himl->cy, 0, 0, DI_NORMAL );
2582
}
2583
2584
done:
2585
DestroyIcon(hBestFitIcon);
2586
2587
TRACE("Insert index = %d, himl->cCurImage = %d\n", nIndex, himl->cCurImage);
2588
return nIndex;
2589
}
2590
2591
2592
/*************************************************************************
2593
* ImageList_SetBkColor [COMCTL32.@]
2594
*
2595
* Sets the background color of an image list.
2596
*
2597
* PARAMS
2598
* himl [I] handle to image list
2599
* clrBk [I] background color
2600
*
2601
* RETURNS
2602
* Success: previous background color
2603
* Failure: CLR_NONE
2604
*/
2605
2606
COLORREF WINAPI
2607
ImageList_SetBkColor (HIMAGELIST himl, COLORREF clrBk)
2608
{
2609
COLORREF clrOldBk;
2610
2611
if (!is_valid(himl))
2612
return CLR_NONE;
2613
2614
clrOldBk = himl->clrBk;
2615
himl->clrBk = clrBk;
2616
return clrOldBk;
2617
}
2618
2619
2620
/*************************************************************************
2621
* ImageList_SetDragCursorImage [COMCTL32.@]
2622
*
2623
* Combines the specified image with the current drag image
2624
*
2625
* PARAMS
2626
* himlDrag [I] handle to drag image list
2627
* iDrag [I] drag image index
2628
* dxHotspot [I] X position of the hot spot
2629
* dyHotspot [I] Y position of the hot spot
2630
*
2631
* RETURNS
2632
* Success: TRUE
2633
* Failure: FALSE
2634
*
2635
* NOTES
2636
* - The names dxHotspot, dyHotspot are misleading because they have nothing
2637
* to do with a hotspot but are only the offset of the origin of the new
2638
* image relative to the origin of the old image.
2639
*
2640
* - When this function is called and the drag image is visible, a
2641
* short flickering occurs but this matches the Win9x behavior. It is
2642
* possible to fix the flickering using code like in ImageList_DragMove.
2643
*/
2644
2645
BOOL WINAPI
2646
ImageList_SetDragCursorImage (HIMAGELIST himlDrag, INT iDrag,
2647
INT dxHotspot, INT dyHotspot)
2648
{
2649
HIMAGELIST himlTemp;
2650
BOOL visible;
2651
2652
if (!is_valid(InternalDrag.himl) || !is_valid(himlDrag))
2653
return FALSE;
2654
2655
TRACE(" dxH=%d dyH=%d nX=%d nY=%d\n",
2656
dxHotspot, dyHotspot, InternalDrag.dxHotspot, InternalDrag.dyHotspot);
2657
2658
visible = InternalDrag.bShow;
2659
2660
himlTemp = ImageList_Merge (InternalDrag.himlNoCursor, 0, himlDrag, iDrag,
2661
dxHotspot, dyHotspot);
2662
2663
if (visible) {
2664
/* hide the drag image */
2665
ImageList_DragShowNolock(FALSE);
2666
}
2667
if ((InternalDrag.himl->cx != himlTemp->cx) ||
2668
(InternalDrag.himl->cy != himlTemp->cy)) {
2669
/* the size of the drag image changed, invalidate the buffer */
2670
DeleteObject(InternalDrag.hbmBg);
2671
InternalDrag.hbmBg = 0;
2672
}
2673
2674
if (InternalDrag.himl != InternalDrag.himlNoCursor)
2675
ImageList_Destroy (InternalDrag.himl);
2676
InternalDrag.himl = himlTemp;
2677
2678
if (visible) {
2679
/* show the drag image */
2680
ImageList_DragShowNolock(TRUE);
2681
}
2682
2683
return TRUE;
2684
}
2685
2686
2687
/*************************************************************************
2688
* ImageList_SetFilter [COMCTL32.@]
2689
*
2690
* Sets a filter (or does something completely different)!!???
2691
* It removes 12 Bytes from the stack (3 Parameters).
2692
*
2693
* PARAMS
2694
* himl [I] SHOULD be a handle to image list
2695
* i [I] COULD be an index?
2696
* dwFilter [I] ???
2697
*
2698
* RETURNS
2699
* Success: TRUE ???
2700
* Failure: FALSE ???
2701
*
2702
* BUGS
2703
* This is an UNDOCUMENTED function!!!!
2704
* empty stub.
2705
*/
2706
2707
BOOL WINAPI
2708
ImageList_SetFilter (HIMAGELIST himl, INT i, DWORD dwFilter)
2709
{
2710
FIXME("%p, %d, %#lx:empty stub!\n", himl, i, dwFilter);
2711
2712
return FALSE;
2713
}
2714
2715
2716
/*************************************************************************
2717
* ImageList_SetFlags [COMCTL32.@]
2718
*
2719
* Sets the image list flags.
2720
*
2721
* PARAMS
2722
* himl [I] Handle to image list
2723
* flags [I] Flags to set
2724
*
2725
* RETURNS
2726
* Old flags?
2727
*
2728
* BUGS
2729
* Stub.
2730
*/
2731
2732
DWORD WINAPI
2733
ImageList_SetFlags(HIMAGELIST himl, DWORD flags)
2734
{
2735
FIXME("(%p %#lx):empty stub\n", himl, flags);
2736
return 0;
2737
}
2738
2739
2740
/*************************************************************************
2741
* ImageList_SetIconSize [COMCTL32.@]
2742
*
2743
* Sets the image size of the bitmap and deletes all images.
2744
*
2745
* PARAMS
2746
* himl [I] handle to image list
2747
* cx [I] image width
2748
* cy [I] image height
2749
*
2750
* RETURNS
2751
* Success: TRUE
2752
* Failure: FALSE
2753
*/
2754
2755
BOOL WINAPI
2756
ImageList_SetIconSize (HIMAGELIST himl, INT cx, INT cy)
2757
{
2758
INT nCount;
2759
HBITMAP hbmNew;
2760
2761
if (!is_valid(himl))
2762
return FALSE;
2763
2764
/* remove all images */
2765
himl->cMaxImage = himl->cInitial + 1;
2766
himl->cCurImage = 0;
2767
himl->cx = cx;
2768
himl->cy = cy;
2769
2770
/* initialize overlay mask indices */
2771
for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
2772
himl->nOvlIdx[nCount] = -1;
2773
2774
hbmNew = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage);
2775
SelectObject (himl->hdcImage, hbmNew);
2776
DeleteObject (himl->hbmImage);
2777
himl->hbmImage = hbmNew;
2778
2779
if (himl->hbmMask) {
2780
SIZE sz;
2781
imagelist_get_bitmap_size(himl, himl->cMaxImage, &sz);
2782
hbmNew = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
2783
SelectObject (himl->hdcMask, hbmNew);
2784
DeleteObject (himl->hbmMask);
2785
himl->hbmMask = hbmNew;
2786
}
2787
2788
return TRUE;
2789
}
2790
2791
2792
/*************************************************************************
2793
* ImageList_SetImageCount [COMCTL32.@]
2794
*
2795
* Resizes an image list to the specified number of images.
2796
*
2797
* PARAMS
2798
* himl [I] handle to image list
2799
* iImageCount [I] number of images in the image list
2800
*
2801
* RETURNS
2802
* Success: TRUE
2803
* Failure: FALSE
2804
*/
2805
2806
BOOL WINAPI
2807
ImageList_SetImageCount (HIMAGELIST himl, UINT iImageCount)
2808
{
2809
HDC hdcBitmap;
2810
HBITMAP hbmNewBitmap, hbmOld;
2811
INT nNewCount, nCopyCount;
2812
2813
TRACE("%p %d\n",himl,iImageCount);
2814
2815
if (!is_valid(himl))
2816
return FALSE;
2817
2818
nNewCount = iImageCount + 1;
2819
nCopyCount = min(himl->cCurImage, iImageCount);
2820
2821
hdcBitmap = CreateCompatibleDC (0);
2822
2823
hbmNewBitmap = ImageList_CreateImage(hdcBitmap, himl, nNewCount);
2824
2825
if (hbmNewBitmap != 0)
2826
{
2827
hbmOld = SelectObject (hdcBitmap, hbmNewBitmap);
2828
imagelist_copy_images( himl, himl->hdcImage, hdcBitmap, 0, nCopyCount, 0 );
2829
SelectObject (hdcBitmap, hbmOld);
2830
2831
/* FIXME: delete 'empty' image space? */
2832
2833
SelectObject (himl->hdcImage, hbmNewBitmap);
2834
DeleteObject (himl->hbmImage);
2835
himl->hbmImage = hbmNewBitmap;
2836
}
2837
else
2838
ERR("Could not create new image bitmap!\n");
2839
2840
if (himl->hbmMask)
2841
{
2842
SIZE sz;
2843
imagelist_get_bitmap_size( himl, nNewCount, &sz );
2844
hbmNewBitmap = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
2845
if (hbmNewBitmap != 0)
2846
{
2847
hbmOld = SelectObject (hdcBitmap, hbmNewBitmap);
2848
imagelist_copy_images( himl, himl->hdcMask, hdcBitmap, 0, nCopyCount, 0 );
2849
SelectObject (hdcBitmap, hbmOld);
2850
2851
/* FIXME: delete 'empty' image space? */
2852
2853
SelectObject (himl->hdcMask, hbmNewBitmap);
2854
DeleteObject (himl->hbmMask);
2855
himl->hbmMask = hbmNewBitmap;
2856
}
2857
else
2858
ERR("Could not create new mask bitmap!\n");
2859
}
2860
2861
DeleteDC (hdcBitmap);
2862
2863
himl->item_flags = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, himl->item_flags,
2864
nNewCount * sizeof(*himl->item_flags));
2865
2866
/* Update max image count and current image count */
2867
himl->cMaxImage = nNewCount;
2868
himl->cCurImage = iImageCount;
2869
2870
return TRUE;
2871
}
2872
2873
2874
/*************************************************************************
2875
* ImageList_SetOverlayImage [COMCTL32.@]
2876
*
2877
* Assigns an overlay mask index to an existing image in an image list.
2878
*
2879
* PARAMS
2880
* himl [I] handle to image list
2881
* iImage [I] image index
2882
* iOverlay [I] overlay mask index
2883
*
2884
* RETURNS
2885
* Success: TRUE
2886
* Failure: FALSE
2887
*/
2888
2889
BOOL WINAPI
2890
ImageList_SetOverlayImage (HIMAGELIST himl, INT iImage, INT iOverlay)
2891
{
2892
if (!is_valid(himl))
2893
return FALSE;
2894
if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
2895
return FALSE;
2896
if ((iImage!=-1) && ((iImage < 0) || (iImage > himl->cCurImage)))
2897
return FALSE;
2898
himl->nOvlIdx[iOverlay - 1] = iImage;
2899
return TRUE;
2900
}
2901
2902
2903
2904
/* helper for ImageList_Write - write bitmap to pstm
2905
* currently everything is written as 24 bit RGB, except masks
2906
*/
2907
static BOOL _write_bitmap(HBITMAP hBitmap, IStream *pstm)
2908
{
2909
LPBITMAPFILEHEADER bmfh;
2910
LPBITMAPINFOHEADER bmih;
2911
LPBYTE data = NULL, lpBits;
2912
BITMAP bm;
2913
INT bitCount, sizeImage, offBits, totalSize;
2914
HDC xdc;
2915
BOOL result = FALSE;
2916
2917
if (!GetObjectW(hBitmap, sizeof(BITMAP), &bm))
2918
return FALSE;
2919
2920
bitCount = bm.bmBitsPixel;
2921
sizeImage = get_dib_stride(bm.bmWidth, bitCount) * bm.bmHeight;
2922
2923
totalSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
2924
if(bitCount <= 8)
2925
totalSize += (1 << bitCount) * sizeof(RGBQUAD);
2926
offBits = totalSize;
2927
totalSize += sizeImage;
2928
2929
data = Alloc(totalSize);
2930
bmfh = (LPBITMAPFILEHEADER)data;
2931
bmih = (LPBITMAPINFOHEADER)(data + sizeof(BITMAPFILEHEADER));
2932
lpBits = data + offBits;
2933
2934
/* setup BITMAPFILEHEADER */
2935
bmfh->bfType = (('M' << 8) | 'B');
2936
bmfh->bfSize = offBits;
2937
bmfh->bfReserved1 = 0;
2938
bmfh->bfReserved2 = 0;
2939
bmfh->bfOffBits = offBits;
2940
2941
/* setup BITMAPINFOHEADER */
2942
bmih->biSize = sizeof(BITMAPINFOHEADER);
2943
bmih->biWidth = bm.bmWidth;
2944
bmih->biHeight = bm.bmHeight;
2945
bmih->biPlanes = 1;
2946
bmih->biBitCount = bitCount;
2947
bmih->biCompression = BI_RGB;
2948
bmih->biSizeImage = sizeImage;
2949
bmih->biXPelsPerMeter = 0;
2950
bmih->biYPelsPerMeter = 0;
2951
bmih->biClrUsed = 0;
2952
bmih->biClrImportant = 0;
2953
2954
xdc = GetDC(0);
2955
result = GetDIBits(xdc, hBitmap, 0, bm.bmHeight, lpBits, (BITMAPINFO *)bmih, DIB_RGB_COLORS) == bm.bmHeight;
2956
ReleaseDC(0, xdc);
2957
if (!result)
2958
goto failed;
2959
2960
TRACE("width %lu, height %lu, planes %u, bpp %u\n",
2961
bmih->biWidth, bmih->biHeight,
2962
bmih->biPlanes, bmih->biBitCount);
2963
2964
if(FAILED(IStream_Write(pstm, data, totalSize, NULL)))
2965
goto failed;
2966
2967
result = TRUE;
2968
2969
failed:
2970
Free(data);
2971
2972
return result;
2973
}
2974
2975
#if __WINE_COMCTL32_VERSION == 6
2976
/*************************************************************************
2977
* ImageList_WriteEx [COMCTL32.@]
2978
*/
2979
HRESULT WINAPI ImageList_WriteEx(HIMAGELIST himl, DWORD flags, IStream *pstm)
2980
{
2981
FIXME("%p %#lx %p: semi-stub\n", himl, flags, pstm);
2982
return ImageList_Write(himl, pstm) ? S_OK : E_FAIL;
2983
}
2984
#endif /* __WINE_COMCTL32_VERSION == 6 */
2985
2986
/*************************************************************************
2987
* ImageList_Write [COMCTL32.@]
2988
*
2989
* Writes an image list to a stream.
2990
*
2991
* PARAMS
2992
* himl [I] handle to image list
2993
* pstm [O] Pointer to a stream.
2994
*
2995
* RETURNS
2996
* Success: TRUE
2997
* Failure: FALSE
2998
*
2999
* BUGS
3000
* probably.
3001
*/
3002
3003
BOOL WINAPI ImageList_Write(HIMAGELIST himl, IStream *pstm)
3004
{
3005
ILHEAD ilHead;
3006
int i;
3007
3008
TRACE("%p %p\n", himl, pstm);
3009
3010
if (!is_valid(himl))
3011
return FALSE;
3012
3013
ilHead.usMagic = (('L' << 8) | 'I');
3014
ilHead.usVersion = 0x101;
3015
ilHead.cCurImage = himl->cCurImage;
3016
ilHead.cMaxImage = himl->cMaxImage;
3017
ilHead.cGrow = himl->cGrow;
3018
ilHead.cx = himl->cx;
3019
ilHead.cy = himl->cy;
3020
ilHead.bkcolor = himl->clrBk;
3021
ilHead.flags = himl->flags;
3022
for(i = 0; i < 4; i++) {
3023
ilHead.ovls[i] = himl->nOvlIdx[i];
3024
}
3025
3026
TRACE("cx %u, cy %u, flags 0x04%x, cCurImage %u, cMaxImage %u\n",
3027
ilHead.cx, ilHead.cy, ilHead.flags, ilHead.cCurImage, ilHead.cMaxImage);
3028
3029
if(FAILED(IStream_Write(pstm, &ilHead, sizeof(ILHEAD), NULL)))
3030
return FALSE;
3031
3032
/* write the bitmap */
3033
if(!_write_bitmap(himl->hbmImage, pstm))
3034
return FALSE;
3035
3036
/* write the mask if we have one */
3037
if(himl->flags & ILC_MASK) {
3038
if(!_write_bitmap(himl->hbmMask, pstm))
3039
return FALSE;
3040
}
3041
3042
return TRUE;
3043
}
3044
3045
3046
static HBITMAP ImageList_CreateImage(HDC hdc, HIMAGELIST himl, UINT count)
3047
{
3048
HBITMAP hbmNewBitmap;
3049
UINT ilc = (himl->flags & 0xFE);
3050
SIZE sz;
3051
3052
imagelist_get_bitmap_size( himl, count, &sz );
3053
3054
if ((ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32) || ilc == ILC_COLOR)
3055
{
3056
char buffer[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
3057
BITMAPINFO *bmi = (BITMAPINFO *)buffer;
3058
3059
TRACE("Creating DIBSection %ld x %ld, %d Bits per Pixel\n",
3060
sz.cx, sz.cy, himl->uBitsPixel);
3061
3062
memset( buffer, 0, sizeof(buffer) );
3063
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
3064
bmi->bmiHeader.biWidth = sz.cx;
3065
bmi->bmiHeader.biHeight = sz.cy;
3066
bmi->bmiHeader.biPlanes = 1;
3067
bmi->bmiHeader.biBitCount = himl->uBitsPixel;
3068
bmi->bmiHeader.biCompression = BI_RGB;
3069
3070
if (himl->uBitsPixel <= ILC_COLOR8)
3071
{
3072
if (!himl->color_table_set)
3073
{
3074
/* retrieve the default color map */
3075
HBITMAP tmp = CreateBitmap( 1, 1, 1, 1, NULL );
3076
GetDIBits( hdc, tmp, 0, 0, NULL, bmi, DIB_RGB_COLORS );
3077
DeleteObject( tmp );
3078
if (ilc == ILC_COLOR4)
3079
{
3080
RGBQUAD tmp;
3081
tmp = bmi->bmiColors[7];
3082
bmi->bmiColors[7] = bmi->bmiColors[8];
3083
bmi->bmiColors[8] = tmp;
3084
}
3085
}
3086
else
3087
{
3088
GetDIBColorTable(himl->hdcImage, 0, 1 << himl->uBitsPixel, bmi->bmiColors);
3089
}
3090
}
3091
hbmNewBitmap = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, NULL, 0, 0);
3092
}
3093
else /*if (ilc == ILC_COLORDDB)*/
3094
{
3095
TRACE("Creating Bitmap: %d Bits per Pixel\n", himl->uBitsPixel);
3096
3097
hbmNewBitmap = CreateBitmap (sz.cx, sz.cy, 1, himl->uBitsPixel, NULL);
3098
}
3099
TRACE("returning %p\n", hbmNewBitmap);
3100
return hbmNewBitmap;
3101
}
3102
3103
/*************************************************************************
3104
* ImageList_SetColorTable [COMCTL32.@]
3105
*
3106
* Sets the color table of an image list.
3107
*
3108
* PARAMS
3109
* himl [I] Handle to the image list.
3110
* uStartIndex [I] The first index to set.
3111
* cEntries [I] Number of entries to set.
3112
* prgb [I] New color information for color table for the image list.
3113
*
3114
* RETURNS
3115
* Success: Number of entries in the table that were set.
3116
* Failure: Zero.
3117
*
3118
* SEE
3119
* ImageList_Create(), SetDIBColorTable()
3120
*/
3121
3122
UINT WINAPI
3123
ImageList_SetColorTable(HIMAGELIST himl, UINT uStartIndex, UINT cEntries, const RGBQUAD *prgb)
3124
{
3125
TRACE("(%p, %d, %d, %p)\n", himl, uStartIndex, cEntries, prgb);
3126
himl->color_table_set = TRUE;
3127
return SetDIBColorTable(himl->hdcImage, uStartIndex, cEntries, prgb);
3128
}
3129
3130
#if __WINE_COMCTL32_VERSION == 6
3131
/*************************************************************************
3132
* ImageList_CoCreateInstance [COMCTL32.@]
3133
*
3134
* Creates a new imagelist instance and returns an interface pointer to it.
3135
*
3136
* PARAMS
3137
* rclsid [I] A reference to the CLSID (CLSID_ImageList).
3138
* punkOuter [I] Pointer to IUnknown interface for aggregation, if desired
3139
* riid [I] Identifier of the requested interface.
3140
* ppv [O] Returns the address of the pointer requested, or NULL.
3141
*
3142
* RETURNS
3143
* Success: S_OK.
3144
* Failure: Error value.
3145
*/
3146
HRESULT WINAPI
3147
ImageList_CoCreateInstance (REFCLSID rclsid, const IUnknown *punkOuter, REFIID riid, void **ppv)
3148
{
3149
TRACE("(%s,%p,%s,%p)\n", debugstr_guid(rclsid), punkOuter, debugstr_guid(riid), ppv);
3150
3151
if (!IsEqualCLSID(&CLSID_ImageList, rclsid))
3152
return E_NOINTERFACE;
3153
3154
return ImageListImpl_CreateInstance(punkOuter, riid, ppv);
3155
}
3156
#endif /* __WINE_COMCTL32_VERSION == 6 */
3157
3158
3159
/*************************************************************************
3160
* IImageList implementation
3161
*/
3162
3163
static HRESULT WINAPI ImageListImpl_QueryInterface(IImageList2 *iface,
3164
REFIID iid, void **ppv)
3165
{
3166
HIMAGELIST imgl = impl_from_IImageList2(iface);
3167
3168
TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
3169
3170
if (!ppv) return E_INVALIDARG;
3171
3172
if (IsEqualIID(&IID_IUnknown, iid) ||
3173
IsEqualIID(&IID_IImageList, iid) ||
3174
IsEqualIID(&IID_IImageList2, iid))
3175
{
3176
*ppv = &imgl->IImageList2_iface;
3177
}
3178
else
3179
{
3180
*ppv = NULL;
3181
return E_NOINTERFACE;
3182
}
3183
3184
IImageList2_AddRef(iface);
3185
return S_OK;
3186
}
3187
3188
static ULONG WINAPI ImageListImpl_AddRef(IImageList2 *iface)
3189
{
3190
HIMAGELIST imgl = impl_from_IImageList2(iface);
3191
ULONG ref = InterlockedIncrement(&imgl->ref);
3192
3193
TRACE("%p, refcount %lu\n", iface, ref);
3194
return ref;
3195
}
3196
3197
static ULONG WINAPI ImageListImpl_Release(IImageList2 *iface)
3198
{
3199
HIMAGELIST This = impl_from_IImageList2(iface);
3200
ULONG ref = InterlockedDecrement(&This->ref);
3201
3202
TRACE("%p, refcount %lu\n", iface, ref);
3203
3204
if (ref == 0)
3205
{
3206
/* delete image bitmaps */
3207
if (This->hbmImage) DeleteObject (This->hbmImage);
3208
if (This->hbmMask) DeleteObject (This->hbmMask);
3209
3210
/* delete image & mask DCs */
3211
if (This->hdcImage) DeleteDC (This->hdcImage);
3212
if (This->hdcMask) DeleteDC (This->hdcMask);
3213
3214
/* delete blending brushes */
3215
if (This->hbrBlend25) DeleteObject (This->hbrBlend25);
3216
if (This->hbrBlend50) DeleteObject (This->hbrBlend50);
3217
3218
This->IImageList2_iface.lpVtbl = NULL;
3219
This->magic = 0;
3220
Free(This->item_flags);
3221
Free(This);
3222
}
3223
3224
return ref;
3225
}
3226
3227
static HRESULT WINAPI ImageListImpl_Add(IImageList2 *iface, HBITMAP hbmImage,
3228
HBITMAP hbmMask, int *pi)
3229
{
3230
HIMAGELIST imgl = impl_from_IImageList2(iface);
3231
int ret;
3232
3233
if (!pi)
3234
return E_FAIL;
3235
3236
ret = ImageList_Add(imgl, hbmImage, hbmMask);
3237
3238
if (ret == -1)
3239
return E_FAIL;
3240
3241
*pi = ret;
3242
return S_OK;
3243
}
3244
3245
static HRESULT WINAPI ImageListImpl_ReplaceIcon(IImageList2 *iface, int i,
3246
HICON hicon, int *pi)
3247
{
3248
HIMAGELIST imgl = impl_from_IImageList2(iface);
3249
int ret;
3250
3251
if (!pi)
3252
return E_FAIL;
3253
3254
ret = ImageList_ReplaceIcon(imgl, i, hicon);
3255
3256
if (ret == -1)
3257
return E_FAIL;
3258
3259
*pi = ret;
3260
return S_OK;
3261
}
3262
3263
static HRESULT WINAPI ImageListImpl_SetOverlayImage(IImageList2 *iface,
3264
int iImage, int iOverlay)
3265
{
3266
HIMAGELIST imgl = impl_from_IImageList2(iface);
3267
return ImageList_SetOverlayImage(imgl, iImage, iOverlay) ? S_OK : E_FAIL;
3268
}
3269
3270
static HRESULT WINAPI ImageListImpl_Replace(IImageList2 *iface, int i,
3271
HBITMAP hbmImage, HBITMAP hbmMask)
3272
{
3273
HIMAGELIST imgl = impl_from_IImageList2(iface);
3274
return ImageList_Replace(imgl, i, hbmImage, hbmMask) ? S_OK : E_FAIL;
3275
}
3276
3277
static HRESULT WINAPI ImageListImpl_AddMasked(IImageList2 *iface, HBITMAP hbmImage,
3278
COLORREF crMask, int *pi)
3279
{
3280
HIMAGELIST imgl = impl_from_IImageList2(iface);
3281
int ret;
3282
3283
if (!pi)
3284
return E_FAIL;
3285
3286
ret = ImageList_AddMasked(imgl, hbmImage, crMask);
3287
3288
if (ret == -1)
3289
return E_FAIL;
3290
3291
*pi = ret;
3292
return S_OK;
3293
}
3294
3295
static HRESULT WINAPI ImageListImpl_Draw(IImageList2 *iface,
3296
IMAGELISTDRAWPARAMS *pimldp)
3297
{
3298
HIMAGELIST imgl = impl_from_IImageList2(iface);
3299
HIMAGELIST old_himl;
3300
int ret;
3301
3302
/* As far as I can tell, Windows simply ignores the contents of pimldp->himl
3303
so we shall simulate the same */
3304
old_himl = pimldp->himl;
3305
pimldp->himl = imgl;
3306
3307
ret = ImageList_DrawIndirect(pimldp);
3308
3309
pimldp->himl = old_himl;
3310
return ret ? S_OK : E_INVALIDARG;
3311
}
3312
3313
static HRESULT WINAPI ImageListImpl_Remove(IImageList2 *iface, int i)
3314
{
3315
HIMAGELIST imgl = impl_from_IImageList2(iface);
3316
return (ImageList_Remove(imgl, i) == 0) ? E_INVALIDARG : S_OK;
3317
}
3318
3319
static HRESULT WINAPI ImageListImpl_GetIcon(IImageList2 *iface, int i, UINT flags,
3320
HICON *picon)
3321
{
3322
HIMAGELIST imgl = impl_from_IImageList2(iface);
3323
HICON hIcon;
3324
3325
if (!picon)
3326
return E_FAIL;
3327
3328
hIcon = ImageList_GetIcon(imgl, i, flags);
3329
3330
if (hIcon == NULL)
3331
return E_FAIL;
3332
3333
*picon = hIcon;
3334
return S_OK;
3335
}
3336
3337
static HRESULT WINAPI ImageListImpl_GetImageInfo(IImageList2 *iface, int i,
3338
IMAGEINFO *pImageInfo)
3339
{
3340
HIMAGELIST imgl = impl_from_IImageList2(iface);
3341
return ImageList_GetImageInfo(imgl, i, pImageInfo) ? S_OK : E_FAIL;
3342
}
3343
3344
static HRESULT WINAPI ImageListImpl_Copy(IImageList2 *iface, int dst_index,
3345
IUnknown *unk_src, int src_index, UINT flags)
3346
{
3347
HIMAGELIST imgl = impl_from_IImageList2(iface);
3348
IImageList *src = NULL;
3349
HRESULT ret;
3350
3351
if (!unk_src)
3352
return E_FAIL;
3353
3354
/* TODO: Add test for IID_ImageList2 too */
3355
if (FAILED(IUnknown_QueryInterface(unk_src, &IID_IImageList,
3356
(void **) &src)))
3357
return E_FAIL;
3358
3359
if (ImageList_Copy(imgl, dst_index, (HIMAGELIST) src, src_index, flags))
3360
ret = S_OK;
3361
else
3362
ret = E_FAIL;
3363
3364
IImageList_Release(src);
3365
return ret;
3366
}
3367
3368
static HRESULT WINAPI ImageListImpl_Merge(IImageList2 *iface, int i1,
3369
IUnknown *punk2, int i2, int dx, int dy, REFIID riid, void **ppv)
3370
{
3371
HIMAGELIST imgl = impl_from_IImageList2(iface);
3372
IImageList *iml2 = NULL;
3373
HIMAGELIST merged;
3374
HRESULT ret = E_FAIL;
3375
3376
TRACE("(%p)->(%d %p %d %d %d %s %p)\n", iface, i1, punk2, i2, dx, dy, debugstr_guid(riid), ppv);
3377
3378
/* TODO: Add test for IID_ImageList2 too */
3379
if (FAILED(IUnknown_QueryInterface(punk2, &IID_IImageList,
3380
(void **) &iml2)))
3381
return E_FAIL;
3382
3383
merged = ImageList_Merge(imgl, i1, (HIMAGELIST) iml2, i2, dx, dy);
3384
3385
/* Get the interface for the new image list */
3386
if (merged)
3387
{
3388
ret = HIMAGELIST_QueryInterface(merged, riid, ppv);
3389
ImageList_Destroy(merged);
3390
}
3391
3392
IImageList_Release(iml2);
3393
return ret;
3394
}
3395
3396
static HRESULT WINAPI ImageListImpl_Clone(IImageList2 *iface, REFIID riid, void **ppv)
3397
{
3398
HIMAGELIST imgl = impl_from_IImageList2(iface);
3399
HIMAGELIST clone;
3400
HRESULT ret = E_FAIL;
3401
3402
TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppv);
3403
3404
clone = ImageList_Duplicate(imgl);
3405
3406
/* Get the interface for the new image list */
3407
if (clone)
3408
{
3409
ret = HIMAGELIST_QueryInterface(clone, riid, ppv);
3410
ImageList_Destroy(clone);
3411
}
3412
3413
return ret;
3414
}
3415
3416
static HRESULT WINAPI ImageListImpl_GetImageRect(IImageList2 *iface, int i,
3417
RECT *prc)
3418
{
3419
HIMAGELIST imgl = impl_from_IImageList2(iface);
3420
IMAGEINFO info;
3421
3422
if (!prc)
3423
return E_FAIL;
3424
3425
if (!ImageList_GetImageInfo(imgl, i, &info))
3426
return E_FAIL;
3427
3428
*prc = info.rcImage;
3429
3430
return S_OK;
3431
}
3432
3433
static HRESULT WINAPI ImageListImpl_GetIconSize(IImageList2 *iface, int *cx,
3434
int *cy)
3435
{
3436
HIMAGELIST imgl = impl_from_IImageList2(iface);
3437
return ImageList_GetIconSize(imgl, cx, cy) ? S_OK : E_INVALIDARG;
3438
}
3439
3440
static HRESULT WINAPI ImageListImpl_SetIconSize(IImageList2 *iface, int cx,
3441
int cy)
3442
{
3443
HIMAGELIST imgl = impl_from_IImageList2(iface);
3444
return ImageList_SetIconSize(imgl, cx, cy) ? S_OK : E_FAIL;
3445
}
3446
3447
static HRESULT WINAPI ImageListImpl_GetImageCount(IImageList2 *iface, int *pi)
3448
{
3449
HIMAGELIST imgl = impl_from_IImageList2(iface);
3450
*pi = ImageList_GetImageCount(imgl);
3451
return S_OK;
3452
}
3453
3454
static HRESULT WINAPI ImageListImpl_SetImageCount(IImageList2 *iface, UINT count)
3455
{
3456
HIMAGELIST imgl = impl_from_IImageList2(iface);
3457
return ImageList_SetImageCount(imgl, count) ? S_OK : E_FAIL;
3458
}
3459
3460
static HRESULT WINAPI ImageListImpl_SetBkColor(IImageList2 *iface, COLORREF clrBk,
3461
COLORREF *pclr)
3462
{
3463
HIMAGELIST imgl = impl_from_IImageList2(iface);
3464
*pclr = ImageList_SetBkColor(imgl, clrBk);
3465
return S_OK;
3466
}
3467
3468
static HRESULT WINAPI ImageListImpl_GetBkColor(IImageList2 *iface, COLORREF *pclr)
3469
{
3470
HIMAGELIST imgl = impl_from_IImageList2(iface);
3471
*pclr = ImageList_GetBkColor(imgl);
3472
return S_OK;
3473
}
3474
3475
static HRESULT WINAPI ImageListImpl_BeginDrag(IImageList2 *iface, int iTrack,
3476
int dxHotspot, int dyHotspot)
3477
{
3478
HIMAGELIST imgl = impl_from_IImageList2(iface);
3479
return ImageList_BeginDrag(imgl, iTrack, dxHotspot, dyHotspot) ? S_OK : E_FAIL;
3480
}
3481
3482
static HRESULT WINAPI ImageListImpl_EndDrag(IImageList2 *iface)
3483
{
3484
ImageList_EndDrag();
3485
return S_OK;
3486
}
3487
3488
static HRESULT WINAPI ImageListImpl_DragEnter(IImageList2 *iface, HWND hwndLock,
3489
int x, int y)
3490
{
3491
return ImageList_DragEnter(hwndLock, x, y) ? S_OK : E_FAIL;
3492
}
3493
3494
static HRESULT WINAPI ImageListImpl_DragLeave(IImageList2 *iface, HWND hwndLock)
3495
{
3496
return ImageList_DragLeave(hwndLock) ? S_OK : E_FAIL;
3497
}
3498
3499
static HRESULT WINAPI ImageListImpl_DragMove(IImageList2 *iface, int x, int y)
3500
{
3501
return ImageList_DragMove(x, y) ? S_OK : E_FAIL;
3502
}
3503
3504
static HRESULT WINAPI ImageListImpl_SetDragCursorImage(IImageList2 *iface,
3505
IUnknown *punk, int iDrag, int dxHotspot, int dyHotspot)
3506
{
3507
IImageList *iml2 = NULL;
3508
BOOL ret;
3509
3510
if (!punk)
3511
return E_FAIL;
3512
3513
/* TODO: Add test for IID_ImageList2 too */
3514
if (FAILED(IUnknown_QueryInterface(punk, &IID_IImageList,
3515
(void **) &iml2)))
3516
return E_FAIL;
3517
3518
ret = ImageList_SetDragCursorImage((HIMAGELIST) iml2, iDrag, dxHotspot,
3519
dyHotspot);
3520
3521
IImageList_Release(iml2);
3522
3523
return ret ? S_OK : E_FAIL;
3524
}
3525
3526
static HRESULT WINAPI ImageListImpl_DragShowNolock(IImageList2 *iface, BOOL fShow)
3527
{
3528
return ImageList_DragShowNolock(fShow) ? S_OK : E_FAIL;
3529
}
3530
3531
static HRESULT WINAPI ImageListImpl_GetDragImage(IImageList2 *iface, POINT *ppt,
3532
POINT *pptHotspot, REFIID riid, PVOID *ppv)
3533
{
3534
HRESULT ret = E_FAIL;
3535
HIMAGELIST hNew;
3536
3537
if (!ppv)
3538
return E_FAIL;
3539
3540
hNew = ImageList_GetDragImage(ppt, pptHotspot);
3541
3542
/* Get the interface for the new image list */
3543
if (hNew)
3544
{
3545
IImageList *idrag = (IImageList*)hNew;
3546
3547
ret = HIMAGELIST_QueryInterface(hNew, riid, ppv);
3548
IImageList_Release(idrag);
3549
}
3550
3551
return ret;
3552
}
3553
3554
static HRESULT WINAPI ImageListImpl_GetItemFlags(IImageList2 *iface, int i, DWORD *flags)
3555
{
3556
HIMAGELIST This = impl_from_IImageList2(iface);
3557
3558
if (i < 0 || i >= This->cCurImage)
3559
return E_INVALIDARG;
3560
3561
*flags = This->item_flags[i];
3562
3563
return S_OK;
3564
}
3565
3566
static HRESULT WINAPI ImageListImpl_GetOverlayImage(IImageList2 *iface, int iOverlay,
3567
int *piIndex)
3568
{
3569
HIMAGELIST This = impl_from_IImageList2(iface);
3570
int i;
3571
3572
if ((iOverlay < 0) || (iOverlay > This->cCurImage))
3573
return E_FAIL;
3574
3575
for (i = 0; i < MAX_OVERLAYIMAGE; i++)
3576
{
3577
if (This->nOvlIdx[i] == iOverlay)
3578
{
3579
*piIndex = i + 1;
3580
return S_OK;
3581
}
3582
}
3583
3584
return E_FAIL;
3585
}
3586
3587
static HRESULT WINAPI ImageListImpl_Resize(IImageList2 *iface, INT cx, INT cy)
3588
{
3589
FIXME("(%p)->(%d %d): stub\n", iface, cx, cy);
3590
return E_NOTIMPL;
3591
}
3592
3593
static HRESULT WINAPI ImageListImpl_GetOriginalSize(IImageList2 *iface, INT image, DWORD flags, INT *cx, INT *cy)
3594
{
3595
FIXME("(%p)->(%d %lx %p %p): stub\n", iface, image, flags, cx, cy);
3596
return E_NOTIMPL;
3597
}
3598
3599
static HRESULT WINAPI ImageListImpl_SetOriginalSize(IImageList2 *iface, INT image, INT cx, INT cy)
3600
{
3601
FIXME("(%p)->(%d %d %d): stub\n", iface, image, cx, cy);
3602
return E_NOTIMPL;
3603
}
3604
3605
static HRESULT WINAPI ImageListImpl_SetCallback(IImageList2 *iface, IUnknown *callback)
3606
{
3607
FIXME("(%p)->(%p): stub\n", iface, callback);
3608
return E_NOTIMPL;
3609
}
3610
3611
static HRESULT WINAPI ImageListImpl_GetCallback(IImageList2 *iface, REFIID riid, void **ppv)
3612
{
3613
FIXME("(%p)->(%s %p): stub\n", iface, debugstr_guid(riid), ppv);
3614
return E_NOTIMPL;
3615
}
3616
3617
static HRESULT WINAPI ImageListImpl_ForceImagePresent(IImageList2 *iface, INT image, DWORD flags)
3618
{
3619
FIXME("(%p)->(%d %lx): stub\n", iface, image, flags);
3620
return E_NOTIMPL;
3621
}
3622
3623
static HRESULT WINAPI ImageListImpl_DiscardImages(IImageList2 *iface, INT first_image, INT last_image, DWORD flags)
3624
{
3625
FIXME("(%p)->(%d %d %lx): stub\n", iface, first_image, last_image, flags);
3626
return E_NOTIMPL;
3627
}
3628
3629
static HRESULT WINAPI ImageListImpl_PreloadImages(IImageList2 *iface, IMAGELISTDRAWPARAMS *params)
3630
{
3631
FIXME("(%p)->(%p): stub\n", iface, params);
3632
return E_NOTIMPL;
3633
}
3634
3635
static HRESULT WINAPI ImageListImpl_GetStatistics(IImageList2 *iface, IMAGELISTSTATS *stats)
3636
{
3637
FIXME("(%p)->(%p): stub\n", iface, stats);
3638
return E_NOTIMPL;
3639
}
3640
3641
static HRESULT WINAPI ImageListImpl_Initialize(IImageList2 *iface, INT cx, INT cy, UINT flags, INT initial, INT grow)
3642
{
3643
HIMAGELIST himl = impl_from_IImageList2(iface);
3644
INT nCount;
3645
HBITMAP hbmTemp;
3646
UINT ilc = (flags & 0xFE);
3647
static const WORD aBitBlend25[] =
3648
{0xAA, 0x00, 0x55, 0x00, 0xAA, 0x00, 0x55, 0x00};
3649
static const WORD aBitBlend50[] =
3650
{0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA};
3651
3652
TRACE("(%p)->(%d %d %d %d %d)\n", iface, cx, cy, flags, initial, grow);
3653
3654
if (cx < 0 || cy < 0) return E_INVALIDARG;
3655
if (!((flags&ILC_COLORDDB) == ILC_COLORDDB) && (cx == 0 || cy == 0)) return E_INVALIDARG;
3656
3657
grow = (WORD)((max( grow, 1 ) + 3) & ~3);
3658
3659
if (grow > 256)
3660
{
3661
/* Windows doesn't limit the size here, but X11 doesn't let us allocate such huge bitmaps */
3662
WARN( "grow %d too large, limiting to 256\n", grow );
3663
grow = 256;
3664
}
3665
3666
himl->cx = cx;
3667
himl->cy = cy;
3668
himl->flags = flags;
3669
himl->cMaxImage = initial + 1;
3670
himl->cInitial = initial;
3671
himl->cGrow = grow;
3672
himl->clrFg = CLR_DEFAULT;
3673
himl->clrBk = CLR_NONE;
3674
himl->color_table_set = FALSE;
3675
3676
/* initialize overlay mask indices */
3677
for (nCount = 0; nCount < MAX_OVERLAYIMAGE; nCount++)
3678
himl->nOvlIdx[nCount] = -1;
3679
3680
/* Create Image & Mask DCs */
3681
himl->hdcImage = CreateCompatibleDC (0);
3682
if (!himl->hdcImage)
3683
return E_FAIL;
3684
if (himl->flags & ILC_MASK){
3685
himl->hdcMask = CreateCompatibleDC(0);
3686
if (!himl->hdcMask)
3687
return E_FAIL;
3688
}
3689
3690
/* Default to ILC_COLOR4 if none of the ILC_COLOR* flags are specified */
3691
if (ilc == ILC_COLOR)
3692
{
3693
ilc = ILC_COLOR4;
3694
himl->flags |= ILC_COLOR4;
3695
}
3696
3697
if (ilc >= ILC_COLOR4 && ilc <= ILC_COLOR32)
3698
himl->uBitsPixel = ilc;
3699
else
3700
himl->uBitsPixel = (UINT)GetDeviceCaps (himl->hdcImage, BITSPIXEL);
3701
3702
if (himl->cMaxImage > 0) {
3703
himl->hbmImage = ImageList_CreateImage(himl->hdcImage, himl, himl->cMaxImage);
3704
SelectObject(himl->hdcImage, himl->hbmImage);
3705
} else
3706
himl->hbmImage = 0;
3707
3708
if ((himl->cMaxImage > 0) && (himl->flags & ILC_MASK)) {
3709
SIZE sz;
3710
3711
imagelist_get_bitmap_size(himl, himl->cMaxImage, &sz);
3712
himl->hbmMask = CreateBitmap (sz.cx, sz.cy, 1, 1, NULL);
3713
if (himl->hbmMask == 0) {
3714
ERR("Error creating mask bitmap!\n");
3715
return E_FAIL;
3716
}
3717
SelectObject(himl->hdcMask, himl->hbmMask);
3718
}
3719
else
3720
himl->hbmMask = 0;
3721
3722
himl->item_flags = Alloc( himl->cMaxImage * sizeof(*himl->item_flags) );
3723
3724
/* create blending brushes */
3725
hbmTemp = CreateBitmap (8, 8, 1, 1, aBitBlend25);
3726
himl->hbrBlend25 = CreatePatternBrush (hbmTemp);
3727
DeleteObject (hbmTemp);
3728
3729
hbmTemp = CreateBitmap (8, 8, 1, 1, aBitBlend50);
3730
himl->hbrBlend50 = CreatePatternBrush (hbmTemp);
3731
DeleteObject (hbmTemp);
3732
3733
TRACE("created imagelist %p\n", himl);
3734
return S_OK;
3735
3736
}
3737
3738
static HRESULT WINAPI ImageListImpl_Replace2(IImageList2 *iface, INT i, HBITMAP image, HBITMAP mask, IUnknown *unk, DWORD flags)
3739
{
3740
FIXME("(%p)->(%d %p %p %p %lx): stub\n", iface, i, image, mask, unk, flags);
3741
return E_NOTIMPL;
3742
}
3743
3744
static HRESULT WINAPI ImageListImpl_ReplaceFromImageList(IImageList2 *iface, INT i, IImageList *imagelist, INT src,
3745
IUnknown *unk, DWORD flags)
3746
{
3747
FIXME("(%p)->(%d %p %d %p %lx): stub\n", iface, i, imagelist, src, unk, flags);
3748
return E_NOTIMPL;
3749
}
3750
3751
static const IImageList2Vtbl ImageListImpl_Vtbl = {
3752
ImageListImpl_QueryInterface,
3753
ImageListImpl_AddRef,
3754
ImageListImpl_Release,
3755
ImageListImpl_Add,
3756
ImageListImpl_ReplaceIcon,
3757
ImageListImpl_SetOverlayImage,
3758
ImageListImpl_Replace,
3759
ImageListImpl_AddMasked,
3760
ImageListImpl_Draw,
3761
ImageListImpl_Remove,
3762
ImageListImpl_GetIcon,
3763
ImageListImpl_GetImageInfo,
3764
ImageListImpl_Copy,
3765
ImageListImpl_Merge,
3766
ImageListImpl_Clone,
3767
ImageListImpl_GetImageRect,
3768
ImageListImpl_GetIconSize,
3769
ImageListImpl_SetIconSize,
3770
ImageListImpl_GetImageCount,
3771
ImageListImpl_SetImageCount,
3772
ImageListImpl_SetBkColor,
3773
ImageListImpl_GetBkColor,
3774
ImageListImpl_BeginDrag,
3775
ImageListImpl_EndDrag,
3776
ImageListImpl_DragEnter,
3777
ImageListImpl_DragLeave,
3778
ImageListImpl_DragMove,
3779
ImageListImpl_SetDragCursorImage,
3780
ImageListImpl_DragShowNolock,
3781
ImageListImpl_GetDragImage,
3782
ImageListImpl_GetItemFlags,
3783
ImageListImpl_GetOverlayImage,
3784
ImageListImpl_Resize,
3785
ImageListImpl_GetOriginalSize,
3786
ImageListImpl_SetOriginalSize,
3787
ImageListImpl_SetCallback,
3788
ImageListImpl_GetCallback,
3789
ImageListImpl_ForceImagePresent,
3790
ImageListImpl_DiscardImages,
3791
ImageListImpl_PreloadImages,
3792
ImageListImpl_GetStatistics,
3793
ImageListImpl_Initialize,
3794
ImageListImpl_Replace2,
3795
ImageListImpl_ReplaceFromImageList
3796
};
3797
3798
static BOOL is_valid(HIMAGELIST himl)
3799
{
3800
BOOL valid;
3801
__TRY
3802
{
3803
valid = himl && himl->magic == IMAGELIST_MAGIC;
3804
}
3805
__EXCEPT_PAGE_FAULT
3806
{
3807
valid = FALSE;
3808
}
3809
__ENDTRY
3810
return valid;
3811
}
3812
3813
/*************************************************************************
3814
* HIMAGELIST_QueryInterface [COMCTL32.@]
3815
*
3816
* Returns a pointer to an IImageList or IImageList2 object for the given
3817
* HIMAGELIST.
3818
*
3819
* PARAMS
3820
* himl [I] Image list handle.
3821
* riid [I] Identifier of the requested interface.
3822
* ppv [O] Returns the address of the pointer requested, or NULL.
3823
*
3824
* RETURNS
3825
* Success: S_OK.
3826
* Failure: Error value.
3827
*/
3828
HRESULT WINAPI
3829
HIMAGELIST_QueryInterface (HIMAGELIST himl, REFIID riid, void **ppv)
3830
{
3831
TRACE("(%p,%s,%p)\n", himl, debugstr_guid(riid), ppv);
3832
return IImageList2_QueryInterface((IImageList2 *) himl, riid, ppv);
3833
}
3834
3835
static HRESULT ImageListImpl_CreateInstance(const IUnknown *pUnkOuter, REFIID iid, void** ppv)
3836
{
3837
HIMAGELIST This;
3838
HRESULT ret;
3839
3840
TRACE("(%p,%s,%p)\n", pUnkOuter, debugstr_guid(iid), ppv);
3841
3842
*ppv = NULL;
3843
3844
if (pUnkOuter) return CLASS_E_NOAGGREGATION;
3845
3846
This = Alloc(sizeof(struct _IMAGELIST));
3847
if (!This) return E_OUTOFMEMORY;
3848
3849
This->IImageList2_iface.lpVtbl = &ImageListImpl_Vtbl;
3850
This->magic = IMAGELIST_MAGIC;
3851
This->ref = 1;
3852
3853
ret = IImageList2_QueryInterface(&This->IImageList2_iface, iid, ppv);
3854
IImageList2_Release(&This->IImageList2_iface);
3855
3856
return ret;
3857
}
3858
3859