]> git.saurik.com Git - wxWidgets.git/blame - src/msw/gdiimage.cpp
applied (slightly modified) wxToggleButton patch from John Norris and Axel Schlueter
[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>
9// Licence: wxWindows license
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
40#include "wx/msw/dib.h"
c25a510b 41#include "wx/msw/bitmap.h"
0d0512bd 42#include "wx/msw/gdiimage.h"
f66f0fd7
GRG
43#include "wx/bitmap.h"
44
45#if wxUSE_XPM_IN_MSW
46# include "wx/xpmhand.h"
47#endif // wxUSE_XPM_IN_MSW
0d0512bd 48
8f177c8e 49#ifdef __WIN16__
f66f0fd7 50# include "wx/msw/curico.h"
8f177c8e
VZ
51#endif // __WIN16__
52
0d0512bd
VZ
53// ----------------------------------------------------------------------------
54// private classes
55// ----------------------------------------------------------------------------
56
57// all image handlers are declared/defined in this file because the outside
58// world doesn't have to know about them (but only about wxBITMAP_TYPE_XXX ids)
59
60class WXDLLEXPORT wxBMPFileHandler : public wxBitmapHandler
61{
62public:
63 wxBMPFileHandler() : wxBitmapHandler(_T("Windows bitmap file"), _T("bmp"),
64 wxBITMAP_TYPE_BMP)
65 {
66 }
67
68 virtual bool LoadFile(wxBitmap *bitmap,
69 const wxString& name, long flags,
70 int desiredWidth, int desiredHeight);
71 virtual bool SaveFile(wxBitmap *bitmap,
72 const wxString& name, int type,
73 const wxPalette *palette = NULL);
74
75private:
76 DECLARE_DYNAMIC_CLASS(wxBMPFileHandler)
77};
78
79class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler
80{
81public:
82 wxBMPResourceHandler() : wxBitmapHandler(_T("Windows bitmap resource"),
83 wxEmptyString,
84 wxBITMAP_TYPE_BMP_RESOURCE)
85 {
86 }
87
88 virtual bool LoadFile(wxBitmap *bitmap,
89 const wxString& name, long flags,
90 int desiredWidth, int desiredHeight);
91
92private:
93 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler)
94};
95
96class WXDLLEXPORT wxIconHandler : public wxGDIImageHandler
97{
98public:
99 wxIconHandler(const wxString& name, const wxString& ext, long type)
100 : wxGDIImageHandler(name, ext, type)
101 {
102 }
103
104 // creating and saving icons is not supported
105 virtual bool Create(wxGDIImage *WXUNUSED(image),
106 void *WXUNUSED(data),
107 long WXUNUSED(flags),
108 int WXUNUSED(width),
109 int WXUNUSED(height),
110 int WXUNUSED(depth) = 1)
111 {
112 return FALSE;
113 }
114
115 virtual bool Save(wxGDIImage *WXUNUSED(image),
116 const wxString& WXUNUSED(name),
117 int WXUNUSED(type))
118 {
119 return FALSE;
120 }
121
122 virtual bool Load(wxGDIImage *image,
123 const wxString& name,
124 long flags,
125 int desiredWidth, int desiredHeight)
126 {
127 wxIcon *icon = wxDynamicCast(image, wxIcon);
128 wxCHECK_MSG( icon, FALSE, _T("wxIconHandler only works with icons") );
129
130 return LoadIcon(icon, name, flags, desiredWidth, desiredHeight);
131 }
132
133protected:
134 virtual bool LoadIcon(wxIcon *icon,
135 const wxString& name, long flags,
136 int desiredWidth = -1, int desiredHeight = -1) = 0;
137};
138
139class WXDLLEXPORT wxICOFileHandler : public wxIconHandler
140{
141public:
142 wxICOFileHandler() : wxIconHandler(_T("ICO icon file"),
143 _T("ico"),
144 wxBITMAP_TYPE_ICO)
145 {
146 }
147
148 virtual bool LoadIcon(wxIcon *icon,
149 const wxString& name, long flags,
150 int desiredWidth = -1, int desiredHeight = -1);
151
152private:
153 DECLARE_DYNAMIC_CLASS(wxICOFileHandler)
154};
155
156class WXDLLEXPORT wxICOResourceHandler: public wxIconHandler
157{
158public:
159 wxICOResourceHandler() : wxIconHandler(_T("ICO resource"),
160 _T("ico"),
161 wxBITMAP_TYPE_ICO_RESOURCE)
162 {
163 }
164
165 virtual bool LoadIcon(wxIcon *icon,
166 const wxString& name, long flags,
167 int desiredWidth = -1, int desiredHeight = -1);
168
169private:
170 DECLARE_DYNAMIC_CLASS(wxICOResourceHandler)
171};
172
173// ----------------------------------------------------------------------------
174// wxWin macros
175// ----------------------------------------------------------------------------
176
0d0512bd
VZ
177 IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler)
178 IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
179 IMPLEMENT_DYNAMIC_CLASS(wxICOFileHandler, wxGDIImageHandler)
180 IMPLEMENT_DYNAMIC_CLASS(wxICOResourceHandler, wxGDIImageHandler)
0d0512bd
VZ
181
182// ----------------------------------------------------------------------------
183// private functions
184// ----------------------------------------------------------------------------
185
186static wxSize GetHiconSize(HICON hicon);
187
188// ============================================================================
189// implementation
190// ============================================================================
191
192wxList wxGDIImage::ms_handlers;
193
194// ----------------------------------------------------------------------------
195// wxGDIImage functions forwarded to wxGDIImageRefData
196// ----------------------------------------------------------------------------
197
198bool wxGDIImage::FreeResource(bool WXUNUSED(force))
199{
200 if ( !IsNull() )
201 {
202 GetGDIImageData()->Free();
203 GetGDIImageData()->m_handle = 0;
204 }
205
206 return TRUE;
207}
208
209WXHANDLE wxGDIImage::GetResourceHandle()
210{
211 return GetHandle();
212}
213
214// ----------------------------------------------------------------------------
215// wxGDIImage handler stuff
216// ----------------------------------------------------------------------------
217
218void wxGDIImage::AddHandler(wxGDIImageHandler *handler)
219{
220 ms_handlers.Append(handler);
221}
222
223void wxGDIImage::InsertHandler(wxGDIImageHandler *handler)
224{
225 ms_handlers.Insert(handler);
226}
227
228bool wxGDIImage::RemoveHandler(const wxString& name)
229{
230 wxGDIImageHandler *handler = FindHandler(name);
231 if ( handler )
232 {
233 ms_handlers.DeleteObject(handler);
234 return TRUE;
235 }
236 else
237 return FALSE;
238}
239
240wxGDIImageHandler *wxGDIImage::FindHandler(const wxString& name)
241{
242 wxNode *node = ms_handlers.First();
243 while ( node )
244 {
245 wxGDIImageHandler *handler = (wxGDIImageHandler *)node->Data();
246 if ( handler->GetName() == name )
247 return handler;
248 node = node->Next();
249 }
250
251 return NULL;
252}
253
254wxGDIImageHandler *wxGDIImage::FindHandler(const wxString& extension,
255 long type)
256{
257 wxNode *node = ms_handlers.First();
258 while ( node )
259 {
260 wxGDIImageHandler *handler = (wxGDIImageHandler *)node->Data();
261 if ( (handler->GetExtension() = extension) &&
262 (type == -1 || handler->GetType() == type) )
263 {
264 return handler;
265 }
266
267 node = node->Next();
268 }
269 return NULL;
270}
271
272wxGDIImageHandler *wxGDIImage::FindHandler(long type)
273{
274 wxNode *node = ms_handlers.First();
275 while ( node )
276 {
277 wxGDIImageHandler *handler = (wxGDIImageHandler *)node->Data();
278 if ( handler->GetType() == type )
279 return handler;
280
281 node = node->Next();
282 }
283
284 return NULL;
285}
286
287void wxGDIImage::CleanUpHandlers()
288{
289 wxNode *node = ms_handlers.First();
290 while ( node )
291 {
292 wxGDIImageHandler *handler = (wxGDIImageHandler *)node->Data();
293 wxNode *next = node->Next();
294 delete handler;
295 delete node;
296 node = next;
297 }
298}
299
300void wxGDIImage::InitStandardHandlers()
301{
302 AddHandler(new wxBMPResourceHandler);
303 AddHandler(new wxBMPFileHandler);
304
f66f0fd7
GRG
305 // GRG: Add these handlers by default if XPM support is enabled
306
307#if wxUSE_XPM_IN_MSW
308 AddHandler(new wxXPMFileHandler);
309 AddHandler(new wxXPMDataHandler);
310#endif // wxUSE_XPM_IN_MSW
0d0512bd
VZ
311
312 AddHandler(new wxICOResourceHandler);
313 AddHandler(new wxICOFileHandler);
314}
315
316// ----------------------------------------------------------------------------
317// wxBitmap handlers
318// ----------------------------------------------------------------------------
319
320bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap,
321 const wxString& name, long WXUNUSED(flags),
322 int WXUNUSED(desiredWidth),
323 int WXUNUSED(desiredHeight))
324{
325 // TODO: load colourmap.
326 bitmap->SetHBITMAP((WXHBITMAP)::LoadBitmap(wxGetInstance(), name));
327
328 wxBitmapRefData *data = bitmap->GetBitmapData();
329 if ( bitmap->Ok() )
330 {
331 BITMAP bm;
332 if ( !::GetObject(GetHbitmapOf(*bitmap), sizeof(BITMAP), (LPSTR) &bm) )
333 {
f6bcfd97 334 wxLogLastError(wxT("GetObject(HBITMAP)"));
0d0512bd
VZ
335 }
336
337 data->m_width = bm.bmWidth;
338 data->m_height = bm.bmHeight;
339 data->m_depth = bm.bmBitsPixel;
340 }
341 else
342 {
343 // it's probably not found
344 wxLogError(wxT("Can't load bitmap '%s' from resources! Check .rc file."),
345 name.c_str());
346 }
347
348 return bitmap->Ok();
349}
350
351bool wxBMPFileHandler::LoadFile(wxBitmap *bitmap,
352 const wxString& name, long WXUNUSED(flags),
353 int WXUNUSED(desiredWidth),
354 int WXUNUSED(desiredHeight))
355{
356#if wxUSE_IMAGE_LOADING_IN_MSW
357 wxPalette *palette = NULL;
358 bool success = wxLoadIntoBitmap(WXSTRINGCAST name, bitmap, &palette) != 0;
359 if ( success && palette )
360 {
361 bitmap->SetPalette(*palette);
362 }
363
364 // it was copied by the bitmap if it was loaded successfully
365 delete palette;
366
367 return success;
368#else
369 return FALSE;
370#endif
371}
372
373bool wxBMPFileHandler::SaveFile(wxBitmap *bitmap,
374 const wxString& name,
375 int WXUNUSED(type),
376 const wxPalette *pal)
377{
378#if wxUSE_IMAGE_LOADING_IN_MSW
379 wxPalette *actualPalette = (wxPalette *)pal;
380 if ( !actualPalette )
381 actualPalette = bitmap->GetPalette();
382 return wxSaveBitmap(WXSTRINGCAST name, bitmap, actualPalette) != 0;
383#else
384 return FALSE;
385#endif
386}
387
388// ----------------------------------------------------------------------------
389// wxIcon handlers
390// ----------------------------------------------------------------------------
391
392bool wxICOFileHandler::LoadIcon(wxIcon *icon,
393 const wxString& name,
394 long flags,
395 int desiredWidth, int desiredHeight)
396{
397#if wxUSE_RESOURCE_LOADING_IN_MSW
398 icon->UnRef();
399
400 // actual size
401 wxSize size;
402
403#ifdef __WIN32__
a4352768
VZ
404 HICON hicon = NULL;
405
406 // were we asked for a large icon?
407 if ( desiredWidth == ::GetSystemMetrics(SM_CXICON) &&
408 desiredHeight == ::GetSystemMetrics(SM_CYICON) )
409 {
410 // get the first large icon from file
411 if ( !::ExtractIconEx(name, 0, &hicon, NULL, 1) )
412 {
413 // it is not an error, but it might still be useful to be informed
414 // about it optionally
415 wxLogTrace(_T("iconload"),
416 _T("No large icons found in the file '%s'."),
417 name.c_str());
418 }
419 }
420 else if ( desiredWidth == ::GetSystemMetrics(SM_CXSMICON) &&
421 desiredHeight == ::GetSystemMetrics(SM_CYSMICON) )
422 {
423 // get the first small icon from file
424 if ( !::ExtractIconEx(name, 0, NULL, &hicon, 1) )
425 {
426 wxLogTrace(_T("iconload"),
427 _T("No small icons found in the file '%s'."),
428 name.c_str());
429 }
430 }
431 //else: not standard size, load below
432
433 if ( !hicon )
434 {
435 // take any (the first one) icon from the file by default
436 hicon = ::ExtractIcon(wxGetInstance(), name, 0 /* first */);
437 }
438
0d0512bd
VZ
439 if ( !hicon )
440 {
441 wxLogSysError(_T("Failed to load icon from the file '%s'"),
442 name.c_str());
443
444 return FALSE;
445 }
446
447 size = GetHiconSize(hicon);
448#else // Win16
449 HICON hicon = ReadIconFile((wxChar *)name.c_str(),
450 wxGetInstance(),
451 &size.x, &size.y);
452#endif // Win32/Win16
453
454 if ( (desiredWidth != -1 && desiredWidth != size.x) ||
455 (desiredHeight != -1 && desiredHeight != size.y) )
456 {
a4352768
VZ
457 wxLogTrace(_T("iconload"),
458 _T("Returning FALSE from wxICOFileHandler::Load because of the size mismatch: actual (%d, %d), requested (%d, %d)"),
459 size.x, size.y,
460 desiredWidth, desiredHeight);
0d0512bd
VZ
461
462 ::DestroyIcon(hicon);
463
464 return FALSE;
465 }
466
467 icon->SetHICON((WXHICON)hicon);
468 icon->SetSize(size.x, size.y);
469
470 return icon->Ok();
471#else
472 return FALSE;
473#endif
474}
475
476bool wxICOResourceHandler::LoadIcon(wxIcon *icon,
477 const wxString& name,
478 long flags,
479 int desiredWidth, int desiredHeight)
480{
481 HICON hicon;
482
483#if defined(__WIN32__) && !defined(__SC__)
484 if ( desiredWidth != -1 && desiredHeight != -1 )
485 {
486 hicon = (HICON)::LoadImage(wxGetInstance(), name, IMAGE_ICON,
487 desiredWidth, desiredHeight,
488 LR_DEFAULTCOLOR);
489 }
490 else
491#endif // Win32
492 {
493 hicon = ::LoadIcon(wxGetInstance(), name);
494 }
495
496 wxSize size = GetHiconSize(hicon);
497 icon->SetSize(size.x, size.y);
498
499 // Override the found values with desired values
500 if ( desiredWidth > -1 && desiredHeight > -1 )
501 {
502 icon->SetSize(desiredWidth, desiredHeight);
503 }
504
505 icon->SetHICON((WXHICON)hicon);
506
507 return icon->Ok();
508}
509
510// ----------------------------------------------------------------------------
511// private functions
512// ----------------------------------------------------------------------------
513
514static wxSize GetHiconSize(HICON hicon)
515{
516 wxSize size(32, 32); // default
517
518#ifdef __WIN32__
519 // Win32s doesn't have GetIconInfo function...
520 if ( hicon && wxGetOsVersion() != wxWIN32S )
521 {
522 ICONINFO info;
523 if ( !::GetIconInfo(hicon, &info) )
524 {
f6bcfd97 525 wxLogLastError(wxT("GetIconInfo"));
0d0512bd
VZ
526 }
527 else
528 {
529 HBITMAP hbmp = info.hbmMask;
530 if ( hbmp )
531 {
532 BITMAP bm;
533 if ( ::GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm) )
534 {
535 size = wxSize(bm.bmWidth, bm.bmHeight);
536 }
537
538 ::DeleteObject(info.hbmMask);
539 }
540 if ( info.hbmColor )
541 ::DeleteObject(info.hbmColor);
542 }
543 }
544#endif
545
546 return size;
547}