mirror of
https://github.com/glfw/glfw.git
synced 2026-09-20 16:30:45 +00:00
Add glfwSetWindowIcon
Adds support for setting window icons programmatically on platforms where this makes sense. Fixes #453. Closes #467.
This commit is contained in:
+145
-55
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
@@ -66,6 +67,112 @@ static DWORD getWindowExStyle(const _GLFWwindow* window)
|
||||
return style;
|
||||
}
|
||||
|
||||
// Returns the image whose area most closely matches the desired one
|
||||
//
|
||||
static const GLFWimage* chooseImage(int count, const GLFWimage* images,
|
||||
int width, int height)
|
||||
{
|
||||
int i, leastDiff = INT_MAX;
|
||||
const GLFWimage* closest = NULL;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
const int currDiff = abs(images[i].width * images[i].height -
|
||||
width * height);
|
||||
if (currDiff < leastDiff)
|
||||
{
|
||||
closest = images + i;
|
||||
leastDiff = currDiff;
|
||||
}
|
||||
}
|
||||
|
||||
return closest;
|
||||
}
|
||||
|
||||
// Creates an RGBA icon or cursor
|
||||
//
|
||||
static HICON createIcon(const GLFWimage* image,
|
||||
int xhot, int yhot, GLFWbool icon)
|
||||
{
|
||||
int i;
|
||||
HDC dc;
|
||||
HICON handle;
|
||||
HBITMAP color, mask;
|
||||
BITMAPV5HEADER bi;
|
||||
ICONINFO ii;
|
||||
unsigned char* target = NULL;
|
||||
unsigned char* source = image->pixels;
|
||||
|
||||
ZeroMemory(&bi, sizeof(bi));
|
||||
bi.bV5Size = sizeof(BITMAPV5HEADER);
|
||||
bi.bV5Width = image->width;
|
||||
bi.bV5Height = -image->height;
|
||||
bi.bV5Planes = 1;
|
||||
bi.bV5BitCount = 32;
|
||||
bi.bV5Compression = BI_BITFIELDS;
|
||||
bi.bV5RedMask = 0x00ff0000;
|
||||
bi.bV5GreenMask = 0x0000ff00;
|
||||
bi.bV5BlueMask = 0x000000ff;
|
||||
bi.bV5AlphaMask = 0xff000000;
|
||||
|
||||
dc = GetDC(NULL);
|
||||
color = CreateDIBSection(dc,
|
||||
(BITMAPINFO*) &bi,
|
||||
DIB_RGB_COLORS,
|
||||
(void**) &target,
|
||||
NULL,
|
||||
(DWORD) 0);
|
||||
ReleaseDC(NULL, dc);
|
||||
|
||||
if (!color)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create RGBA bitmap");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
|
||||
if (!mask)
|
||||
{
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||
"Win32: Failed to create mask bitmap");
|
||||
DeleteObject(color);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < image->width * image->height; i++)
|
||||
{
|
||||
target[0] = source[2];
|
||||
target[1] = source[1];
|
||||
target[2] = source[0];
|
||||
target[3] = source[3];
|
||||
target += 4;
|
||||
source += 4;
|
||||
}
|
||||
|
||||
ZeroMemory(&ii, sizeof(ii));
|
||||
ii.fIcon = icon;
|
||||
ii.xHotspot = xhot;
|
||||
ii.yHotspot = yhot;
|
||||
ii.hbmMask = mask;
|
||||
ii.hbmColor = color;
|
||||
|
||||
handle = CreateIconIndirect(&ii);
|
||||
|
||||
DeleteObject(color);
|
||||
DeleteObject(mask);
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
if (icon)
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create icon");
|
||||
else
|
||||
_glfwInputError(GLFW_PLATFORM_ERROR, "Win32: Failed to create cursor");
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
// Translate client window size to full window size according to styles
|
||||
//
|
||||
static void getFullWindowSize(DWORD style, DWORD exStyle,
|
||||
@@ -886,6 +993,12 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
|
||||
}
|
||||
|
||||
destroyWindow(window);
|
||||
|
||||
if (window->win32.bigIcon)
|
||||
DestroyIcon(window->win32.bigIcon);
|
||||
|
||||
if (window->win32.smallIcon)
|
||||
DestroyIcon(window->win32.smallIcon);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||
@@ -902,6 +1015,37 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
||||
free(wideTitle);
|
||||
}
|
||||
|
||||
void _glfwPlatformSetWindowIcon(_GLFWwindow* window,
|
||||
int count, const GLFWimage* images)
|
||||
{
|
||||
HICON bigIcon = NULL, smallIcon = NULL;
|
||||
|
||||
if (count)
|
||||
{
|
||||
const GLFWimage* bigImage = chooseImage(count, images,
|
||||
GetSystemMetrics(SM_CXICON),
|
||||
GetSystemMetrics(SM_CYICON));
|
||||
const GLFWimage* smallImage = chooseImage(count, images,
|
||||
GetSystemMetrics(SM_CXSMICON),
|
||||
GetSystemMetrics(SM_CYSMICON));
|
||||
|
||||
bigIcon = createIcon(bigImage, 0, 0, GLFW_TRUE);
|
||||
smallIcon = createIcon(smallImage, 0, 0, GLFW_TRUE);
|
||||
}
|
||||
|
||||
SendMessage(window->win32.handle, WM_SETICON, ICON_BIG, (LPARAM) bigIcon);
|
||||
SendMessage(window->win32.handle, WM_SETICON, ICON_SMALL, (LPARAM) smallIcon);
|
||||
|
||||
if (window->win32.bigIcon)
|
||||
DestroyIcon(window->win32.bigIcon);
|
||||
|
||||
if (window->win32.smallIcon)
|
||||
DestroyIcon(window->win32.smallIcon);
|
||||
|
||||
window->win32.bigIcon = bigIcon;
|
||||
window->win32.smallIcon = smallIcon;
|
||||
}
|
||||
|
||||
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
|
||||
{
|
||||
POINT pos = { 0, 0 };
|
||||
@@ -1236,61 +1380,7 @@ int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||
const GLFWimage* image,
|
||||
int xhot, int yhot)
|
||||
{
|
||||
HDC dc;
|
||||
HBITMAP bitmap, mask;
|
||||
BITMAPV5HEADER bi;
|
||||
ICONINFO ii;
|
||||
DWORD* target = 0;
|
||||
BYTE* source = (BYTE*) image->pixels;
|
||||
int i;
|
||||
|
||||
ZeroMemory(&bi, sizeof(bi));
|
||||
bi.bV5Size = sizeof(BITMAPV5HEADER);
|
||||
bi.bV5Width = image->width;
|
||||
bi.bV5Height = -image->height;
|
||||
bi.bV5Planes = 1;
|
||||
bi.bV5BitCount = 32;
|
||||
bi.bV5Compression = BI_BITFIELDS;
|
||||
bi.bV5RedMask = 0x00ff0000;
|
||||
bi.bV5GreenMask = 0x0000ff00;
|
||||
bi.bV5BlueMask = 0x000000ff;
|
||||
bi.bV5AlphaMask = 0xff000000;
|
||||
|
||||
dc = GetDC(NULL);
|
||||
bitmap = CreateDIBSection(dc, (BITMAPINFO*) &bi, DIB_RGB_COLORS,
|
||||
(void**) &target, NULL, (DWORD) 0);
|
||||
ReleaseDC(NULL, dc);
|
||||
|
||||
if (!bitmap)
|
||||
return GLFW_FALSE;
|
||||
|
||||
mask = CreateBitmap(image->width, image->height, 1, 1, NULL);
|
||||
if (!mask)
|
||||
{
|
||||
DeleteObject(bitmap);
|
||||
return GLFW_FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < image->width * image->height; i++, target++, source += 4)
|
||||
{
|
||||
*target = (source[3] << 24) |
|
||||
(source[0] << 16) |
|
||||
(source[1] << 8) |
|
||||
source[2];
|
||||
}
|
||||
|
||||
ZeroMemory(&ii, sizeof(ii));
|
||||
ii.fIcon = FALSE;
|
||||
ii.xHotspot = xhot;
|
||||
ii.yHotspot = yhot;
|
||||
ii.hbmMask = mask;
|
||||
ii.hbmColor = bitmap;
|
||||
|
||||
cursor->win32.handle = (HCURSOR) CreateIconIndirect(&ii);
|
||||
|
||||
DeleteObject(bitmap);
|
||||
DeleteObject(mask);
|
||||
|
||||
cursor->win32.handle = (HCURSOR) createIcon(image, xhot, yhot, GLFW_FALSE);
|
||||
if (!cursor->win32.handle)
|
||||
return GLFW_FALSE;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user