]> git.saurik.com Git - wxWidgets.git/blame - src/msw/gdiimage.cpp
fix typo in drawing slider ticks; added assert to check for it (slightly modified...
[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
621b3e21
VZ
178IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler)
179IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
180IMPLEMENT_DYNAMIC_CLASS(wxICOFileHandler, wxObject)
181IMPLEMENT_DYNAMIC_CLASS(wxICOResourceHandler, wxObject)
0d0512bd
VZ
182
183// ----------------------------------------------------------------------------
184// private functions
185// ----------------------------------------------------------------------------
186
04ef50df
JS
187#endif
188 // __MICROWIN__
0d0512bd
VZ
189
190// ============================================================================
191// implementation
192// ============================================================================
193
194wxList wxGDIImage::ms_handlers;
195
196// ----------------------------------------------------------------------------
197// wxGDIImage functions forwarded to wxGDIImageRefData
198// ----------------------------------------------------------------------------
199
200bool wxGDIImage::FreeResource(bool WXUNUSED(force))
201{
202 if ( !IsNull() )
203 {
204 GetGDIImageData()->Free();
205 GetGDIImageData()->m_handle = 0;
206 }
207
208 return TRUE;
209}
210
2b5f62a0 211WXHANDLE wxGDIImage::GetResourceHandle() const
0d0512bd
VZ
212{
213 return GetHandle();
214}
215
216// ----------------------------------------------------------------------------
217// wxGDIImage handler stuff
218// ----------------------------------------------------------------------------
219
220void wxGDIImage::AddHandler(wxGDIImageHandler *handler)
221{
222 ms_handlers.Append(handler);
223}
224
225void wxGDIImage::InsertHandler(wxGDIImageHandler *handler)
226{
227 ms_handlers.Insert(handler);
228}
229
230bool wxGDIImage::RemoveHandler(const wxString& name)
231{
232 wxGDIImageHandler *handler = FindHandler(name);
233 if ( handler )
234 {
235 ms_handlers.DeleteObject(handler);
236 return TRUE;
237 }
238 else
239 return FALSE;
240}
241
242wxGDIImageHandler *wxGDIImage::FindHandler(const wxString& name)
243{
244 wxNode *node = ms_handlers.First();
245 while ( node )
246 {
247 wxGDIImageHandler *handler = (wxGDIImageHandler *)node->Data();
248 if ( handler->GetName() == name )
249 return handler;
250 node = node->Next();
251 }
252
253 return NULL;
254}
255
256wxGDIImageHandler *wxGDIImage::FindHandler(const wxString& extension,
257 long type)
258{
259 wxNode *node = ms_handlers.First();
260 while ( node )
261 {
262 wxGDIImageHandler *handler = (wxGDIImageHandler *)node->Data();
263 if ( (handler->GetExtension() = extension) &&
264 (type == -1 || handler->GetType() == type) )
265 {
266 return handler;
267 }
268
269 node = node->Next();
270 }
271 return NULL;
272}
273
274wxGDIImageHandler *wxGDIImage::FindHandler(long type)
275{
276 wxNode *node = ms_handlers.First();
277 while ( node )
278 {
279 wxGDIImageHandler *handler = (wxGDIImageHandler *)node->Data();
280 if ( handler->GetType() == type )
281 return handler;
282
283 node = node->Next();
284 }
285
286 return NULL;
287}
288
289void wxGDIImage::CleanUpHandlers()
290{
291 wxNode *node = ms_handlers.First();
292 while ( node )
293 {
294 wxGDIImageHandler *handler = (wxGDIImageHandler *)node->Data();
295 wxNode *next = node->Next();
296 delete handler;
297 delete node;
298 node = next;
299 }
300}
301
302void wxGDIImage::InitStandardHandlers()
303{
04ef50df 304#ifndef __WXMICROWIN__
0d0512bd
VZ
305 AddHandler(new wxBMPResourceHandler);
306 AddHandler(new wxBMPFileHandler);
0d0512bd
VZ
307 AddHandler(new wxICOResourceHandler);
308 AddHandler(new wxICOFileHandler);
04ef50df 309#endif
0d0512bd
VZ
310}
311
04ef50df
JS
312#ifndef __WXMICROWIN__
313
0d0512bd
VZ
314// ----------------------------------------------------------------------------
315// wxBitmap handlers
316// ----------------------------------------------------------------------------
317
318bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap,
319 const wxString& name, long WXUNUSED(flags),
320 int WXUNUSED(desiredWidth),
321 int WXUNUSED(desiredHeight))
322{
323 // TODO: load colourmap.
324 bitmap->SetHBITMAP((WXHBITMAP)::LoadBitmap(wxGetInstance(), name));
325
326 wxBitmapRefData *data = bitmap->GetBitmapData();
327 if ( bitmap->Ok() )
328 {
329 BITMAP bm;
330 if ( !::GetObject(GetHbitmapOf(*bitmap), sizeof(BITMAP), (LPSTR) &bm) )
331 {
f6bcfd97 332 wxLogLastError(wxT("GetObject(HBITMAP)"));
0d0512bd
VZ
333 }
334
335 data->m_width = bm.bmWidth;
336 data->m_height = bm.bmHeight;
337 data->m_depth = bm.bmBitsPixel;
338 }
339 else
340 {
341 // it's probably not found
342 wxLogError(wxT("Can't load bitmap '%s' from resources! Check .rc file."),
343 name.c_str());
344 }
345
346 return bitmap->Ok();
347}
348
349bool wxBMPFileHandler::LoadFile(wxBitmap *bitmap,
350 const wxString& name, long WXUNUSED(flags),
351 int WXUNUSED(desiredWidth),
352 int WXUNUSED(desiredHeight))
353{
354#if wxUSE_IMAGE_LOADING_IN_MSW
355 wxPalette *palette = NULL;
356 bool success = wxLoadIntoBitmap(WXSTRINGCAST name, bitmap, &palette) != 0;
d275c7eb
VZ
357
358#if wxUSE_PALETTE
0d0512bd
VZ
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;
d275c7eb 366#endif // wxUSE_PALETTE
0d0512bd
VZ
367
368 return success;
369#else
370 return FALSE;
371#endif
372}
373
374bool wxBMPFileHandler::SaveFile(wxBitmap *bitmap,
375 const wxString& name,
376 int WXUNUSED(type),
377 const wxPalette *pal)
378{
379#if wxUSE_IMAGE_LOADING_IN_MSW
d275c7eb
VZ
380
381#if wxUSE_PALETTE
0d0512bd
VZ
382 wxPalette *actualPalette = (wxPalette *)pal;
383 if ( !actualPalette )
384 actualPalette = bitmap->GetPalette();
d275c7eb
VZ
385#else
386 wxPalette *actualPalette = NULL;
387#endif // wxUSE_PALETTE
388
0d0512bd
VZ
389 return wxSaveBitmap(WXSTRINGCAST name, bitmap, actualPalette) != 0;
390#else
391 return FALSE;
392#endif
393}
394
395// ----------------------------------------------------------------------------
396// wxIcon handlers
397// ----------------------------------------------------------------------------
398
399bool wxICOFileHandler::LoadIcon(wxIcon *icon,
400 const wxString& name,
33ac7e6f 401 long WXUNUSED(flags),
0d0512bd
VZ
402 int desiredWidth, int desiredHeight)
403{
404#if wxUSE_RESOURCE_LOADING_IN_MSW
405 icon->UnRef();
406
407 // actual size
408 wxSize size;
409
410#ifdef __WIN32__
a4352768
VZ
411 HICON hicon = NULL;
412
2dace059
VZ
413 // Parse the filename: it may be of the form "filename;n" in order to
414 // specify the nth icon in the file.
415 //
416 // For the moment, ignore the issue of possible semicolons in the
417 // filename.
ff9aab3c 418 int iconIndex = 0;
2dace059 419 wxString nameReal(name);
ff9aab3c 420 wxString strIconIndex = name.AfterLast(wxT(';'));
b642d457 421 if (strIconIndex != name)
ff9aab3c
JS
422 {
423 iconIndex = wxAtoi(strIconIndex);
2dace059 424 nameReal = name.BeforeLast(wxT(';'));
ff9aab3c
JS
425 }
426
2b5f62a0
VZ
427#if 0
428 // If we don't know what size icon we're looking for,
429 // try to find out what's there.
430 // Unfortunately this doesn't work, because ExtractIconEx
431 // will scale the icon to the 'desired' size, even if that
432 // size of icon isn't explicitly stored. So we would have
433 // to parse the icon file outselves.
434 if ( desiredWidth == -1 &&
435 desiredHeight == -1)
436 {
437 // Try loading a large icon first
438 if ( ::ExtractIconEx(nameReal, iconIndex, &hicon, NULL, 1) == 1)
439 {
440 }
441 // Then try loading a small icon
442 else if ( ::ExtractIconEx(nameReal, iconIndex, NULL, &hicon, 1) == 1)
443 {
444 }
445 }
446 else
447#endif
a4352768
VZ
448 // were we asked for a large icon?
449 if ( desiredWidth == ::GetSystemMetrics(SM_CXICON) &&
450 desiredHeight == ::GetSystemMetrics(SM_CYICON) )
451 {
ff9aab3c 452 // get the specified large icon from file
2dace059 453 if ( !::ExtractIconEx(nameReal, iconIndex, &hicon, NULL, 1) )
a4352768
VZ
454 {
455 // it is not an error, but it might still be useful to be informed
456 // about it optionally
457 wxLogTrace(_T("iconload"),
458 _T("No large icons found in the file '%s'."),
459 name.c_str());
460 }
461 }
462 else if ( desiredWidth == ::GetSystemMetrics(SM_CXSMICON) &&
463 desiredHeight == ::GetSystemMetrics(SM_CYSMICON) )
464 {
ff9aab3c 465 // get the specified small icon from file
2dace059 466 if ( !::ExtractIconEx(nameReal, iconIndex, NULL, &hicon, 1) )
a4352768
VZ
467 {
468 wxLogTrace(_T("iconload"),
469 _T("No small icons found in the file '%s'."),
470 name.c_str());
471 }
472 }
473 //else: not standard size, load below
474
475 if ( !hicon )
476 {
d8f3f983
RD
477 // take any size icon from the file by index
478 hicon = ::ExtractIcon(wxGetInstance(), nameReal, iconIndex);
a4352768
VZ
479 }
480
0d0512bd
VZ
481 if ( !hicon )
482 {
483 wxLogSysError(_T("Failed to load icon from the file '%s'"),
484 name.c_str());
485
486 return FALSE;
487 }
488
6bad4c32 489 size = wxGetHiconSize(hicon);
0d0512bd
VZ
490#else // Win16
491 HICON hicon = ReadIconFile((wxChar *)name.c_str(),
492 wxGetInstance(),
493 &size.x, &size.y);
494#endif // Win32/Win16
495
496 if ( (desiredWidth != -1 && desiredWidth != size.x) ||
497 (desiredHeight != -1 && desiredHeight != size.y) )
498 {
a4352768
VZ
499 wxLogTrace(_T("iconload"),
500 _T("Returning FALSE from wxICOFileHandler::Load because of the size mismatch: actual (%d, %d), requested (%d, %d)"),
501 size.x, size.y,
502 desiredWidth, desiredHeight);
0d0512bd
VZ
503
504 ::DestroyIcon(hicon);
505
506 return FALSE;
507 }
508
509 icon->SetHICON((WXHICON)hicon);
510 icon->SetSize(size.x, size.y);
511
512 return icon->Ok();
513#else
514 return FALSE;
515#endif
516}
517
518bool wxICOResourceHandler::LoadIcon(wxIcon *icon,
519 const wxString& name,
33ac7e6f 520 long WXUNUSED(flags),
0d0512bd
VZ
521 int desiredWidth, int desiredHeight)
522{
523 HICON hicon;
524
9cb9fdb3
VZ
525 // do we need the icon of the specific size or would any icon do?
526 bool hasSize = desiredWidth != -1 || desiredHeight != -1;
527
528 wxASSERT_MSG( !hasSize || (desiredWidth != -1 && desiredHeight != -1),
529 _T("width and height should be either both -1 or not") );
530
2dace059
VZ
531 // try to load the icon from this program first to allow overriding the
532 // standard icons (although why one would want to do it considering that
533 // we already have wxApp::GetStdIcon() is unclear)
9990cb50
VZ
534
535 // note that we can't just always call LoadImage() because it seems to do
536 // some icon rescaling internally which results in very ugly 16x16 icons
0d0512bd 537#if defined(__WIN32__) && !defined(__SC__)
9990cb50 538 if ( hasSize )
0d0512bd 539 {
9990cb50
VZ
540 hicon = (HICON)::LoadImage(wxGetInstance(), name, IMAGE_ICON,
541 desiredWidth, desiredHeight,
542 LR_DEFAULTCOLOR);
0d0512bd 543 }
9990cb50 544 else
fea2b62e 545#endif // Win32/!Win32
9990cb50
VZ
546 {
547 hicon = ::LoadIcon(wxGetInstance(), name);
548 }
fea2b62e 549
2dace059 550 // next check if it's not a standard icon
9cb9fdb3 551 if ( !hicon && !hasSize )
2dace059
VZ
552 {
553 static const struct
554 {
555 const wxChar *name;
556 LPTSTR id;
557 } stdIcons[] =
558 {
559 { wxT("wxICON_QUESTION"), IDI_QUESTION },
560 { wxT("wxICON_WARNING"), IDI_EXCLAMATION },
561 { wxT("wxICON_ERROR"), IDI_HAND },
c2edb18a 562 { wxT("wxICON_INFORMATION"), IDI_ASTERISK },
2dace059
VZ
563 };
564
565 for ( size_t nIcon = 0; !hicon && nIcon < WXSIZEOF(stdIcons); nIcon++ )
566 {
567 if ( name == stdIcons[nIcon].name )
568 {
9cb9fdb3 569 hicon = ::LoadIcon((HINSTANCE)NULL, stdIcons[nIcon].id);
2dace059
VZ
570 }
571 }
572 }
573
6bad4c32 574 wxSize size = wxGetHiconSize(hicon);
0d0512bd
VZ
575 icon->SetSize(size.x, size.y);
576
0d0512bd
VZ
577 icon->SetHICON((WXHICON)hicon);
578
579 return icon->Ok();
580}
581
582// ----------------------------------------------------------------------------
583// private functions
584// ----------------------------------------------------------------------------
585
6bad4c32 586wxSize wxGetHiconSize(HICON hicon)
0d0512bd
VZ
587{
588 wxSize size(32, 32); // default
589
590#ifdef __WIN32__
591 // Win32s doesn't have GetIconInfo function...
592 if ( hicon && wxGetOsVersion() != wxWIN32S )
593 {
594 ICONINFO info;
595 if ( !::GetIconInfo(hicon, &info) )
596 {
f6bcfd97 597 wxLogLastError(wxT("GetIconInfo"));
0d0512bd
VZ
598 }
599 else
600 {
601 HBITMAP hbmp = info.hbmMask;
602 if ( hbmp )
603 {
604 BITMAP bm;
605 if ( ::GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm) )
606 {
607 size = wxSize(bm.bmWidth, bm.bmHeight);
608 }
609
610 ::DeleteObject(info.hbmMask);
611 }
612 if ( info.hbmColor )
613 ::DeleteObject(info.hbmColor);
614 }
615 }
616#endif
617
618 return size;
619}
04ef50df
JS
620#endif
621 // __WXMICROWIN__