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