diff --git a/source/Platform/Win32/Win32Display.cpp b/source/Platform/Win32/Win32Display.cpp index f8bbe49..c24b61a 100644 --- a/source/Platform/Win32/Win32Display.cpp +++ b/source/Platform/Win32/Win32Display.cpp @@ -127,21 +127,71 @@ void Win32Display::showCursor(bool value) ::SetCursor(m_cursor); } -void Win32Display::setIcon(const std::string& icon) +void Win32Display::setIcon(unsigned int width, unsigned int height, const uint8_t *pixels) { - HICON hIcon = (HICON) ::LoadImage(0, icon.c_str(), IMAGE_ICON, - 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE); + ::HDC hdc; + ::ICONINFO ii; + ::BITMAPV5HEADER bi; + ::HBITMAP bmp_color, bmp_mask; + unsigned char *bmp_data = NULL; - if (hIcon) { + ::ZeroMemory(&bi, sizeof(bi)); + bi.bV5Size = sizeof(bi); + bi.bV5Width = width; + bi.bV5Height = height; + bi.bV5Planes = 1; + bi.bV5BitCount = 32; + bi.bV5Compression = BI_RGB; + bi.bV5CSType = LCS_WINDOWS_COLOR_SPACE; + bi.bV5Intent = LCS_GM_IMAGES; - if (m_icon) { - DestroyIcon(m_icon); - } - m_icon = hIcon; + hdc = ::GetDC(NULL); + bmp_color = ::CreateDIBSection(hdc, reinterpret_cast(&bi), + DIB_RGB_COLORS, (void **) &bmp_data, NULL, 0); + ::ReleaseDC(NULL, hdc); - ::SendMessage(m_handle, WM_SETICON, ICON_SMALL, (LPARAM) hIcon); - ::SendMessage(m_handle, WM_SETICON, ICON_BIG, (LPARAM) hIcon); + if (!bmp_color) { + Log::error("Win32Display::setIcon() - Failed to create RGBA bitmap"); + return; } + + bmp_mask = CreateBitmap(width, height, 1, 1, NULL); + if (!bmp_mask) { + Log::error("Win32Display::setIcon() - Failed to create mask bitmap"); + ::DeleteObject(bmp_color); + return; + } + + // pixels are always RGBA, WinApi wants BGRA + for(int i = 0; i < width * height; i++) { + bmp_data[i * 4 + 0] = pixels[i * 4 + 2]; // R <- B + bmp_data[i * 4 + 1] = pixels[i * 4 + 1]; // G <- G + bmp_data[i * 4 + 2] = pixels[i * 4 + 0]; // B <- R + bmp_data[i * 4 + 3] = pixels[i * 4 + 3]; // A <- A + } + + ::ZeroMemory(&ii, sizeof(ii)); + ii.fIcon = TRUE; + ii.xHotspot = 0; + ii.yHotspot = 0; + ii.hbmColor = bmp_color; + ii.hbmMask = bmp_mask; + + if (m_icon) { + ::DestroyIcon(m_icon); + } + + m_icon = CreateIconIndirect(&ii); + + if (m_icon) { + ::SendMessage(m_handle, WM_SETICON, ICON_SMALL, (LPARAM) m_icon); + ::SendMessage(m_handle, WM_SETICON, ICON_BIG, (LPARAM) m_icon); + } else { + Log::error("Win32Display::setIcon() - Failed to create icon"); + } + + ::DeleteObject(bmp_color); + ::DeleteObject(bmp_mask); } void Win32Display::registerClass() diff --git a/source/Platform/Win32/Win32Display.h b/source/Platform/Win32/Win32Display.h index 7a08cb4..d022da1 100644 --- a/source/Platform/Win32/Win32Display.h +++ b/source/Platform/Win32/Win32Display.h @@ -4,6 +4,7 @@ #include "Win32GLContext.h" #include +#include #include namespace sp { @@ -30,7 +31,7 @@ public : virtual void setCaption(const std::string& caption); - virtual void setIcon(const std::string& icon); + virtual void setIcon(unsigned int width, unsigned int height, const uint8_t *pixels); virtual void showCursor(bool value);