]> git.saurik.com Git - wxWidgets.git/blame - src/msw/gdiimage.cpp
supporting full style mask
[wxWidgets.git] / src / msw / gdiimage.cpp
CommitLineData
0d0512bd 1///////////////////////////////////////////////////////////////////////////////
670f9935 2// Name: src/msw/gdiimage.cpp
0d0512bd
VZ
3// Purpose: wxGDIImage implementation
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 20.11.99
7// RCS-ID: $Id$
8// Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
65571936 9// Licence: wxWindows licence
0d0512bd
VZ
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
0d0512bd
VZ
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#ifndef WX_PRECOMP
28 #include "wx/string.h"
f94dfb38 29 #include "wx/log.h"
670f9935 30 #include "wx/app.h"
0bca0373 31 #include "wx/bitmap.h"
0d0512bd
VZ
32#endif // WX_PRECOMP
33
e42a6c18
VZ
34#include "wx/msw/private.h"
35
474df218 36#include "wx/msw/gdiimage.h"
4676948b
JS
37
38#if wxUSE_WXDIB
474df218 39#include "wx/msw/dib.h"
4676948b
JS
40#endif
41
42#ifdef __WXWINCE__
43#include <winreg.h>
44#include <shellapi.h>
45#endif
f66f0fd7 46
419430a0
JS
47#include "wx/file.h"
48
d162a7ee 49#include "wx/listimpl.cpp"
259c43f6 50WX_DEFINE_LIST(wxGDIImageHandlerList)
d162a7ee 51
0d0512bd
VZ
52// ----------------------------------------------------------------------------
53// private classes
54// ----------------------------------------------------------------------------
55
04ef50df
JS
56#ifndef __WXMICROWIN__
57
0d0512bd
VZ
58// all image handlers are declared/defined in this file because the outside
59// world doesn't have to know about them (but only about wxBITMAP_TYPE_XXX ids)
60
61class WXDLLEXPORT wxBMPFileHandler : public wxBitmapHandler
62{
63public:
9a83f860 64 wxBMPFileHandler() : wxBitmapHandler(wxT("Windows bitmap file"), wxT("bmp"),
0d0512bd
VZ
65 wxBITMAP_TYPE_BMP)
66 {
67 }
68
69 virtual bool LoadFile(wxBitmap *bitmap,
e86f2cc8 70 const wxString& name, wxBitmapType flags,
0d0512bd 71 int desiredWidth, int desiredHeight);
e86f2cc8
FM
72 virtual bool SaveFile(const wxBitmap *bitmap,
73 const wxString& name, wxBitmapType type,
74 const wxPalette *palette = NULL) const;
0d0512bd
VZ
75
76private:
77 DECLARE_DYNAMIC_CLASS(wxBMPFileHandler)
78};
79
80class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler
81{
82public:
9a83f860 83 wxBMPResourceHandler() : wxBitmapHandler(wxT("Windows bitmap resource"),
0d0512bd
VZ
84 wxEmptyString,
85 wxBITMAP_TYPE_BMP_RESOURCE)
86 {
87 }
88
89 virtual bool LoadFile(wxBitmap *bitmap,
e86f2cc8 90 const wxString& name, wxBitmapType flags,
0d0512bd
VZ
91 int desiredWidth, int desiredHeight);
92
93private:
94 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler)
95};
96
97class WXDLLEXPORT wxIconHandler : public wxGDIImageHandler
98{
99public:
e86f2cc8 100 wxIconHandler(const wxString& name, const wxString& ext, wxBitmapType type)
0d0512bd
VZ
101 : wxGDIImageHandler(name, ext, type)
102 {
103 }
104
105 // creating and saving icons is not supported
106 virtual bool Create(wxGDIImage *WXUNUSED(image),
452418c4 107 const void* WXUNUSED(data),
e86f2cc8 108 wxBitmapType WXUNUSED(flags),
0d0512bd
VZ
109 int WXUNUSED(width),
110 int WXUNUSED(height),
111 int WXUNUSED(depth) = 1)
112 {
4f8090e0 113 return false;
0d0512bd
VZ
114 }
115
e86f2cc8 116 virtual bool Save(const wxGDIImage *WXUNUSED(image),
0d0512bd 117 const wxString& WXUNUSED(name),
e86f2cc8 118 wxBitmapType WXUNUSED(type)) const
0d0512bd 119 {
4f8090e0 120 return false;
0d0512bd
VZ
121 }
122
123 virtual bool Load(wxGDIImage *image,
124 const wxString& name,
e86f2cc8 125 wxBitmapType flags,
0d0512bd
VZ
126 int desiredWidth, int desiredHeight)
127 {
128 wxIcon *icon = wxDynamicCast(image, wxIcon);
9a83f860 129 wxCHECK_MSG( icon, false, wxT("wxIconHandler only works with icons") );
0d0512bd
VZ
130
131 return LoadIcon(icon, name, flags, desiredWidth, desiredHeight);
132 }
133
134protected:
135 virtual bool LoadIcon(wxIcon *icon,
e86f2cc8 136 const wxString& name, wxBitmapType flags,
0d0512bd
VZ
137 int desiredWidth = -1, int desiredHeight = -1) = 0;
138};
139
140class WXDLLEXPORT wxICOFileHandler : public wxIconHandler
141{
142public:
9a83f860
VZ
143 wxICOFileHandler() : wxIconHandler(wxT("ICO icon file"),
144 wxT("ico"),
0d0512bd
VZ
145 wxBITMAP_TYPE_ICO)
146 {
147 }
148
795c9ab8 149protected:
0d0512bd 150 virtual bool LoadIcon(wxIcon *icon,
e86f2cc8 151 const wxString& name, wxBitmapType flags,
0d0512bd
VZ
152 int desiredWidth = -1, int desiredHeight = -1);
153
154private:
155 DECLARE_DYNAMIC_CLASS(wxICOFileHandler)
156};
157
158class WXDLLEXPORT wxICOResourceHandler: public wxIconHandler
159{
160public:
9a83f860
VZ
161 wxICOResourceHandler() : wxIconHandler(wxT("ICO resource"),
162 wxT("ico"),
0d0512bd
VZ
163 wxBITMAP_TYPE_ICO_RESOURCE)
164 {
165 }
166
795c9ab8 167protected:
0d0512bd 168 virtual bool LoadIcon(wxIcon *icon,
e86f2cc8 169 const wxString& name, wxBitmapType flags,
0d0512bd
VZ
170 int desiredWidth = -1, int desiredHeight = -1);
171
172private:
173 DECLARE_DYNAMIC_CLASS(wxICOResourceHandler)
174};
175
176// ----------------------------------------------------------------------------
177// wxWin macros
178// ----------------------------------------------------------------------------
179
621b3e21
VZ
180IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler)
181IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
182IMPLEMENT_DYNAMIC_CLASS(wxICOFileHandler, wxObject)
183IMPLEMENT_DYNAMIC_CLASS(wxICOResourceHandler, wxObject)
0d0512bd
VZ
184
185// ----------------------------------------------------------------------------
186// private functions
187// ----------------------------------------------------------------------------
188
04ef50df
JS
189#endif
190 // __MICROWIN__
0d0512bd
VZ
191
192// ============================================================================
193// implementation
194// ============================================================================
195
d162a7ee 196wxGDIImageHandlerList wxGDIImage::ms_handlers;
0d0512bd
VZ
197
198// ----------------------------------------------------------------------------
199// wxGDIImage functions forwarded to wxGDIImageRefData
200// ----------------------------------------------------------------------------
201
202bool wxGDIImage::FreeResource(bool WXUNUSED(force))
203{
204 if ( !IsNull() )
205 {
206 GetGDIImageData()->Free();
207 GetGDIImageData()->m_handle = 0;
208 }
209
4f8090e0 210 return true;
0d0512bd
VZ
211}
212
2b5f62a0 213WXHANDLE wxGDIImage::GetResourceHandle() const
0d0512bd
VZ
214{
215 return GetHandle();
216}
217
218// ----------------------------------------------------------------------------
219// wxGDIImage handler stuff
220// ----------------------------------------------------------------------------
221
222void wxGDIImage::AddHandler(wxGDIImageHandler *handler)
223{
224 ms_handlers.Append(handler);
225}
226
227void wxGDIImage::InsertHandler(wxGDIImageHandler *handler)
228{
229 ms_handlers.Insert(handler);
230}
231
232bool wxGDIImage::RemoveHandler(const wxString& name)
233{
234 wxGDIImageHandler *handler = FindHandler(name);
235 if ( handler )
236 {
237 ms_handlers.DeleteObject(handler);
4f8090e0 238 return true;
0d0512bd
VZ
239 }
240 else
4f8090e0 241 return false;
0d0512bd
VZ
242}
243
244wxGDIImageHandler *wxGDIImage::FindHandler(const wxString& name)
245{
222ed1d6 246 wxGDIImageHandlerList::compatibility_iterator node = ms_handlers.GetFirst();
0d0512bd
VZ
247 while ( node )
248 {
d162a7ee 249 wxGDIImageHandler *handler = node->GetData();
0d0512bd
VZ
250 if ( handler->GetName() == name )
251 return handler;
4f8090e0 252 node = node->GetNext();
0d0512bd
VZ
253 }
254
255 return NULL;
256}
257
258wxGDIImageHandler *wxGDIImage::FindHandler(const wxString& extension,
259 long type)
260{
222ed1d6 261 wxGDIImageHandlerList::compatibility_iterator node = ms_handlers.GetFirst();
0d0512bd
VZ
262 while ( node )
263 {
d162a7ee 264 wxGDIImageHandler *handler = node->GetData();
795c9ab8 265 if ( (handler->GetExtension() == extension) &&
0d0512bd
VZ
266 (type == -1 || handler->GetType() == type) )
267 {
268 return handler;
269 }
270
4f8090e0 271 node = node->GetNext();
0d0512bd
VZ
272 }
273 return NULL;
274}
275
276wxGDIImageHandler *wxGDIImage::FindHandler(long type)
277{
222ed1d6 278 wxGDIImageHandlerList::compatibility_iterator node = ms_handlers.GetFirst();
0d0512bd
VZ
279 while ( node )
280 {
d162a7ee 281 wxGDIImageHandler *handler = node->GetData();
0d0512bd
VZ
282 if ( handler->GetType() == type )
283 return handler;
284
4f8090e0 285 node = node->GetNext();
0d0512bd
VZ
286 }
287
288 return NULL;
289}
290
291void wxGDIImage::CleanUpHandlers()
292{
222ed1d6 293 wxGDIImageHandlerList::compatibility_iterator node = ms_handlers.GetFirst();
0d0512bd
VZ
294 while ( node )
295 {
d162a7ee 296 wxGDIImageHandler *handler = node->GetData();
222ed1d6 297 wxGDIImageHandlerList::compatibility_iterator next = node->GetNext();
0d0512bd 298 delete handler;
222ed1d6 299 ms_handlers.Erase( node );
0d0512bd
VZ
300 node = next;
301 }
302}
303
304void wxGDIImage::InitStandardHandlers()
305{
04ef50df 306#ifndef __WXMICROWIN__
0d0512bd
VZ
307 AddHandler(new wxBMPResourceHandler);
308 AddHandler(new wxBMPFileHandler);
0d0512bd
VZ
309 AddHandler(new wxICOResourceHandler);
310 AddHandler(new wxICOFileHandler);
04ef50df 311#endif
0d0512bd
VZ
312}
313
04ef50df
JS
314#ifndef __WXMICROWIN__
315
0d0512bd
VZ
316// ----------------------------------------------------------------------------
317// wxBitmap handlers
318// ----------------------------------------------------------------------------
319
320bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap,
e86f2cc8 321 const wxString& name, wxBitmapType WXUNUSED(flags),
0d0512bd
VZ
322 int WXUNUSED(desiredWidth),
323 int WXUNUSED(desiredHeight))
324{
325 // TODO: load colourmap.
e0a050e3 326 bitmap->SetHBITMAP((WXHBITMAP)::LoadBitmap(wxGetInstance(), name.wx_str()));
0d0512bd 327
a1b806b9 328 if ( !bitmap->IsOk() )
0d0512bd
VZ
329 {
330 // it's probably not found
331 wxLogError(wxT("Can't load bitmap '%s' from resources! Check .rc file."),
332 name.c_str());
8bbbae21 333
4f8090e0 334 return false;
8bbbae21
VZ
335 }
336
337 BITMAP bm;
338 if ( !::GetObject(GetHbitmapOf(*bitmap), sizeof(BITMAP), (LPSTR) &bm) )
339 {
340 wxLogLastError(wxT("GetObject(HBITMAP)"));
0d0512bd
VZ
341 }
342
8bbbae21
VZ
343 bitmap->SetWidth(bm.bmWidth);
344 bitmap->SetHeight(bm.bmHeight);
345 bitmap->SetDepth(bm.bmBitsPixel);
346
9542f0a1
VZ
347 // use 0xc0c0c0 as transparent colour by default
348 bitmap->SetMask(new wxMask(*bitmap, *wxLIGHT_GREY));
349
4f8090e0 350 return true;
0d0512bd
VZ
351}
352
353bool wxBMPFileHandler::LoadFile(wxBitmap *bitmap,
e86f2cc8 354 const wxString& name, wxBitmapType WXUNUSED(flags),
0d0512bd
VZ
355 int WXUNUSED(desiredWidth),
356 int WXUNUSED(desiredHeight))
357{
4676948b 358#if wxUSE_WXDIB
9a83f860 359 wxCHECK_MSG( bitmap, false, wxT("NULL bitmap in LoadFile") );
d275c7eb 360
474df218 361 wxDIB dib(name);
0d0512bd 362
a91bcd3b 363 return dib.IsOk() && bitmap->CopyFromDIB(dib);
4676948b 364#else
213ceb3f 365 return false;
4676948b 366#endif
0d0512bd
VZ
367}
368
e86f2cc8 369bool wxBMPFileHandler::SaveFile(const wxBitmap *bitmap,
0d0512bd 370 const wxString& name,
e86f2cc8
FM
371 wxBitmapType WXUNUSED(type),
372 const wxPalette * WXUNUSED(pal)) const
0d0512bd 373{
4676948b 374#if wxUSE_WXDIB
9a83f860 375 wxCHECK_MSG( bitmap, false, wxT("NULL bitmap in SaveFile") );
2b254edf
VZ
376
377 wxDIB dib(*bitmap);
378
379 return dib.Save(name);
4676948b 380#else
213ceb3f 381 return false;
4676948b 382#endif
0d0512bd
VZ
383}
384
385// ----------------------------------------------------------------------------
386// wxIcon handlers
387// ----------------------------------------------------------------------------
388
389bool wxICOFileHandler::LoadIcon(wxIcon *icon,
390 const wxString& name,
e86f2cc8 391 wxBitmapType WXUNUSED(flags),
0d0512bd
VZ
392 int desiredWidth, int desiredHeight)
393{
0d0512bd
VZ
394 icon->UnRef();
395
396 // actual size
397 wxSize size;
398
a4352768
VZ
399 HICON hicon = NULL;
400
2dace059
VZ
401 // Parse the filename: it may be of the form "filename;n" in order to
402 // specify the nth icon in the file.
403 //
404 // For the moment, ignore the issue of possible semicolons in the
405 // filename.
ff9aab3c 406 int iconIndex = 0;
2dace059 407 wxString nameReal(name);
ff9aab3c 408 wxString strIconIndex = name.AfterLast(wxT(';'));
b642d457 409 if (strIconIndex != name)
ff9aab3c
JS
410 {
411 iconIndex = wxAtoi(strIconIndex);
2dace059 412 nameReal = name.BeforeLast(wxT(';'));
ff9aab3c
JS
413 }
414
2b5f62a0
VZ
415#if 0
416 // If we don't know what size icon we're looking for,
417 // try to find out what's there.
418 // Unfortunately this doesn't work, because ExtractIconEx
419 // will scale the icon to the 'desired' size, even if that
420 // size of icon isn't explicitly stored. So we would have
421 // to parse the icon file outselves.
422 if ( desiredWidth == -1 &&
423 desiredHeight == -1)
424 {
425 // Try loading a large icon first
426 if ( ::ExtractIconEx(nameReal, iconIndex, &hicon, NULL, 1) == 1)
427 {
428 }
429 // Then try loading a small icon
430 else if ( ::ExtractIconEx(nameReal, iconIndex, NULL, &hicon, 1) == 1)
431 {
432 }
433 }
434 else
435#endif
4676948b 436 // were we asked for a large icon?
a4352768
VZ
437 if ( desiredWidth == ::GetSystemMetrics(SM_CXICON) &&
438 desiredHeight == ::GetSystemMetrics(SM_CYICON) )
439 {
ff9aab3c 440 // get the specified large icon from file
e0a050e3 441 if ( !::ExtractIconEx(nameReal.wx_str(), iconIndex, &hicon, NULL, 1) )
a4352768
VZ
442 {
443 // it is not an error, but it might still be useful to be informed
444 // about it optionally
9a83f860
VZ
445 wxLogTrace(wxT("iconload"),
446 wxT("No large icons found in the file '%s'."),
a4352768
VZ
447 name.c_str());
448 }
449 }
450 else if ( desiredWidth == ::GetSystemMetrics(SM_CXSMICON) &&
451 desiredHeight == ::GetSystemMetrics(SM_CYSMICON) )
452 {
ff9aab3c 453 // get the specified small icon from file
e0a050e3 454 if ( !::ExtractIconEx(nameReal.wx_str(), iconIndex, NULL, &hicon, 1) )
a4352768 455 {
9a83f860
VZ
456 wxLogTrace(wxT("iconload"),
457 wxT("No small icons found in the file '%s'."),
a4352768
VZ
458 name.c_str());
459 }
460 }
461 //else: not standard size, load below
462
4676948b 463#ifndef __WXWINCE__
a4352768
VZ
464 if ( !hicon )
465 {
d8f3f983 466 // take any size icon from the file by index
e0a050e3 467 hicon = ::ExtractIcon(wxGetInstance(), nameReal.wx_str(), iconIndex);
a4352768 468 }
4676948b 469#endif
a4352768 470
0d0512bd
VZ
471 if ( !hicon )
472 {
9a83f860 473 wxLogSysError(wxT("Failed to load icon from the file '%s'"),
0d0512bd
VZ
474 name.c_str());
475
4f8090e0 476 return false;
0d0512bd
VZ
477 }
478
6bad4c32 479 size = wxGetHiconSize(hicon);
0d0512bd
VZ
480
481 if ( (desiredWidth != -1 && desiredWidth != size.x) ||
482 (desiredHeight != -1 && desiredHeight != size.y) )
483 {
9a83f860
VZ
484 wxLogTrace(wxT("iconload"),
485 wxT("Returning false from wxICOFileHandler::Load because of the size mismatch: actual (%d, %d), requested (%d, %d)"),
a4352768
VZ
486 size.x, size.y,
487 desiredWidth, desiredHeight);
0d0512bd
VZ
488
489 ::DestroyIcon(hicon);
490
4f8090e0 491 return false;
0d0512bd
VZ
492 }
493
494 icon->SetHICON((WXHICON)hicon);
495 icon->SetSize(size.x, size.y);
496
a1b806b9 497 return icon->IsOk();
0d0512bd
VZ
498}
499
500bool wxICOResourceHandler::LoadIcon(wxIcon *icon,
501 const wxString& name,
e86f2cc8 502 wxBitmapType WXUNUSED(flags),
0d0512bd
VZ
503 int desiredWidth, int desiredHeight)
504{
505 HICON hicon;
506
9cb9fdb3
VZ
507 // do we need the icon of the specific size or would any icon do?
508 bool hasSize = desiredWidth != -1 || desiredHeight != -1;
509
510 wxASSERT_MSG( !hasSize || (desiredWidth != -1 && desiredHeight != -1),
9a83f860 511 wxT("width and height should be either both -1 or not") );
9cb9fdb3 512
2dace059
VZ
513 // try to load the icon from this program first to allow overriding the
514 // standard icons (although why one would want to do it considering that
515 // we already have wxApp::GetStdIcon() is unclear)
9990cb50
VZ
516
517 // note that we can't just always call LoadImage() because it seems to do
518 // some icon rescaling internally which results in very ugly 16x16 icons
9990cb50 519 if ( hasSize )
0d0512bd 520 {
e0a050e3 521 hicon = (HICON)::LoadImage(wxGetInstance(), name.wx_str(), IMAGE_ICON,
9990cb50
VZ
522 desiredWidth, desiredHeight,
523 LR_DEFAULTCOLOR);
0d0512bd 524 }
9990cb50 525 else
9990cb50 526 {
e0a050e3 527 hicon = ::LoadIcon(wxGetInstance(), name.wx_str());
9990cb50 528 }
fea2b62e 529
2dace059 530 // next check if it's not a standard icon
4676948b 531#ifndef __WXWINCE__
9cb9fdb3 532 if ( !hicon && !hasSize )
2dace059
VZ
533 {
534 static const struct
535 {
536 const wxChar *name;
537 LPTSTR id;
538 } stdIcons[] =
539 {
540 { wxT("wxICON_QUESTION"), IDI_QUESTION },
541 { wxT("wxICON_WARNING"), IDI_EXCLAMATION },
542 { wxT("wxICON_ERROR"), IDI_HAND },
c2edb18a 543 { wxT("wxICON_INFORMATION"), IDI_ASTERISK },
2dace059
VZ
544 };
545
546 for ( size_t nIcon = 0; !hicon && nIcon < WXSIZEOF(stdIcons); nIcon++ )
547 {
548 if ( name == stdIcons[nIcon].name )
549 {
9cb9fdb3 550 hicon = ::LoadIcon((HINSTANCE)NULL, stdIcons[nIcon].id);
fde87a82 551 break;
2dace059
VZ
552 }
553 }
554 }
4676948b 555#endif
2dace059 556
6bad4c32 557 wxSize size = wxGetHiconSize(hicon);
0d0512bd
VZ
558 icon->SetSize(size.x, size.y);
559
0d0512bd
VZ
560 icon->SetHICON((WXHICON)hicon);
561
a1b806b9 562 return icon->IsOk();
0d0512bd
VZ
563}
564
565// ----------------------------------------------------------------------------
566// private functions
567// ----------------------------------------------------------------------------
568
0c0d1521 569wxSize wxGetHiconSize(HICON WXUNUSED_IN_WINCE(hicon))
0d0512bd 570{
ab3d29ea 571 wxSize size;
7010702f 572
4676948b 573#ifndef __WXWINCE__
ab3d29ea 574 if ( hicon )
0d0512bd
VZ
575 {
576 ICONINFO info;
577 if ( !::GetIconInfo(hicon, &info) )
578 {
f6bcfd97 579 wxLogLastError(wxT("GetIconInfo"));
0d0512bd
VZ
580 }
581 else
582 {
583 HBITMAP hbmp = info.hbmMask;
584 if ( hbmp )
585 {
586 BITMAP bm;
587 if ( ::GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm) )
588 {
589 size = wxSize(bm.bmWidth, bm.bmHeight);
590 }
591
592 ::DeleteObject(info.hbmMask);
593 }
594 if ( info.hbmColor )
595 ::DeleteObject(info.hbmColor);
596 }
597 }
ab3d29ea
VZ
598
599 if ( !size.x )
600#endif // !__WXWINCE__
601 {
602 // use default icon size on this hardware
603 size.x = ::GetSystemMetrics(SM_CXICON);
604 size.y = ::GetSystemMetrics(SM_CYICON);
605 }
0c0d1521 606
0d0512bd
VZ
607 return size;
608}
474df218
VZ
609
610#endif // __WXMICROWIN__