From b0ee7bbb7ee5b56ff1293c148aab535fedaa01b1 Mon Sep 17 00:00:00 2001 From: Littleboy Date: Wed, 29 Jun 2011 06:18:50 -0400 Subject: BACKENDS: Implement Win32TaskbarManager::setCount() --- backends/taskbar/win32/win32-taskbar.cpp | 122 ++++++++++++++++++++++++++++++- backends/taskbar/win32/win32-taskbar.h | 5 ++ 2 files changed, 126 insertions(+), 1 deletion(-) (limited to 'backends') diff --git a/backends/taskbar/win32/win32-taskbar.cpp b/backends/taskbar/win32/win32-taskbar.cpp index 18d99d6eca..04889f3dd7 100644 --- a/backends/taskbar/win32/win32-taskbar.cpp +++ b/backends/taskbar/win32/win32-taskbar.cpp @@ -66,7 +66,7 @@ // System.Title property key, values taken from http://msdn.microsoft.com/en-us/library/bb787584.aspx const PROPERTYKEY PKEY_Title = { /* fmtid = */ { 0xF29F85E0, 0x4FF9, 0x1068, { 0xAB, 0x91, 0x08, 0x00, 0x2B, 0x27, 0xB3, 0xD9 } }, /* propID = */ 2 }; -Win32TaskbarManager::Win32TaskbarManager() : _taskbar(NULL) { +Win32TaskbarManager::Win32TaskbarManager() : _taskbar(NULL), _count(0), _icon(NULL) { // Do nothing if not running on Windows 7 or later if (!isWin7OrLater()) return; @@ -96,6 +96,9 @@ Win32TaskbarManager::~Win32TaskbarManager() { _taskbar->Release(); _taskbar = NULL; + if (_icon) + DestroyIcon(_icon); + CoUninitialize(); } @@ -144,6 +147,123 @@ void Win32TaskbarManager::setProgressState(TaskbarProgressState state) { _taskbar->SetProgressState(getHwnd(), (TBPFLAG)state); } +void Win32TaskbarManager::setCount(int count) { + if (_taskbar == NULL) + return; + + if (count == 0) { + _taskbar->SetOverlayIcon(getHwnd(), NULL, L""); + return; + } + + // FIXME: This isn't really nice and could use a cleanup. + // The only good thing is that it doesn't use GDI+ + // and thus does not have a dependancy on it, + // with the downside of being a lot more ugly. + // Maybe replace it by a Graphic::Surface, use + // ScummVM font drawing and extract the contents at + // the end? + + if (_count != count || _icon == NULL) { + // Cleanup previous icon + _count = count; + if (_icon) + DestroyIcon(_icon); + + Common::String countString = (count < 100 ? Common::String::format("%d", count) : "9+"); + + // Create transparent background + BITMAPV5HEADER bi; + ZeroMemory(&bi, sizeof(BITMAPV5HEADER)); + bi.bV5Size = sizeof(BITMAPV5HEADER); + bi.bV5Width = 16; + bi.bV5Height = 16; + bi.bV5Planes = 1; + bi.bV5BitCount = 32; + bi.bV5Compression = BI_RGB; + // Set 32 BPP alpha format + bi.bV5RedMask = 0x00FF0000; + bi.bV5GreenMask = 0x0000FF00; + bi.bV5BlueMask = 0x000000FF; + bi.bV5AlphaMask = 0xFF000000; + + // Get DC + HDC hdc; + hdc = GetDC(NULL); + HDC hMemDC = CreateCompatibleDC(hdc); + ReleaseDC(NULL, hdc); + + // Create a bitmap mask + HBITMAP hBitmapMask = CreateBitmap(16, 16, 1, 1, NULL); + + // Create the DIB section with an alpha channel + void *lpBits; + HBITMAP hBitmap = CreateDIBSection(hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS, (void **)&lpBits, NULL, 0); + HBITMAP hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); + + // Load the icon background + HICON hIconBackground = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(1002 /* IDI_COUNT */)); + DrawIconEx(hMemDC, 0, 0, hIconBackground, 16, 16, 0, 0, DI_NORMAL); + DeleteObject(hIconBackground); + + // Draw the count + LOGFONT lFont; + memset(&lFont, 0, sizeof(LOGFONT)); + lFont.lfHeight = 10; + lFont.lfWeight = FW_BOLD; + lFont.lfItalic = 1; + strcpy(lFont.lfFaceName, "Arial"); + + HFONT hFont = CreateFontIndirect(&lFont); + SelectObject(hMemDC, hFont); + + RECT rect; + SetRect(&rect, 4, 4, 12, 12); + SetTextColor(hMemDC, RGB(48, 48, 48)); + SetBkMode(hMemDC, TRANSPARENT); + DrawText(hMemDC, countString.c_str(), -1, &rect, DT_NOCLIP|DT_CENTER); + + // Set the text alpha to fully opaque (we consider the data inside the text rect) + DWORD *lpdwPixel = (DWORD *)lpBits; + for (int x = 3; x < 12; x++) { + for(int y = 3; y < 12; y++) { + unsigned char *p = (unsigned char *)(lpdwPixel + x * 16 + y); + + if (p[0] != 0 && p[1] != 0 && p[2] != 0) + p[3] = 255; + } + } + + // Cleanup DC + DeleteObject(hFont); + SelectObject(hMemDC, hOldBitmap); + DeleteDC(hMemDC); + + // Prepare our new icon + ICONINFO ii; + ii.fIcon = FALSE; + ii.xHotspot = 0; + ii.yHotspot = 0; + ii.hbmMask = hBitmapMask; + ii.hbmColor = hBitmap; + + _icon = CreateIconIndirect(&ii); + + DeleteObject(hBitmap); + DeleteObject(hBitmapMask); + + if (!_icon) { + warning("[Win32TaskbarManager::setCount] Cannot create icon for count"); + return; + } + } + + // Sets the overlay icon + LPWSTR desc = ansiToUnicode(Common::String::format("Found games: %d", count).c_str()); + _taskbar->SetOverlayIcon(getHwnd(), _icon, desc); + delete[] desc; +} + void Win32TaskbarManager::addRecent(const Common::String &name, const Common::String &description) { //warning("[Win32TaskbarManager::addRecent] Adding recent list entry: %s (%s)", name.c_str(), description.c_str()); diff --git a/backends/taskbar/win32/win32-taskbar.h b/backends/taskbar/win32/win32-taskbar.h index 3415a79bd7..c9d1761017 100644 --- a/backends/taskbar/win32/win32-taskbar.h +++ b/backends/taskbar/win32/win32-taskbar.h @@ -41,11 +41,16 @@ public: virtual void setOverlayIcon(const Common::String &name, const Common::String &description); virtual void setProgressValue(int completed, int total); virtual void setProgressState(TaskbarProgressState state); + virtual void setCount(int count); virtual void addRecent(const Common::String &name, const Common::String &description); private: ITaskbarList3 *_taskbar; + // Count handling + HICON _icon; + int _count; + /** * Get the path to an icon for the game * -- cgit v1.2.3