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