]> git.saurik.com Git - wxWidgets.git/blame - src/msw/gdiimage.cpp
Fix accelerstors with down and left
[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>
65571936 9// Licence: wxWindows licence
0d0512bd
VZ
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
0d0512bd
VZ
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#ifndef WX_PRECOMP
28 #include "wx/string.h"
f94dfb38 29 #include "wx/log.h"
0d0512bd
VZ
30#endif // WX_PRECOMP
31
e42a6c18
VZ
32#include "wx/msw/private.h"
33
0d0512bd
VZ
34#include "wx/app.h"
35
f66f0fd7 36#include "wx/bitmap.h"
474df218 37#include "wx/msw/gdiimage.h"
4676948b
JS
38
39#if wxUSE_WXDIB
474df218 40#include "wx/msw/dib.h"
4676948b
JS
41#endif
42
43#ifdef __WXWINCE__
44#include <winreg.h>
45#include <shellapi.h>
46#endif
f66f0fd7 47
419430a0
JS
48#include "wx/file.h"
49
d162a7ee 50#include "wx/listimpl.cpp"
259c43f6 51WX_DEFINE_LIST(wxGDIImageHandlerList)
d162a7ee 52
0d0512bd
VZ
53// ----------------------------------------------------------------------------
54// private classes
55// ----------------------------------------------------------------------------
56
04ef50df
JS
57#ifndef __WXMICROWIN__
58
0d0512bd
VZ
59// all image handlers are declared/defined in this file because the outside
60// world doesn't have to know about them (but only about wxBITMAP_TYPE_XXX ids)
61
62class WXDLLEXPORT wxBMPFileHandler : public wxBitmapHandler
63{
64public:
65 wxBMPFileHandler() : wxBitmapHandler(_T("Windows bitmap file"), _T("bmp"),
66 wxBITMAP_TYPE_BMP)
67 {
68 }
69
70 virtual bool LoadFile(wxBitmap *bitmap,
71 const wxString& name, long flags,
72 int desiredWidth, int desiredHeight);
73 virtual bool SaveFile(wxBitmap *bitmap,
74 const wxString& name, int type,
75 const wxPalette *palette = NULL);
76
77private:
78 DECLARE_DYNAMIC_CLASS(wxBMPFileHandler)
79};
80
81class WXDLLEXPORT wxBMPResourceHandler: public wxBitmapHandler
82{
83public:
84 wxBMPResourceHandler() : wxBitmapHandler(_T("Windows bitmap resource"),
85 wxEmptyString,
86 wxBITMAP_TYPE_BMP_RESOURCE)
87 {
88 }
89
90 virtual bool LoadFile(wxBitmap *bitmap,
91 const wxString& name, long flags,
92 int desiredWidth, int desiredHeight);
93
94private:
95 DECLARE_DYNAMIC_CLASS(wxBMPResourceHandler)
96};
97
98class WXDLLEXPORT wxIconHandler : public wxGDIImageHandler
99{
100public:
101 wxIconHandler(const wxString& name, const wxString& ext, long type)
102 : wxGDIImageHandler(name, ext, type)
103 {
104 }
105
106 // creating and saving icons is not supported
107 virtual bool Create(wxGDIImage *WXUNUSED(image),
108 void *WXUNUSED(data),
109 long WXUNUSED(flags),
110 int WXUNUSED(width),
111 int WXUNUSED(height),
112 int WXUNUSED(depth) = 1)
113 {
4f8090e0 114 return false;
0d0512bd
VZ
115 }
116
117 virtual bool Save(wxGDIImage *WXUNUSED(image),
118 const wxString& WXUNUSED(name),
119 int WXUNUSED(type))
120 {
4f8090e0 121 return false;
0d0512bd
VZ
122 }
123
124 virtual bool Load(wxGDIImage *image,
125 const wxString& name,
126 long flags,
127 int desiredWidth, int desiredHeight)
128 {
129 wxIcon *icon = wxDynamicCast(image, wxIcon);
4f8090e0 130 wxCHECK_MSG( icon, false, _T("wxIconHandler only works with icons") );
0d0512bd
VZ
131
132 return LoadIcon(icon, name, flags, desiredWidth, desiredHeight);
133 }
134
135protected:
136 virtual bool LoadIcon(wxIcon *icon,
137 const wxString& name, long flags,
138 int desiredWidth = -1, int desiredHeight = -1) = 0;
139};
140
141class WXDLLEXPORT wxICOFileHandler : public wxIconHandler
142{
143public:
144 wxICOFileHandler() : wxIconHandler(_T("ICO icon file"),
145 _T("ico"),
146 wxBITMAP_TYPE_ICO)
147 {
148 }
149
795c9ab8 150protected:
0d0512bd
VZ
151 virtual bool LoadIcon(wxIcon *icon,
152 const wxString& name, long flags,
153 int desiredWidth = -1, int desiredHeight = -1);
154
155private:
156 DECLARE_DYNAMIC_CLASS(wxICOFileHandler)
157};
158
159class WXDLLEXPORT wxICOResourceHandler: public wxIconHandler
160{
161public:
162 wxICOResourceHandler() : wxIconHandler(_T("ICO resource"),
163 _T("ico"),
164 wxBITMAP_TYPE_ICO_RESOURCE)
165 {
166 }
167
795c9ab8 168protected:
0d0512bd
VZ
169 virtual bool LoadIcon(wxIcon *icon,
170 const wxString& name, long flags,
171 int desiredWidth = -1, int desiredHeight = -1);
172
173private:
174 DECLARE_DYNAMIC_CLASS(wxICOResourceHandler)
175};
176
177// ----------------------------------------------------------------------------
178// wxWin macros
179// ----------------------------------------------------------------------------
180
621b3e21
VZ
181IMPLEMENT_DYNAMIC_CLASS(wxBMPFileHandler, wxBitmapHandler)
182IMPLEMENT_DYNAMIC_CLASS(wxBMPResourceHandler, wxBitmapHandler)
183IMPLEMENT_DYNAMIC_CLASS(wxICOFileHandler, wxObject)
184IMPLEMENT_DYNAMIC_CLASS(wxICOResourceHandler, wxObject)
0d0512bd
VZ
185
186// ----------------------------------------------------------------------------
187// private functions
188// ----------------------------------------------------------------------------
189
04ef50df
JS
190#endif
191 // __MICROWIN__
0d0512bd
VZ
192
193// ============================================================================
194// implementation
195// ============================================================================
196
d162a7ee 197wxGDIImageHandlerList wxGDIImage::ms_handlers;
0d0512bd
VZ
198
199// ----------------------------------------------------------------------------
200// wxGDIImage functions forwarded to wxGDIImageRefData
201// ----------------------------------------------------------------------------
202
203bool wxGDIImage::FreeResource(bool WXUNUSED(force))
204{
205 if ( !IsNull() )
206 {
207 GetGDIImageData()->Free();
208 GetGDIImageData()->m_handle = 0;
209 }
210
4f8090e0 211 return true;
0d0512bd
VZ
212}
213
2b5f62a0 214WXHANDLE wxGDIImage::GetResourceHandle() const
0d0512bd
VZ
215{
216 return GetHandle();
217}
218
219// ----------------------------------------------------------------------------
220// wxGDIImage handler stuff
221// ----------------------------------------------------------------------------
222
223void wxGDIImage::AddHandler(wxGDIImageHandler *handler)
224{
225 ms_handlers.Append(handler);
226}
227
228void wxGDIImage::InsertHandler(wxGDIImageHandler *handler)
229{
230 ms_handlers.Insert(handler);
231}
232
233bool wxGDIImage::RemoveHandler(const wxString& name)
234{
235 wxGDIImageHandler *handler = FindHandler(name);
236 if ( handler )
237 {
238 ms_handlers.DeleteObject(handler);
4f8090e0 239 return true;
0d0512bd
VZ
240 }
241 else
4f8090e0 242 return false;
0d0512bd
VZ
243}
244
245wxGDIImageHandler *wxGDIImage::FindHandler(const wxString& name)
246{
222ed1d6 247 wxGDIImageHandlerList::compatibility_iterator node = ms_handlers.GetFirst();
0d0512bd
VZ
248 while ( node )
249 {
d162a7ee 250 wxGDIImageHandler *handler = node->GetData();
0d0512bd
VZ
251 if ( handler->GetName() == name )
252 return handler;
4f8090e0 253 node = node->GetNext();
0d0512bd
VZ
254 }
255
256 return NULL;
257}
258
259wxGDIImageHandler *wxGDIImage::FindHandler(const wxString& extension,
260 long type)
261{
222ed1d6 262 wxGDIImageHandlerList::compatibility_iterator node = ms_handlers.GetFirst();
0d0512bd
VZ
263 while ( node )
264 {
d162a7ee 265 wxGDIImageHandler *handler = node->GetData();
795c9ab8 266 if ( (handler->GetExtension() == extension) &&
0d0512bd
VZ
267 (type == -1 || handler->GetType() == type) )
268 {
269 return handler;
270 }
271
4f8090e0 272 node = node->GetNext();
0d0512bd
VZ
273 }
274 return NULL;
275}
276
277wxGDIImageHandler *wxGDIImage::FindHandler(long type)
278{
222ed1d6 279 wxGDIImageHandlerList::compatibility_iterator node = ms_handlers.GetFirst();
0d0512bd
VZ
280 while ( node )
281 {
d162a7ee 282 wxGDIImageHandler *handler = node->GetData();
0d0512bd
VZ
283 if ( handler->GetType() == type )
284 return handler;
285
4f8090e0 286 node = node->GetNext();
0d0512bd
VZ
287 }
288
289 return NULL;
290}
291
292void wxGDIImage::CleanUpHandlers()
293{
222ed1d6 294 wxGDIImageHandlerList::compatibility_iterator node = ms_handlers.GetFirst();
0d0512bd
VZ
295 while ( node )
296 {
d162a7ee 297 wxGDIImageHandler *handler = node->GetData();
222ed1d6 298 wxGDIImageHandlerList::compatibility_iterator next = node->GetNext();
0d0512bd 299 delete handler;
222ed1d6 300 ms_handlers.Erase( node );
0d0512bd
VZ
301 node = next;
302 }
303}
304
305void wxGDIImage::InitStandardHandlers()
306{
04ef50df 307#ifndef __WXMICROWIN__
0d0512bd
VZ
308 AddHandler(new wxBMPResourceHandler);
309 AddHandler(new wxBMPFileHandler);
0d0512bd
VZ
310 AddHandler(new wxICOResourceHandler);
311 AddHandler(new wxICOFileHandler);
04ef50df 312#endif
0d0512bd
VZ
313}
314
04ef50df
JS
315#ifndef __WXMICROWIN__
316
0d0512bd
VZ
317// ----------------------------------------------------------------------------
318// wxBitmap handlers
319// ----------------------------------------------------------------------------
320
321bool wxBMPResourceHandler::LoadFile(wxBitmap *bitmap,
322 const wxString& name, long WXUNUSED(flags),
323 int WXUNUSED(desiredWidth),
324 int WXUNUSED(desiredHeight))
325{
326 // TODO: load colourmap.
327 bitmap->SetHBITMAP((WXHBITMAP)::LoadBitmap(wxGetInstance(), name));
328
8bbbae21 329 if ( !bitmap->Ok() )
0d0512bd
VZ
330 {
331 // it's probably not found
332 wxLogError(wxT("Can't load bitmap '%s' from resources! Check .rc file."),
333 name.c_str());
8bbbae21 334
4f8090e0 335 return false;
8bbbae21
VZ
336 }
337
338 BITMAP bm;
339 if ( !::GetObject(GetHbitmapOf(*bitmap), sizeof(BITMAP), (LPSTR) &bm) )
340 {
341 wxLogLastError(wxT("GetObject(HBITMAP)"));
0d0512bd
VZ
342 }
343
8bbbae21
VZ
344 bitmap->SetWidth(bm.bmWidth);
345 bitmap->SetHeight(bm.bmHeight);
346 bitmap->SetDepth(bm.bmBitsPixel);
347
9542f0a1
VZ
348 // use 0xc0c0c0 as transparent colour by default
349 bitmap->SetMask(new wxMask(*bitmap, *wxLIGHT_GREY));
350
4f8090e0 351 return true;
0d0512bd
VZ
352}
353
354bool wxBMPFileHandler::LoadFile(wxBitmap *bitmap,
355 const wxString& name, long WXUNUSED(flags),
356 int WXUNUSED(desiredWidth),
357 int WXUNUSED(desiredHeight))
358{
4676948b 359#if wxUSE_WXDIB
474df218 360 wxCHECK_MSG( bitmap, false, _T("NULL bitmap in LoadFile") );
d275c7eb 361
474df218 362 wxDIB dib(name);
0d0512bd 363
a91bcd3b 364 return dib.IsOk() && bitmap->CopyFromDIB(dib);
4676948b 365#else
213ceb3f 366 return false;
4676948b 367#endif
0d0512bd
VZ
368}
369
370bool wxBMPFileHandler::SaveFile(wxBitmap *bitmap,
371 const wxString& name,
372 int WXUNUSED(type),
2b254edf 373 const wxPalette * WXUNUSED(pal))
0d0512bd 374{
4676948b 375#if wxUSE_WXDIB
2b254edf
VZ
376 wxCHECK_MSG( bitmap, false, _T("NULL bitmap in SaveFile") );
377
378 wxDIB dib(*bitmap);
379
380 return dib.Save(name);
4676948b 381#else
213ceb3f 382 return false;
4676948b 383#endif
0d0512bd
VZ
384}
385
386// ----------------------------------------------------------------------------
387// wxIcon handlers
388// ----------------------------------------------------------------------------
389
390bool wxICOFileHandler::LoadIcon(wxIcon *icon,
391 const wxString& name,
33ac7e6f 392 long WXUNUSED(flags),
0d0512bd
VZ
393 int desiredWidth, int desiredHeight)
394{
0d0512bd
VZ
395 icon->UnRef();
396
397 // actual size
398 wxSize size;
399
a4352768
VZ
400 HICON hicon = NULL;
401
2dace059
VZ
402 // Parse the filename: it may be of the form "filename;n" in order to
403 // specify the nth icon in the file.
404 //
405 // For the moment, ignore the issue of possible semicolons in the
406 // filename.
ff9aab3c 407 int iconIndex = 0;
2dace059 408 wxString nameReal(name);
ff9aab3c 409 wxString strIconIndex = name.AfterLast(wxT(';'));
b642d457 410 if (strIconIndex != name)
ff9aab3c
JS
411 {
412 iconIndex = wxAtoi(strIconIndex);
2dace059 413 nameReal = name.BeforeLast(wxT(';'));
ff9aab3c
JS
414 }
415
2b5f62a0
VZ
416#if 0
417 // If we don't know what size icon we're looking for,
418 // try to find out what's there.
419 // Unfortunately this doesn't work, because ExtractIconEx
420 // will scale the icon to the 'desired' size, even if that
421 // size of icon isn't explicitly stored. So we would have
422 // to parse the icon file outselves.
423 if ( desiredWidth == -1 &&
424 desiredHeight == -1)
425 {
426 // Try loading a large icon first
427 if ( ::ExtractIconEx(nameReal, iconIndex, &hicon, NULL, 1) == 1)
428 {
429 }
430 // Then try loading a small icon
431 else if ( ::ExtractIconEx(nameReal, iconIndex, NULL, &hicon, 1) == 1)
432 {
433 }
434 }
435 else
436#endif
4676948b 437 // were we asked for a large icon?
a4352768
VZ
438 if ( desiredWidth == ::GetSystemMetrics(SM_CXICON) &&
439 desiredHeight == ::GetSystemMetrics(SM_CYICON) )
440 {
ff9aab3c 441 // get the specified large icon from file
2dace059 442 if ( !::ExtractIconEx(nameReal, iconIndex, &hicon, NULL, 1) )
a4352768
VZ
443 {
444 // it is not an error, but it might still be useful to be informed
445 // about it optionally
446 wxLogTrace(_T("iconload"),
447 _T("No large icons found in the file '%s'."),
448 name.c_str());
449 }
450 }
451 else if ( desiredWidth == ::GetSystemMetrics(SM_CXSMICON) &&
452 desiredHeight == ::GetSystemMetrics(SM_CYSMICON) )
453 {
ff9aab3c 454 // get the specified small icon from file
2dace059 455 if ( !::ExtractIconEx(nameReal, iconIndex, NULL, &hicon, 1) )
a4352768
VZ
456 {
457 wxLogTrace(_T("iconload"),
458 _T("No small icons found in the file '%s'."),
459 name.c_str());
460 }
461 }
462 //else: not standard size, load below
463
4676948b 464#ifndef __WXWINCE__
a4352768
VZ
465 if ( !hicon )
466 {
d8f3f983
RD
467 // take any size icon from the file by index
468 hicon = ::ExtractIcon(wxGetInstance(), nameReal, iconIndex);
a4352768 469 }
4676948b 470#endif
a4352768 471
0d0512bd
VZ
472 if ( !hicon )
473 {
474 wxLogSysError(_T("Failed to load icon from the file '%s'"),
475 name.c_str());
476
4f8090e0 477 return false;
0d0512bd
VZ
478 }
479
6bad4c32 480 size = wxGetHiconSize(hicon);
0d0512bd
VZ
481
482 if ( (desiredWidth != -1 && desiredWidth != size.x) ||
483 (desiredHeight != -1 && desiredHeight != size.y) )
484 {
a4352768 485 wxLogTrace(_T("iconload"),
4f8090e0 486 _T("Returning false from wxICOFileHandler::Load because of the size mismatch: actual (%d, %d), requested (%d, %d)"),
a4352768
VZ
487 size.x, size.y,
488 desiredWidth, desiredHeight);
0d0512bd
VZ
489
490 ::DestroyIcon(hicon);
491
4f8090e0 492 return false;
0d0512bd
VZ
493 }
494
495 icon->SetHICON((WXHICON)hicon);
496 icon->SetSize(size.x, size.y);
497
498 return icon->Ok();
0d0512bd
VZ
499}
500
501bool wxICOResourceHandler::LoadIcon(wxIcon *icon,
502 const wxString& name,
33ac7e6f 503 long WXUNUSED(flags),
0d0512bd
VZ
504 int desiredWidth, int desiredHeight)
505{
506 HICON hicon;
507
9cb9fdb3
VZ
508 // do we need the icon of the specific size or would any icon do?
509 bool hasSize = desiredWidth != -1 || desiredHeight != -1;
510
511 wxASSERT_MSG( !hasSize || (desiredWidth != -1 && desiredHeight != -1),
512 _T("width and height should be either both -1 or not") );
513
2dace059
VZ
514 // try to load the icon from this program first to allow overriding the
515 // standard icons (although why one would want to do it considering that
516 // we already have wxApp::GetStdIcon() is unclear)
9990cb50
VZ
517
518 // note that we can't just always call LoadImage() because it seems to do
519 // some icon rescaling internally which results in very ugly 16x16 icons
9990cb50 520 if ( hasSize )
0d0512bd 521 {
9990cb50
VZ
522 hicon = (HICON)::LoadImage(wxGetInstance(), name, IMAGE_ICON,
523 desiredWidth, desiredHeight,
524 LR_DEFAULTCOLOR);
0d0512bd 525 }
9990cb50 526 else
9990cb50
VZ
527 {
528 hicon = ::LoadIcon(wxGetInstance(), name);
529 }
fea2b62e 530
2dace059 531 // next check if it's not a standard icon
4676948b 532#ifndef __WXWINCE__
9cb9fdb3 533 if ( !hicon && !hasSize )
2dace059
VZ
534 {
535 static const struct
536 {
537 const wxChar *name;
538 LPTSTR id;
539 } stdIcons[] =
540 {
541 { wxT("wxICON_QUESTION"), IDI_QUESTION },
542 { wxT("wxICON_WARNING"), IDI_EXCLAMATION },
543 { wxT("wxICON_ERROR"), IDI_HAND },
c2edb18a 544 { wxT("wxICON_INFORMATION"), IDI_ASTERISK },
2dace059
VZ
545 };
546
547 for ( size_t nIcon = 0; !hicon && nIcon < WXSIZEOF(stdIcons); nIcon++ )
548 {
549 if ( name == stdIcons[nIcon].name )
550 {
9cb9fdb3 551 hicon = ::LoadIcon((HINSTANCE)NULL, stdIcons[nIcon].id);
2dace059
VZ
552 }
553 }
554 }
4676948b 555#endif
2dace059 556
6bad4c32 557 wxSize size = wxGetHiconSize(hicon);
0d0512bd
VZ
558 icon->SetSize(size.x, size.y);
559
0d0512bd
VZ
560 icon->SetHICON((WXHICON)hicon);
561
562 return icon->Ok();
563}
564
565// ----------------------------------------------------------------------------
566// private functions
567// ----------------------------------------------------------------------------
568
0c0d1521 569wxSize wxGetHiconSize(HICON WXUNUSED_IN_WINCE(hicon))
0d0512bd 570{
7010702f
WS
571 // default icon size on this hardware
572 // usually 32x32 but can be other (smaller) on pocket devices
573 wxSize size(::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON));
574
4676948b 575#ifndef __WXWINCE__
0d0512bd
VZ
576 if ( hicon && wxGetOsVersion() != wxWIN32S )
577 {
578 ICONINFO info;
579 if ( !::GetIconInfo(hicon, &info) )
580 {
f6bcfd97 581 wxLogLastError(wxT("GetIconInfo"));
0d0512bd
VZ
582 }
583 else
584 {
585 HBITMAP hbmp = info.hbmMask;
586 if ( hbmp )
587 {
588 BITMAP bm;
589 if ( ::GetObject(hbmp, sizeof(BITMAP), (LPSTR) &bm) )
590 {
591 size = wxSize(bm.bmWidth, bm.bmHeight);
592 }
593
594 ::DeleteObject(info.hbmMask);
595 }
596 if ( info.hbmColor )
597 ::DeleteObject(info.hbmColor);
598 }
599 }
4676948b 600#endif
0c0d1521 601
0d0512bd
VZ
602 return size;
603}
474df218
VZ
604
605#endif // __WXMICROWIN__
606