]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/imaglist.cpp
Implement setFont on the iOS port of wxStaticText.
[wxWidgets.git] / src / msw / imaglist.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/msw/imaglist.cpp
3// Purpose: wxImageList implementation for Win32
4// Author: Julian Smart
5// Modified by:
6// Created: 04/01/98
7// Copyright: (c) Julian Smart
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// For compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
26#ifndef WX_PRECOMP
27 #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
28 #include "wx/window.h"
29 #include "wx/icon.h"
30 #include "wx/dc.h"
31 #include "wx/string.h"
32 #include "wx/dcmemory.h"
33 #include "wx/intl.h"
34 #include "wx/log.h"
35 #include "wx/image.h"
36 #include <stdio.h>
37#endif
38
39#include "wx/imaglist.h"
40#include "wx/dc.h"
41#include "wx/msw/dc.h"
42#include "wx/msw/dib.h"
43#include "wx/msw/private.h"
44
45// ----------------------------------------------------------------------------
46// wxWin macros
47// ----------------------------------------------------------------------------
48
49IMPLEMENT_DYNAMIC_CLASS(wxImageList, wxObject)
50
51#define GetHImageList() ((HIMAGELIST)m_hImageList)
52
53// ----------------------------------------------------------------------------
54// private functions
55// ----------------------------------------------------------------------------
56
57// returns the mask if it's valid, otherwise the bitmap mask and, if it's not
58// valid neither, a "solid" mask (no transparent zones at all)
59static HBITMAP GetMaskForImage(const wxBitmap& bitmap, const wxBitmap& mask);
60
61// ============================================================================
62// implementation
63// ============================================================================
64
65// ----------------------------------------------------------------------------
66// wxImageList creation/destruction
67// ----------------------------------------------------------------------------
68
69wxImageList::wxImageList()
70{
71 m_hImageList = 0;
72}
73
74// Creates an image list
75bool wxImageList::Create(int width, int height, bool mask, int initial)
76{
77 UINT flags = 0;
78
79 // as we want to be able to use 32bpp bitmaps in the image lists, we always
80 // use ILC_COLOR32, even if the display resolution is less -- the system
81 // will make the best effort to show the bitmap if we do this resulting in
82 // quite acceptable display while using a lower depth ILC_COLOR constant
83 // (e.g. ILC_COLOR16) shows completely broken bitmaps
84#ifdef __WXWINCE__
85 flags |= ILC_COLOR;
86#else
87 flags |= ILC_COLOR32;
88#endif
89
90 if ( mask )
91 flags |= ILC_MASK;
92
93 // Grow by 1, I guess this is reasonable behaviour most of the time
94 m_hImageList = (WXHIMAGELIST) ImageList_Create(width, height, flags,
95 initial, 1);
96 if ( !m_hImageList )
97 {
98 wxLogLastError(wxT("ImageList_Create()"));
99 }
100
101 return m_hImageList != 0;
102}
103
104wxImageList::~wxImageList()
105{
106 if ( m_hImageList )
107 {
108 ImageList_Destroy(GetHImageList());
109 m_hImageList = 0;
110 }
111}
112
113// ----------------------------------------------------------------------------
114// wxImageList attributes
115// ----------------------------------------------------------------------------
116
117// Returns the number of images in the image list.
118int wxImageList::GetImageCount() const
119{
120 wxASSERT_MSG( m_hImageList, wxT("invalid image list") );
121
122 return ImageList_GetImageCount(GetHImageList());
123}
124
125// Returns the size (same for all images) of the images in the list
126bool wxImageList::GetSize(int WXUNUSED(index), int &width, int &height) const
127{
128 wxASSERT_MSG( m_hImageList, wxT("invalid image list") );
129
130 return ImageList_GetIconSize(GetHImageList(), &width, &height) != 0;
131}
132
133// ----------------------------------------------------------------------------
134// wxImageList operations
135// ----------------------------------------------------------------------------
136
137// Adds a bitmap, and optionally a mask bitmap.
138// Note that wxImageList creates new bitmaps, so you may delete
139// 'bitmap' and 'mask'.
140int wxImageList::Add(const wxBitmap& bitmap, const wxBitmap& mask)
141{
142 HBITMAP hbmp;
143
144#if wxUSE_WXDIB && wxUSE_IMAGE
145 // wxBitmap normally stores alpha in pre-multiplied format but
146 // ImageList_Draw() does pre-multiplication internally so we need to undo
147 // the pre-multiplication here. Converting back and forth like this is, of
148 // course, very inefficient but it's better than wrong appearance so we do
149 // this for now until a better way can be found.
150 AutoHBITMAP hbmpRelease;
151 if ( bitmap.HasAlpha() )
152 {
153 hbmp = wxDIB(bitmap.ConvertToImage(),
154 wxDIB::PixelFormat_NotPreMultiplied).Detach();
155 hbmpRelease.Init(hbmp);
156 }
157 else
158#endif // wxUSE_WXDIB && wxUSE_IMAGE
159 hbmp = GetHbitmapOf(bitmap);
160
161 AutoHBITMAP hbmpMask(GetMaskForImage(bitmap, mask));
162
163 int index = ImageList_Add(GetHImageList(), hbmp, hbmpMask);
164 if ( index == -1 )
165 {
166 wxLogError(_("Couldn't add an image to the image list."));
167 }
168
169 return index;
170}
171
172// Adds a bitmap, using the specified colour to create the mask bitmap
173// Note that wxImageList creates new bitmaps, so you may delete
174// 'bitmap'.
175int wxImageList::Add(const wxBitmap& bitmap, const wxColour& maskColour)
176{
177 HBITMAP hbmp;
178
179#if wxUSE_WXDIB && wxUSE_IMAGE
180 // See the comment in overloaded Add() above.
181 AutoHBITMAP hbmpRelease;
182 if ( bitmap.HasAlpha() )
183 {
184 hbmp = wxDIB(bitmap.ConvertToImage(),
185 wxDIB::PixelFormat_NotPreMultiplied).Detach();
186 hbmpRelease.Init(hbmp);
187 }
188 else
189#endif // wxUSE_WXDIB && wxUSE_IMAGE
190 hbmp = GetHbitmapOf(bitmap);
191
192 int index = ImageList_AddMasked(GetHImageList(),
193 hbmp,
194 wxColourToRGB(maskColour));
195 if ( index == -1 )
196 {
197 wxLogError(_("Couldn't add an image to the image list."));
198 }
199
200 return index;
201}
202
203// Adds a bitmap and mask from an icon.
204int wxImageList::Add(const wxIcon& icon)
205{
206 int index = ImageList_AddIcon(GetHImageList(), GetHiconOf(icon));
207 if ( index == -1 )
208 {
209 wxLogError(_("Couldn't add an image to the image list."));
210 }
211
212 return index;
213}
214
215// Replaces a bitmap, optionally passing a mask bitmap.
216// Note that wxImageList creates new bitmaps, so you may delete
217// 'bitmap' and 'mask'.
218bool wxImageList::Replace(int index,
219 const wxBitmap& bitmap,
220 const wxBitmap& mask)
221{
222 HBITMAP hbmp;
223
224#if wxUSE_WXDIB && wxUSE_IMAGE
225 // See the comment in Add() above.
226 AutoHBITMAP hbmpRelease;
227 if ( bitmap.HasAlpha() )
228 {
229 hbmp = wxDIB(bitmap.ConvertToImage(),
230 wxDIB::PixelFormat_NotPreMultiplied).Detach();
231 hbmpRelease.Init(hbmp);
232 }
233 else
234#endif // wxUSE_WXDIB && wxUSE_IMAGE
235 hbmp = GetHbitmapOf(bitmap);
236
237 AutoHBITMAP hbmpMask(GetMaskForImage(bitmap, mask));
238
239 if ( !ImageList_Replace(GetHImageList(), index, hbmp, hbmpMask) )
240 {
241 wxLogLastError(wxT("ImageList_Replace()"));
242 return false;
243 }
244
245 return true;
246}
247
248// Replaces a bitmap and mask from an icon.
249bool wxImageList::Replace(int i, const wxIcon& icon)
250{
251 bool ok = ImageList_ReplaceIcon(GetHImageList(), i, GetHiconOf(icon)) != -1;
252 if ( !ok )
253 {
254 wxLogLastError(wxT("ImageList_ReplaceIcon()"));
255 }
256
257 return ok;
258}
259
260// Removes the image at the given index.
261bool wxImageList::Remove(int index)
262{
263 bool ok = ImageList_Remove(GetHImageList(), index) != 0;
264 if ( !ok )
265 {
266 wxLogLastError(wxT("ImageList_Remove()"));
267 }
268
269 return ok;
270}
271
272// Remove all images
273bool wxImageList::RemoveAll()
274{
275 // don't use ImageList_RemoveAll() because mingw32 headers don't have it
276 return Remove(-1);
277}
278
279// Draws the given image on a dc at the specified position.
280// If 'solidBackground' is true, Draw sets the image list background
281// colour to the background colour of the wxDC, to speed up
282// drawing by eliminating masked drawing where possible.
283bool wxImageList::Draw(int index,
284 wxDC& dc,
285 int x, int y,
286 int flags,
287 bool solidBackground)
288{
289 wxDCImpl *impl = dc.GetImpl();
290 wxMSWDCImpl *msw_impl = wxDynamicCast( impl, wxMSWDCImpl );
291 if (!msw_impl)
292 return false;
293
294 HDC hDC = GetHdcOf(*msw_impl);
295 wxCHECK_MSG( hDC, false, wxT("invalid wxDC in wxImageList::Draw") );
296
297 COLORREF clr = CLR_NONE; // transparent by default
298 if ( solidBackground )
299 {
300 const wxBrush& brush = dc.GetBackground();
301 if ( brush.IsOk() )
302 {
303 clr = wxColourToRGB(brush.GetColour());
304 }
305 }
306
307 ImageList_SetBkColor(GetHImageList(), clr);
308
309 UINT style = 0;
310 if ( flags & wxIMAGELIST_DRAW_NORMAL )
311 style |= ILD_NORMAL;
312 if ( flags & wxIMAGELIST_DRAW_TRANSPARENT )
313 style |= ILD_TRANSPARENT;
314 if ( flags & wxIMAGELIST_DRAW_SELECTED )
315 style |= ILD_SELECTED;
316 if ( flags & wxIMAGELIST_DRAW_FOCUSED )
317 style |= ILD_FOCUS;
318
319 bool ok = ImageList_Draw(GetHImageList(), index, hDC, x, y, style) != 0;
320 if ( !ok )
321 {
322 wxLogLastError(wxT("ImageList_Draw()"));
323 }
324
325 return ok;
326}
327
328// Get the bitmap
329wxBitmap wxImageList::GetBitmap(int index) const
330{
331#if wxUSE_WXDIB && wxUSE_IMAGE
332 int bmp_width = 0, bmp_height = 0;
333 GetSize(index, bmp_width, bmp_height);
334
335 wxBitmap bitmap(bmp_width, bmp_height);
336 wxMemoryDC dc;
337 dc.SelectObject(bitmap);
338
339 // draw it the first time to find a suitable mask colour
340 ((wxImageList*)this)->Draw(index, dc, 0, 0, wxIMAGELIST_DRAW_TRANSPARENT);
341 dc.SelectObject(wxNullBitmap);
342
343 // find the suitable mask colour
344 wxImage image = bitmap.ConvertToImage();
345 unsigned char r = 0, g = 0, b = 0;
346 image.FindFirstUnusedColour(&r, &g, &b);
347
348 // redraw whole image and bitmap in the mask colour
349 image.Create(bmp_width, bmp_height);
350 image.Replace(0, 0, 0, r, g, b);
351 bitmap = wxBitmap(image);
352
353 // redraw icon over the mask colour to actually draw it
354 dc.SelectObject(bitmap);
355 ((wxImageList*)this)->Draw(index, dc, 0, 0, wxIMAGELIST_DRAW_TRANSPARENT);
356 dc.SelectObject(wxNullBitmap);
357
358 // get the image, set the mask colour and convert back to get transparent bitmap
359 image = bitmap.ConvertToImage();
360 image.SetMaskColour(r, g, b);
361 bitmap = wxBitmap(image);
362#else
363 wxBitmap bitmap;
364#endif
365 return bitmap;
366}
367
368// Get the icon
369wxIcon wxImageList::GetIcon(int index) const
370{
371 HICON hIcon = ImageList_ExtractIcon(0, GetHImageList(), index);
372 if (hIcon)
373 {
374 wxIcon icon;
375 icon.SetHICON((WXHICON)hIcon);
376
377 int iconW, iconH;
378 GetSize(index, iconW, iconH);
379 icon.SetSize(iconW, iconH);
380
381 return icon;
382 }
383 else
384 return wxNullIcon;
385}
386
387// ----------------------------------------------------------------------------
388// helpers
389// ----------------------------------------------------------------------------
390
391static HBITMAP GetMaskForImage(const wxBitmap& bitmap, const wxBitmap& mask)
392{
393#if wxUSE_IMAGE
394 wxBitmap bitmapWithMask;
395#endif // wxUSE_IMAGE
396
397 HBITMAP hbmpMask;
398 wxMask *pMask;
399 bool deleteMask = false;
400
401 if ( mask.IsOk() )
402 {
403 hbmpMask = GetHbitmapOf(mask);
404 pMask = NULL;
405 }
406 else
407 {
408 pMask = bitmap.GetMask();
409
410#if wxUSE_IMAGE
411 // check if we don't have alpha in this bitmap -- we can create a mask
412 // from it (and we need to do it for the older systems which don't
413 // support 32bpp bitmaps natively)
414 if ( !pMask )
415 {
416 wxImage img(bitmap.ConvertToImage());
417 if ( img.HasAlpha() )
418 {
419 img.ConvertAlphaToMask();
420 bitmapWithMask = wxBitmap(img);
421 pMask = bitmapWithMask.GetMask();
422 }
423 }
424#endif // wxUSE_IMAGE
425
426 if ( !pMask )
427 {
428 // use the light grey count as transparent: the trouble here is
429 // that the light grey might have been changed by Windows behind
430 // our back, so use the standard colour map to get its real value
431 wxCOLORMAP *cmap = wxGetStdColourMap();
432 wxColour col;
433 wxRGBToColour(col, cmap[wxSTD_COL_BTNFACE].from);
434
435 pMask = new wxMask(bitmap, col);
436
437 deleteMask = true;
438 }
439
440 hbmpMask = (HBITMAP)pMask->GetMaskBitmap();
441 }
442
443 // windows mask convention is opposite to the wxWidgets one
444 HBITMAP hbmpMaskInv = wxInvertMask(hbmpMask);
445
446 if ( deleteMask )
447 {
448 delete pMask;
449 }
450
451 return hbmpMaskInv;
452}