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