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