X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ad81651f00edc6f489d9b6a0839d316a964fd521..ee3510132b8b4160f848bd4f502a6f5315f90dbc:/src/msw/imaglist.cpp diff --git a/src/msw/imaglist.cpp b/src/msw/imaglist.cpp index 642fc9290c..46cb341d12 100644 --- a/src/msw/imaglist.cpp +++ b/src/msw/imaglist.cpp @@ -1,34 +1,43 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: imaglist.cpp -// Purpose: wxImageList +// Name: src/msw/imaglist.cpp +// Purpose: wxImageList implementation for Win32 // Author: Julian Smart // Modified by: // Created: 04/01/98 // RCS-ID: $Id$ // Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Licence: wxWindows license ///////////////////////////////////////////////////////////////////////////// +// ============================================================================ +// declarations +// ============================================================================ + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + #ifdef __GNUG__ -#pragma implementation "imaglist.h" + #pragma implementation "imaglist.h" #endif // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" #ifdef __BORLANDC__ -#pragma hdrstop + #pragma hdrstop #endif #if defined(__WIN95__) #ifndef WX_PRECOMP -#include -#include "wx/setup.h" -#include "wx/window.h" -#include "wx/icon.h" -#include "wx/dc.h" -#include "wx/string.h" + #include "wx/window.h" + #include "wx/icon.h" + #include "wx/dc.h" + #include "wx/string.h" + #include "wx/dcmemory.h" + + #include #endif #include "wx/log.h" @@ -37,87 +46,113 @@ #include "wx/msw/imaglist.h" #include "wx/msw/private.h" -#if (defined(__WIN95__) && !defined(__GNUWIN32__)) || defined(__TWIN32__) || defined(wxUSE_NORLANDER_HEADERS) -#include +#if defined(__WIN95__) && !((defined(__GNUWIN32_OLD__) || defined(__TWIN32__)) && !defined(__CYGWIN10__)) + #include #endif +// ---------------------------------------------------------------------------- +// wxWin macros +// ---------------------------------------------------------------------------- + IMPLEMENT_DYNAMIC_CLASS(wxImageList, wxObject) -wxImageList::wxImageList(void) +#define GetHImageList() ((HIMAGELIST)m_hImageList) + +// ---------------------------------------------------------------------------- +// private functions +// ---------------------------------------------------------------------------- + +// returns the mask if it's valid, otherwise the bitmap mask and, if it's not +// valid neither, a "solid" mask (no transparent zones at all) +static HBITMAP GetMaskForImage(const wxBitmap& bitmap, const wxBitmap& mask); + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxImageList creation/destruction +// ---------------------------------------------------------------------------- + +wxImageList::wxImageList() { m_hImageList = 0; } -wxImageList::~wxImageList(void) +// Creates an image list +bool wxImageList::Create(int width, int height, bool mask, int initial) { - if ( m_hImageList ) - ImageList_Destroy((HIMAGELIST) m_hImageList); - m_hImageList = 0; + UINT flags = 0; + + // set appropriate color depth + int dd = wxDisplayDepth(); + if (dd <= 4) flags |= ILC_COLOR; // 16 color + else if (dd <= 8) flags |= ILC_COLOR8; // 256 color + else if (dd <= 16) flags |= ILC_COLOR16; // 64k hi-color + else if (dd <= 24) flags |= ILC_COLOR24; // 16m truecolor + else if (dd <= 32) flags |= ILC_COLOR32; // 16m truecolor + + if ( mask ) + flags |= ILC_MASK; + + // Grow by 1, I guess this is reasonable behaviour most of the time + m_hImageList = (WXHIMAGELIST) ImageList_Create(width, height, flags, + initial, 1); + if ( !m_hImageList ) + { + wxLogLastError(wxT("ImageList_Create()")); + } + + return m_hImageList != 0; } +wxImageList::~wxImageList() +{ + if ( m_hImageList ) + { + ImageList_Destroy(GetHImageList()); + m_hImageList = 0; + } +} -// Attributes -//////////////////////////////////////////////////////////////////////////// +// ---------------------------------------------------------------------------- +// wxImageList attributes +// ---------------------------------------------------------------------------- // Returns the number of images in the image list. -int wxImageList::GetImageCount(void) const +int wxImageList::GetImageCount() const { - return ImageList_GetImageCount((HIMAGELIST) m_hImageList); -} + wxASSERT_MSG( m_hImageList, _T("invalid image list") ); -// Operations -//////////////////////////////////////////////////////////////////////////// + return ImageList_GetImageCount(GetHImageList()); +} -// Creates an image list -bool wxImageList::Create(int width, int height, bool mask, int initial) +// Returns the size (same for all images) of the images in the list +bool wxImageList::GetSize(int WXUNUSED(index), int &width, int &height) const { - UINT flags = 0; - if ( mask ) - flags |= ILC_MASK; + wxASSERT_MSG( m_hImageList, _T("invalid image list") ); - // Grow by 1, I guess this is reasonable behaviour most of the time - m_hImageList = (WXHIMAGELIST) ImageList_Create(width, height, flags, initial, 1); - return (m_hImageList != 0); + return ImageList_GetIconSize(GetHImageList(), &width, &height) != 0; } +// ---------------------------------------------------------------------------- +// wxImageList operations +// ---------------------------------------------------------------------------- + // Adds a bitmap, and optionally a mask bitmap. // Note that wxImageList creates new bitmaps, so you may delete // 'bitmap' and 'mask'. int wxImageList::Add(const wxBitmap& bitmap, const wxBitmap& mask) { - HBITMAP hBitmap1 = (HBITMAP) bitmap.GetHBITMAP(); - HBITMAP hBitmap2 = 0; - if ( mask.Ok() ) - hBitmap2 = (HBITMAP) mask.GetHBITMAP(); - else if (bitmap.GetMask()) - hBitmap2 = (HBITMAP) bitmap.GetMask()->GetMaskBitmap(); - - HBITMAP hBitmapI=0; - if(hBitmap2!=0) { - // Microsoft imagelist masks are inverted from wxWindows mask standard (white is mask color) - BITMAP bm; - ::GetObject(hBitmap2,sizeof(BITMAP),(LPVOID)&bm); - int w=bm.bmWidth; - int h=bm.bmHeight; - HDC hdc = ::CreateCompatibleDC(NULL); - HDC hdci = ::CreateCompatibleDC(NULL); - hBitmapI = ::CreateCompatibleBitmap(hdci, w, h); - ::SelectObject(hdc, hBitmap2); - ::SelectObject(hdci, hBitmapI); - ::BitBlt(hdci, 0, 0, w, h, hdc, 0, 0, NOTSRCCOPY); - ::DeleteDC(hdc); - ::DeleteDC(hdci); - } + HBITMAP hbmpMask = GetMaskForImage(bitmap, mask); - int index = ImageList_Add((HIMAGELIST) GetHIMAGELIST(), hBitmap1, hBitmapI); - if ( index == -1 ) + int index = ImageList_Add(GetHImageList(), GetHbitmapOf(bitmap), hbmpMask); + if ( index == -1 ) { wxLogError(_("Couldn't add an image to the image list.")); } - // Clean up inverted mask - if(hBitmapI!=0) - ::DeleteObject(hBitmapI); + ::DeleteObject(hbmpMask); return index; } @@ -128,126 +163,196 @@ int wxImageList::Add(const wxBitmap& bitmap, const wxBitmap& mask) int wxImageList::Add(const wxBitmap& bitmap, const wxColour& maskColour) { #ifdef __TWIN32__ - wxFAIL_MSG("ImageList_AddMasked not implemented in TWIN32"); - return -1; + wxFAIL_MSG(_T("ImageList_AddMasked not implemented in TWIN32")); + return -1; #else - HBITMAP hBitmap1 = (HBITMAP) bitmap.GetHBITMAP(); - COLORREF colorRef = PALETTERGB(maskColour.Red(), maskColour.Green(), maskColour.Blue()); - return ImageList_AddMasked((HIMAGELIST) GetHIMAGELIST(), hBitmap1, colorRef); + int index = ImageList_AddMasked(GetHImageList(), + GetHbitmapOf(bitmap), + wxColourToRGB(maskColour)); + if ( index == -1 ) + { + wxLogError(_("Couldn't add an image to the image list.")); + } + + return index; #endif } // Adds a bitmap and mask from an icon. int wxImageList::Add(const wxIcon& icon) { - HICON hIcon = (HICON) icon.GetHICON(); - return ImageList_AddIcon((HIMAGELIST) GetHIMAGELIST(), hIcon); + int index = ImageList_AddIcon(GetHImageList(), GetHiconOf(icon)); + if ( index == -1 ) + { + wxLogError(_("Couldn't add an image to the image list.")); + } + + return index; } // Replaces a bitmap, optionally passing a mask bitmap. // Note that wxImageList creates new bitmaps, so you may delete // 'bitmap' and 'mask'. -bool wxImageList::Replace(int index, const wxBitmap& bitmap, const wxBitmap& mask) +bool wxImageList::Replace(int index, + const wxBitmap& bitmap, const wxBitmap& mask) { #ifdef __TWIN32__ - wxFAIL_MSG("ImageList_Replace not implemented in TWIN32"); - return FALSE; + wxFAIL_MSG(_T("ImageList_Replace not implemented in TWIN32")); + return FALSE; #else - HBITMAP hBitmap1 = (HBITMAP) bitmap.GetHBITMAP(); - HBITMAP hBitmap2 = 0; - if ( mask.Ok() ) - hBitmap2 = (HBITMAP) mask.GetHBITMAP(); - return (ImageList_Replace((HIMAGELIST) GetHIMAGELIST(), index, hBitmap1, hBitmap2) != 0); -#endif -} + HBITMAP hbmpMask = GetMaskForImage(bitmap, mask); -/* Not supported by Win95 -// Replacing a bitmap, using the specified colour to create the mask bitmap -// Note that wxImageList creates new bitmaps, so you may delete -// 'bitmap'. -bool wxImageList::Replace(int index, const wxBitmap& bitmap, const wxColour& maskColour) -{ - HBITMAP hBitmap1 = (HBITMAP) bitmap.GetHBITMAP(); - COLORREF colorRef = PALETTERGB(maskColour.Red(), maskColour.Green(), maskColour.Blue()); - return (bool) ImageList_ReplaceMasked((HIMAGELIST) GetHIMAGELIST(), index, hBitmap1, colorRef); + bool ok = ImageList_Replace(GetHImageList(), index, + GetHbitmapOf(bitmap), hbmpMask) != 0; + if ( !ok ) + { + wxLogLastError(wxT("ImageList_Add()")); + } + + ::DeleteObject(hbmpMask); + + return ok; +#endif } -*/ // Replaces a bitmap and mask from an icon. -bool wxImageList::Replace(int index, const wxIcon& icon) +bool wxImageList::Replace(int i, const wxIcon& icon) { - HICON hIcon = (HICON) icon.GetHICON(); - return (ImageList_ReplaceIcon((HIMAGELIST) GetHIMAGELIST(), index, hIcon) != 0); + bool ok = ImageList_ReplaceIcon(GetHImageList(), i, GetHiconOf(icon)) != 0; + if ( !ok ) + { + wxLogLastError(wxT("ImageList_ReplaceIcon()")); + } + + return ok; } // Removes the image at the given index. bool wxImageList::Remove(int index) { #ifdef __TWIN32__ - wxFAIL_MSG("ImageList_Replace not implemented in TWIN32"); - return FALSE; + wxFAIL_MSG(_T("ImageList_Replace not implemented in TWIN32")); + return FALSE; #else - return (ImageList_Remove((HIMAGELIST) GetHIMAGELIST(), index) != 0); + bool ok = ImageList_Remove(GetHImageList(), index) != 0; + if ( !ok ) + { + wxLogLastError(wxT("ImageList_Remove()")); + } + + return ok; #endif } // Remove all images -bool wxImageList::RemoveAll(void) +bool wxImageList::RemoveAll() { - // TODO: Is this correct? - while ( GetImageCount() > 0 ) - { - Remove(0); - } - return TRUE; + // don't use ImageList_RemoveAll() because mingw32 headers don't have it + int count = ImageList_GetImageCount(GetHImageList()); + for ( int i = 0; i < count; i++ ) + { + // the image indexes are shifted, so we should always remove the first + // one + (void)Remove(0); + } + + return TRUE; } // Draws the given image on a dc at the specified position. // If 'solidBackground' is TRUE, Draw sets the image list background // colour to the background colour of the wxDC, to speed up // drawing by eliminating masked drawing where possible. -bool wxImageList::Draw(int index, wxDC& dc, int x, int y, - int flags, bool solidBackground) +bool wxImageList::Draw(int index, + wxDC& dc, + int x, int y, + int flags, + bool solidBackground) { #ifdef __TWIN32__ - wxFAIL_MSG("ImageList_Replace not implemented in TWIN32"); - return FALSE; + wxFAIL_MSG(_T("ImageList_Replace not implemented in TWIN32")); + return FALSE; #else - HDC hDC = (HDC) dc.GetHDC(); - if ( !hDC ) - return FALSE; - - if ( solidBackground ) - { - wxBrush *brush = & dc.GetBackground(); - if ( brush && brush->Ok()) - { - wxColour col(brush->GetColour()); - ImageList_SetBkColor((HIMAGELIST) GetHIMAGELIST(), - PALETTERGB(col.Red(), col.Green(), col.Blue())); - } - else - ImageList_SetBkColor((HIMAGELIST) GetHIMAGELIST(), - CLR_NONE); - } - else - ImageList_SetBkColor((HIMAGELIST) GetHIMAGELIST(), - CLR_NONE); + HDC hDC = GetHdcOf(dc); + wxCHECK_MSG( hDC, FALSE, _T("invalid wxDC in wxImageList::Draw") ); + + COLORREF clr = CLR_NONE; // transparent by default + if ( solidBackground ) + { + wxBrush *brush = & dc.GetBackground(); + if ( brush && brush->Ok() ) + { + clr = wxColourToRGB(brush->GetColour()); + } + } + + ImageList_SetBkColor(GetHImageList(), clr); UINT style = 0; - if ( flags & wxIMAGELIST_DRAW_NORMAL ) - style |= ILD_NORMAL; - if ( flags & wxIMAGELIST_DRAW_TRANSPARENT ) - style |= ILD_TRANSPARENT; - if ( flags & wxIMAGELIST_DRAW_SELECTED ) - style |= ILD_SELECTED; - if ( flags & wxIMAGELIST_DRAW_FOCUSED ) - style |= ILD_FOCUS; - - return (ImageList_Draw((HIMAGELIST) GetHIMAGELIST(), index, hDC, - x, y, style) != 0); + if ( flags & wxIMAGELIST_DRAW_NORMAL ) + style |= ILD_NORMAL; + if ( flags & wxIMAGELIST_DRAW_TRANSPARENT ) + style |= ILD_TRANSPARENT; + if ( flags & wxIMAGELIST_DRAW_SELECTED ) + style |= ILD_SELECTED; + if ( flags & wxIMAGELIST_DRAW_FOCUSED ) + style |= ILD_FOCUS; + + bool ok = ImageList_Draw(GetHImageList(), index, hDC, x, y, style) != 0; + if ( !ok ) + { + wxLogLastError(wxT("ImageList_Draw()")); + } + + return ok; #endif } -#endif +// ---------------------------------------------------------------------------- +// helpers +// ---------------------------------------------------------------------------- + +static HBITMAP GetMaskForImage(const wxBitmap& bitmap, const wxBitmap& mask) +{ + HBITMAP hbmpMask; + wxMask *pMask; + bool deleteMask = FALSE; + + if ( mask.Ok() ) + { + hbmpMask = GetHbitmapOf(mask); + pMask = NULL; + } + else + { + pMask = bitmap.GetMask(); + if ( !pMask ) + { + // use the light grey count as transparent: the trouble here is + // that the light grey might have been changed by Windows behind + // our back, so use the standard colour map to get its real value + wxCOLORMAP *cmap = wxGetStdColourMap(); + wxColour col; + wxRGBToColour(col, cmap[wxSTD_COL_BTNFACE].from); + + pMask = new wxMask(bitmap, col); + + deleteMask = TRUE; + } + + hbmpMask = (HBITMAP)pMask->GetMaskBitmap(); + } + + // windows mask convention is opposite to the wxWindows one + HBITMAP hbmpMaskInv = wxInvertMask(hbmpMask); + + if ( deleteMask ) + { + delete pMask; + } + + return hbmpMaskInv; +} + +#endif // Win95