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