X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/e0f15f4ac04b6f1ff6288ece16d44e76663e850d..697c314b162ff4758db0047e548d5401994d2c70:/src/msw/imaglist.cpp diff --git a/src/msw/imaglist.cpp b/src/msw/imaglist.cpp index 4cd16e46c2..4fb0fbb83d 100644 --- a/src/msw/imaglist.cpp +++ b/src/msw/imaglist.cpp @@ -5,8 +5,8 @@ // Modified by: // Created: 04/01/98 // RCS-ID: $Id$ -// Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Copyright: (c) Julian Smart +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -17,10 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ - #pragma implementation "imaglist.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -28,28 +24,24 @@ #pragma hdrstop #endif -#if defined(__WIN95__) - #ifndef WX_PRECOMP + #include "wx/msw/wrapcctl.h" // include "properly" #include "wx/window.h" #include "wx/icon.h" #include "wx/dc.h" #include "wx/string.h" #include "wx/dcmemory.h" - + #include "wx/intl.h" + #include "wx/log.h" + #include "wx/image.h" #include #endif -#include "wx/log.h" -#include "wx/intl.h" - -#include "wx/msw/imaglist.h" +#include "wx/imaglist.h" +#include "wx/dc.h" +#include "wx/msw/dc.h" #include "wx/msw/private.h" -#if !defined(__GNUWIN32_OLD__) && !defined(__TWIN32__) - #include -#endif - // ---------------------------------------------------------------------------- // wxWin macros // ---------------------------------------------------------------------------- @@ -64,7 +56,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxImageList, wxObject) // 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 wxBitmap GetMaskForImage(const wxBitmap& bitmap, const wxBitmap& mask); +static HBITMAP GetMaskForImage(const wxBitmap& bitmap, const wxBitmap& mask); // ============================================================================ // implementation @@ -82,7 +74,21 @@ wxImageList::wxImageList() // Creates an image list bool wxImageList::Create(int width, int height, bool mask, int initial) { - UINT flags = 0; // TODO shouldallow to specify ILC_COLORxxx here + UINT flags = 0; + + // set appropriate color depth +#ifdef __WXWINCE__ + flags |= ILC_COLOR; +#else + 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 +#endif + if ( mask ) flags |= ILC_MASK; @@ -91,7 +97,7 @@ bool wxImageList::Create(int width, int height, bool mask, int initial) initial, 1); if ( !m_hImageList ) { - wxLogLastError("ImageList_Create()"); + wxLogLastError(wxT("ImageList_Create()")); } return m_hImageList != 0; @@ -118,6 +124,14 @@ int wxImageList::GetImageCount() const return ImageList_GetImageCount(GetHImageList()); } +// Returns the size (same for all images) of the images in the list +bool wxImageList::GetSize(int WXUNUSED(index), int &width, int &height) const +{ + wxASSERT_MSG( m_hImageList, _T("invalid image list") ); + + return ImageList_GetIconSize(GetHImageList(), &width, &height) != 0; +} + // ---------------------------------------------------------------------------- // wxImageList operations // ---------------------------------------------------------------------------- @@ -127,8 +141,7 @@ int wxImageList::GetImageCount() const // 'bitmap' and 'mask'. int wxImageList::Add(const wxBitmap& bitmap, const wxBitmap& mask) { - wxBitmap bmpMask = GetMaskForImage(bitmap, mask); - HBITMAP hbmpMask = wxInvertMask(GetHbitmapOf(bmpMask)); + HBITMAP hbmpMask = GetMaskForImage(bitmap, mask); int index = ImageList_Add(GetHImageList(), GetHbitmapOf(bitmap), hbmpMask); if ( index == -1 ) @@ -146,10 +159,6 @@ int wxImageList::Add(const wxBitmap& bitmap, const wxBitmap& mask) // 'bitmap'. int wxImageList::Add(const wxBitmap& bitmap, const wxColour& maskColour) { -#ifdef __TWIN32__ - wxFAIL_MSG(_T("ImageList_AddMasked not implemented in TWIN32")); - return -1; -#else int index = ImageList_AddMasked(GetHImageList(), GetHbitmapOf(bitmap), wxColourToRGB(maskColour)); @@ -159,7 +168,6 @@ int wxImageList::Add(const wxBitmap& bitmap, const wxColour& maskColour) } return index; -#endif } // Adds a bitmap and mask from an icon. @@ -180,33 +188,27 @@ int wxImageList::Add(const wxIcon& icon) bool wxImageList::Replace(int index, const wxBitmap& bitmap, const wxBitmap& mask) { -#ifdef __TWIN32__ - wxFAIL_MSG(_T("ImageList_Replace not implemented in TWIN32")); - return FALSE; -#else - wxBitmap bmpMask = GetMaskForImage(bitmap, mask); - HBITMAP hbmpMask = wxInvertMask(GetHbitmapOf(bmpMask)); + HBITMAP hbmpMask = GetMaskForImage(bitmap, mask); bool ok = ImageList_Replace(GetHImageList(), index, GetHbitmapOf(bitmap), hbmpMask) != 0; if ( !ok ) { - wxLogLastError("ImageList_Add()"); + wxLogLastError(wxT("ImageList_Replace()")); } ::DeleteObject(hbmpMask); return ok; -#endif } // Replaces a bitmap and mask from an icon. bool wxImageList::Replace(int i, const wxIcon& icon) { - bool ok = ImageList_ReplaceIcon(GetHImageList(), i, GetHiconOf(icon)) != 0; + bool ok = ImageList_ReplaceIcon(GetHImageList(), i, GetHiconOf(icon)) != -1; if ( !ok ) { - wxLogLastError("ImageList_ReplaceIcon()"); + wxLogLastError(wxT("ImageList_ReplaceIcon()")); } return ok; @@ -215,34 +217,24 @@ bool wxImageList::Replace(int i, const wxIcon& icon) // Removes the image at the given index. bool wxImageList::Remove(int index) { -#ifdef __TWIN32__ - wxFAIL_MSG(_T("ImageList_Replace not implemented in TWIN32")); - return FALSE; -#else bool ok = ImageList_Remove(GetHImageList(), index) != 0; if ( !ok ) { - wxLogLastError("ImageList_Remove()"); + wxLogLastError(wxT("ImageList_Remove()")); } return ok; -#endif } // Remove all images bool wxImageList::RemoveAll() { - bool ok = ImageList_RemoveAll(GetHImageList()) != 0; - if ( !ok ) - { - wxLogLastError("ImageList_RemoveAll()"); - } - - return ok; + // don't use ImageList_RemoveAll() because mingw32 headers don't have it + return Remove(-1); } // Draws the given image on a dc at the specified position. -// If 'solidBackground' is TRUE, Draw sets the image list background +// 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, @@ -251,20 +243,21 @@ bool wxImageList::Draw(int index, int flags, bool solidBackground) { -#ifdef __TWIN32__ - wxFAIL_MSG(_T("ImageList_Replace not implemented in TWIN32")); - return FALSE; -#else - HDC hDC = GetHdcOf(dc); - wxCHECK_MSG( hDC, FALSE, _T("invalid wxDC in wxImageList::Draw") ); + wxDCImpl *impl = dc.GetImpl(); + wxMSWDCImpl *msw_impl = wxDynamicCast( impl, wxMSWDCImpl ); + if (!msw_impl) + return false; + + HDC hDC = GetHdcOf(*msw_impl); + 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() ) + const wxBrush& brush = dc.GetBackground(); + if ( brush.Ok() ) { - clr = wxColourToRGB(brush->GetColour()); + clr = wxColourToRGB(brush.GetColour()); } } @@ -283,48 +276,134 @@ bool wxImageList::Draw(int index, bool ok = ImageList_Draw(GetHImageList(), index, hDC, x, y, style) != 0; if ( !ok ) { - wxLogLastError("ImageList_Draw()"); + wxLogLastError(wxT("ImageList_Draw()")); } return ok; +} + +// Get the bitmap +wxBitmap wxImageList::GetBitmap(int index) const +{ +#if wxUSE_WXDIB && wxUSE_IMAGE + int bmp_width = 0, bmp_height = 0; + GetSize(index, bmp_width, bmp_height); + + wxBitmap bitmap(bmp_width, bmp_height); + wxMemoryDC dc; + dc.SelectObject(bitmap); + + // draw it the first time to find a suitable mask colour + ((wxImageList*)this)->Draw(index, dc, 0, 0, wxIMAGELIST_DRAW_TRANSPARENT); + dc.SelectObject(wxNullBitmap); + + // find the suitable mask colour + wxImage image = bitmap.ConvertToImage(); + unsigned char r = 0, g = 0, b = 0; + image.FindFirstUnusedColour(&r, &g, &b); + + // redraw whole image and bitmap in the mask colour + image.Create(bmp_width, bmp_height); + image.Replace(0, 0, 0, r, g, b); + bitmap = wxBitmap(image); + + // redraw icon over the mask colour to actually draw it + dc.SelectObject(bitmap); + ((wxImageList*)this)->Draw(index, dc, 0, 0, wxIMAGELIST_DRAW_TRANSPARENT); + dc.SelectObject(wxNullBitmap); + + // get the image, set the mask colour and convert back to get transparent bitmap + image = bitmap.ConvertToImage(); + image.SetMaskColour(r, g, b); + bitmap = wxBitmap(image); +#else + wxBitmap bitmap; #endif + return bitmap; +} + +// Get the icon +wxIcon wxImageList::GetIcon(int index) const +{ + HICON hIcon = ImageList_ExtractIcon(0, GetHImageList(), index); + if (hIcon) + { + wxIcon icon; + icon.SetHICON((WXHICON)hIcon); + + int iconW, iconH; + GetSize(index, iconW, iconH); + icon.SetSize(iconW, iconH); + + return icon; + } + else + return wxNullIcon; } // ---------------------------------------------------------------------------- // helpers // ---------------------------------------------------------------------------- -static wxBitmap GetMaskForImage(const wxBitmap& bitmap, const wxBitmap& mask) +static HBITMAP GetMaskForImage(const wxBitmap& bitmap, const wxBitmap& mask) { - wxBitmap bmpMask; +#if wxUSE_IMAGE + wxBitmap bitmapWithMask; +#endif // wxUSE_IMAGE + + HBITMAP hbmpMask; + wxMask *pMask; + bool deleteMask = false; if ( mask.Ok() ) { - bmpMask = mask; + hbmpMask = GetHbitmapOf(mask); + pMask = NULL; } else { - wxMask *pMask = bitmap.GetMask(); - if ( pMask ) + pMask = bitmap.GetMask(); + +#if wxUSE_IMAGE + // check if we don't have alpha in this bitmap -- we can create a mask + // from it (and we need to do it for the older systems which don't + // support 32bpp bitmaps natively) + if ( !pMask ) { - bmpMask.SetHBITMAP(pMask->GetMaskBitmap()); + wxImage img(bitmap.ConvertToImage()); + if ( img.HasAlpha() ) + { + img.ConvertAlphaToMask(); + bitmapWithMask = wxBitmap(img); + pMask = bitmapWithMask.GetMask(); + } } +#endif // wxUSE_IMAGE + + 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(); } - if ( !bmpMask.Ok() ) + // windows mask convention is opposite to the wxWidgets one + HBITMAP hbmpMaskInv = wxInvertMask(hbmpMask); + + if ( deleteMask ) { - // create a non transparent mask - apparently, this is needed under - // Win9x (it doesn't behave correctly if it's passed 0 mask) - bmpMask.Create(bitmap.GetWidth(), bitmap.GetHeight(), 1); - - wxMemoryDC dcMem; - dcMem.SelectObject(bmpMask); - dcMem.Clear(); - dcMem.SelectObject(wxNullBitmap); + delete pMask; } - return bmpMask; + return hbmpMaskInv; } - -#endif // Win95 -