mirror of
https://github.com/glfw/glfw.git
synced 2024-11-25 22:14:34 +00:00
Better error handling for GenerateTextBadgeIcon()
This commit is contained in:
parent
aa0e9f8aa7
commit
13f1b96386
@ -1644,20 +1644,88 @@ void _glfwSetWindowTaskbarProgressWin32(_GLFWwindow* window, int progressState,
|
|||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to set taskbar progress state");
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to set taskbar progress state");
|
||||||
}
|
}
|
||||||
|
|
||||||
static HICON GenerateBadgeIcon(HWND hWnd, WCHAR* text)
|
typedef struct
|
||||||
|
{
|
||||||
|
HDC hdc;
|
||||||
|
HDC hdcMem;
|
||||||
|
HDC hdcMemMask;
|
||||||
|
|
||||||
|
HBITMAP hBitmap;
|
||||||
|
HBITMAP hBitmapMask;
|
||||||
|
HBITMAP hOldBitmap;
|
||||||
|
HBITMAP hOldBitmapMask;
|
||||||
|
|
||||||
|
HBRUSH hBackgroundBrush;
|
||||||
|
HBRUSH hOldBrush;
|
||||||
|
|
||||||
|
HFONT hFont;
|
||||||
|
HFONT hOldFont;
|
||||||
|
|
||||||
|
COLORREF hOldColor;
|
||||||
|
|
||||||
|
int oldBkMode;
|
||||||
|
|
||||||
|
UINT oldTextAlign;
|
||||||
|
} BadgeData;
|
||||||
|
|
||||||
|
static void CleanupBadgeData(HWND hWnd, BadgeData* data)
|
||||||
|
{
|
||||||
|
if(!data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(data->oldTextAlign != GDI_ERROR)
|
||||||
|
SetTextAlign(data->hdcMem, data->oldTextAlign);
|
||||||
|
|
||||||
|
if(data->oldBkMode)
|
||||||
|
SetBkMode(data->hdcMem, data->oldBkMode);
|
||||||
|
|
||||||
|
if(data->hOldColor != CLR_INVALID)
|
||||||
|
SetTextColor(data->hdcMem, data->hOldColor);
|
||||||
|
|
||||||
|
if(data->hFont)
|
||||||
|
DeleteObject(data->hFont);
|
||||||
|
if(data->hOldFont)
|
||||||
|
SelectObject(data->hdcMem, data->hOldFont);
|
||||||
|
|
||||||
|
if (data->hBackgroundBrush)
|
||||||
|
DeleteObject(data->hBackgroundBrush);
|
||||||
|
if(data->hOldBrush)
|
||||||
|
SelectObject(data->hdcMem, data->hOldBrush);
|
||||||
|
|
||||||
|
if(data->hOldBitmap)
|
||||||
|
SelectObject(data->hdcMem, data->hOldBitmap);
|
||||||
|
if(data->hOldBitmapMask)
|
||||||
|
SelectObject(data->hdcMem, data->hOldBitmapMask);
|
||||||
|
|
||||||
|
if(data->hBitmap)
|
||||||
|
DeleteObject(data->hBitmap);
|
||||||
|
if(data->hBitmapMask)
|
||||||
|
DeleteObject(data->hBitmapMask);
|
||||||
|
|
||||||
|
if(data->hdcMem)
|
||||||
|
DeleteDC(data->hdcMem);
|
||||||
|
if(data->hdcMemMask)
|
||||||
|
DeleteDC(data->hdcMemMask);
|
||||||
|
|
||||||
|
if(data->hdc)
|
||||||
|
ReleaseDC(hWnd, data->hdc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HICON GenerateTextBadgeIcon(HWND hWnd, WCHAR* text)
|
||||||
{
|
{
|
||||||
//Credits to GyrosGeier for helping with transparency
|
//Credits to GyrosGeier for helping with transparency
|
||||||
|
|
||||||
HDC hdc = NULL, hdcMem = NULL, hdcMemMask = NULL;
|
BadgeData badgeData;
|
||||||
HBITMAP hBitmap = NULL, hBitmapMask = NULL;
|
|
||||||
ICONINFO iconInfo;
|
|
||||||
HICON hIcon = NULL;
|
|
||||||
HFONT hFont = NULL;
|
|
||||||
void* bits = NULL;
|
void* bits = NULL;
|
||||||
DWORD* pixels = NULL;
|
DWORD* pixels = NULL;
|
||||||
|
ICONINFO iconInfo;
|
||||||
int width = 16, height = 16;
|
int width = 16, height = 16;
|
||||||
int fontSize = 16, weight = FW_REGULAR;
|
int fontSize = 16, weight = FW_REGULAR;
|
||||||
RECT contentRect = { 0, 0, width, height };
|
RECT contentRect = { 0, 0, width, height };
|
||||||
|
HICON hIcon = NULL;
|
||||||
|
|
||||||
|
memset(&badgeData, 0, sizeof(BadgeData));
|
||||||
|
|
||||||
if (!text)
|
if (!text)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1675,22 +1743,65 @@ static HICON GenerateBadgeIcon(HWND hWnd, WCHAR* text)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
hdc = GetDC(hWnd);
|
badgeData.hdc = GetDC(hWnd);
|
||||||
hdcMem = CreateCompatibleDC(hdc);
|
if(!badgeData.hdc)
|
||||||
hdcMemMask = CreateCompatibleDC(hdc);
|
{
|
||||||
|
CleanupBadgeData(hWnd, &badgeData);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
hBitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
|
badgeData.hdcMem = CreateCompatibleDC(badgeData.hdc);
|
||||||
|
if(!badgeData.hdcMem)
|
||||||
|
{
|
||||||
|
CleanupBadgeData(hWnd, &badgeData);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
badgeData.hdcMemMask = CreateCompatibleDC(badgeData.hdc);
|
||||||
|
if(!badgeData.hdcMemMask)
|
||||||
|
{
|
||||||
|
CleanupBadgeData(hWnd, &badgeData);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
badgeData.hBitmap = CreateDIBSection(badgeData.hdc, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
|
||||||
|
if(!badgeData.hBitmap)
|
||||||
|
{
|
||||||
|
CleanupBadgeData(hWnd, &badgeData);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
pixels = (DWORD*)bits;
|
pixels = (DWORD*)bits;
|
||||||
|
|
||||||
hBitmapMask = CreateCompatibleBitmap(hdc, width, height);
|
badgeData.hBitmapMask = CreateCompatibleBitmap(badgeData.hdc, width, height);
|
||||||
ReleaseDC(hWnd, hdc);
|
if(!badgeData.hBitmapMask)
|
||||||
SelectObject(hdcMem, hBitmap);
|
{
|
||||||
SelectObject(hdcMemMask, hBitmapMask);
|
CleanupBadgeData(hWnd, &badgeData);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
BitBlt(hdcMemMask, 0, 0, width, height, hdcMem, 0, 0, SRCCOPY);
|
badgeData.hOldBitmap = (HBITMAP)SelectObject(badgeData.hdcMem, badgeData.hBitmap);
|
||||||
|
badgeData.hOldBitmapMask = (HBITMAP)SelectObject(badgeData.hdcMemMask, badgeData.hBitmapMask);
|
||||||
|
|
||||||
SelectObject(hdcMem, CreateSolidBrush(RGB(0x26, 0x25, 0x2D)));
|
if(BitBlt(badgeData.hdcMemMask, 0, 0, width, height, badgeData.hdcMem, 0, 0, SRCCOPY) == FALSE)
|
||||||
Ellipse(hdcMem, 0, 0, width + 1, height + 1); //17x17 gives a more fancy ellipse
|
{
|
||||||
|
CleanupBadgeData(hWnd, &badgeData);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
badgeData.hBackgroundBrush = CreateSolidBrush(RGB(0x26, 0x25, 0x2D));
|
||||||
|
if(!badgeData.hBackgroundBrush)
|
||||||
|
{
|
||||||
|
CleanupBadgeData(hWnd, &badgeData);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
badgeData.hOldBrush = (HBRUSH)SelectObject(badgeData.hdcMem, badgeData.hBackgroundBrush);
|
||||||
|
|
||||||
|
if(Ellipse(badgeData.hdcMem, 0, 0, width + 1, height + 1) == FALSE) //17x17 gives a more fancy ellipse
|
||||||
|
{
|
||||||
|
CleanupBadgeData(hWnd, &badgeData);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
//Adjust font size depending on digits to display
|
//Adjust font size depending on digits to display
|
||||||
if (lstrlen(text) > 2)
|
if (lstrlen(text) > 2)
|
||||||
@ -1700,19 +1811,46 @@ static HICON GenerateBadgeIcon(HWND hWnd, WCHAR* text)
|
|||||||
}
|
}
|
||||||
else if (lstrlen(text) > 1)
|
else if (lstrlen(text) > 1)
|
||||||
fontSize = 14;
|
fontSize = 14;
|
||||||
|
|
||||||
//Create and set font
|
//Create and set font
|
||||||
hFont = CreateFont(fontSize, 0, 0, 0, weight, FALSE, FALSE, FALSE, 0,
|
badgeData.hFont = CreateFont(fontSize, 0, 0, 0, weight, FALSE, FALSE, FALSE, 0,
|
||||||
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
|
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
|
||||||
DEFAULT_PITCH | FF_DONTCARE, TEXT("Segeo UI"));
|
DEFAULT_PITCH | FF_DONTCARE, TEXT("Segeo UI"));
|
||||||
SelectObject(hdcMem, hFont);
|
if(!badgeData.hFont)
|
||||||
|
{
|
||||||
|
CleanupBadgeData(hWnd, &badgeData);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
badgeData.hOldFont = (HFONT)SelectObject(badgeData.hdcMem, badgeData.hFont);
|
||||||
|
|
||||||
//Draw text (center aligned)
|
//Draw text (center aligned)
|
||||||
SetTextColor(hdcMem, RGB(255, 255, 255)); //Use white text color
|
badgeData.hOldColor = SetTextColor(badgeData.hdcMem, RGB(255, 255, 255)); //Use white text color
|
||||||
SetBkMode(hdcMem, TRANSPARENT); //Make font background transparent
|
if(badgeData.hOldColor == CLR_INVALID)
|
||||||
SetTextAlign(hdcMem, TA_LEFT | TA_TOP | TA_NOUPDATECP);
|
{
|
||||||
|
CleanupBadgeData(hWnd, &badgeData);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
DrawText(hdcMem, text, lstrlen(text), &contentRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
|
badgeData.oldBkMode = SetBkMode(badgeData.hdcMem, TRANSPARENT); //Make font background transparent
|
||||||
|
if(!badgeData.oldBkMode)
|
||||||
|
{
|
||||||
|
CleanupBadgeData(hWnd, &badgeData);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
badgeData.oldTextAlign = SetTextAlign(badgeData.hdcMem, TA_LEFT | TA_TOP | TA_NOUPDATECP);
|
||||||
|
if(badgeData.oldTextAlign == GDI_ERROR)
|
||||||
|
{
|
||||||
|
CleanupBadgeData(hWnd, &badgeData);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!DrawText(badgeData.hdcMem, text, lstrlen(text), &contentRect, DT_CENTER | DT_VCENTER | DT_SINGLELINE))
|
||||||
|
{
|
||||||
|
CleanupBadgeData(hWnd, &badgeData);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
//Transparency
|
//Transparency
|
||||||
for (int y = 0; y < height; ++y)
|
for (int y = 0; y < height; ++y)
|
||||||
@ -1727,20 +1865,20 @@ static HICON GenerateBadgeIcon(HWND hWnd, WCHAR* text)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SelectObject(badgeData.hdcMem, badgeData.hOldBitmap);
|
||||||
|
badgeData.hOldBitmap = NULL;
|
||||||
|
SelectObject(badgeData.hdcMemMask, badgeData.hOldBitmapMask);
|
||||||
|
badgeData.hOldBitmapMask = NULL;
|
||||||
|
|
||||||
//Generate icon from bitmap
|
//Generate icon from bitmap
|
||||||
iconInfo.fIcon = TRUE;
|
iconInfo.fIcon = TRUE;
|
||||||
iconInfo.xHotspot = 0;
|
iconInfo.xHotspot = 0;
|
||||||
iconInfo.yHotspot = 0;
|
iconInfo.yHotspot = 0;
|
||||||
iconInfo.hbmMask = hBitmapMask;
|
iconInfo.hbmMask = badgeData.hBitmapMask;
|
||||||
iconInfo.hbmColor = hBitmap;
|
iconInfo.hbmColor = badgeData.hBitmap;
|
||||||
hIcon = CreateIconIndirect(&iconInfo);
|
hIcon = CreateIconIndirect(&iconInfo);
|
||||||
|
|
||||||
//Cleanup
|
CleanupBadgeData(hWnd, &badgeData);
|
||||||
DeleteDC(hdcMemMask);
|
|
||||||
DeleteDC(hdcMem);
|
|
||||||
DeleteObject(hBitmap);
|
|
||||||
DeleteObject(hBitmapMask);
|
|
||||||
DeleteObject(hFont);
|
|
||||||
|
|
||||||
return hIcon;
|
return hIcon;
|
||||||
}
|
}
|
||||||
@ -1751,7 +1889,7 @@ void _glfwSetWindowTaskbarBadgeWin32(_GLFWwindow* window, int count)
|
|||||||
HICON icon = NULL;
|
HICON icon = NULL;
|
||||||
char countStr[4];
|
char countStr[4];
|
||||||
WCHAR* countWStr = NULL;
|
WCHAR* countWStr = NULL;
|
||||||
|
|
||||||
if (window == NULL)
|
if (window == NULL)
|
||||||
{
|
{
|
||||||
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Win32: Taskbar badge requires a valid window handle");
|
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, "Win32: Taskbar badge requires a valid window handle");
|
||||||
@ -1769,7 +1907,7 @@ void _glfwSetWindowTaskbarBadgeWin32(_GLFWwindow* window, int count)
|
|||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to set taskbar badge count");
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to set taskbar badge count");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
count = min(count, 999);
|
count = min(count, 999);
|
||||||
|
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
@ -1784,7 +1922,7 @@ void _glfwSetWindowTaskbarBadgeWin32(_GLFWwindow* window, int count)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
icon = GenerateBadgeIcon(window->win32.handle, countWStr);
|
icon = GenerateTextBadgeIcon(window->win32.handle, countWStr);
|
||||||
if (!icon)
|
if (!icon)
|
||||||
{
|
{
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to set taskbar badge count");
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR, "Win32: Failed to set taskbar badge count");
|
||||||
|
Loading…
Reference in New Issue
Block a user