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