我想使用C ++和Win API以编程方式创建32位颜色图标。为此,我使用以下代码here。
HICON CreateSolidColorIcon(COLORREF iconColor, int width, int height)
{
// Obtain a handle to the screen device context.
HDC hdcScreen = GetDC(NULL);
// Create a memory device context, which we will draw into.
HDC hdcMem = CreateCompatibleDC(hdcScreen);
// Create the bitmap, and select it into the device context for drawing.
HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen, width, height);
HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcMem, hbmp);
// Draw your icon.
//
// For this simple example, we're just drawing a solid color rectangle
// in the specified color with the specified dimensions.
HPEN hpen = CreatePen(PS_SOLID, 1, iconColor);
HPEN hpenOld = (HPEN)SelectObject(hdcMem, hpen);
HBRUSH hbrush = CreateSolidBrush(iconColor);
HBRUSH hbrushOld = (HBRUSH)SelectObject(hdcMem, hbrush);
Rectangle(hdcMem, 0, 0, width, height);
SelectObject(hdcMem, hbrushOld);
SelectObject(hdcMem, hpenOld);
DeleteObject(hbrush);
DeleteObject(hpen);
// Create an icon from the bitmap.
//
// Icons require masks to indicate transparent and opaque areas. Since this
// simple example has no transparent areas, we use a fully opaque mask.
HBITMAP hbmpMask = CreateCompatibleBitmap(hdcScreen, width, height);
ICONINFO ii;
ii.fIcon = TRUE;
ii.hbmMask = hbmpMask;
ii.hbmColor = hbmp;
HICON hIcon = CreateIconIndirect(&ii);
DeleteObject(hbmpMask);
// Clean-up.
SelectObject(hdcMem, hbmpOld);
DeleteObject(hbmp);
DeleteDC(hdcMem);
ReleaseDC(NULL, hdcScreen);
// Return the icon.
return hIcon;
}
原则上代码可以工作,我可以使用它在运行时使用Win API创建彩色图标。但是,我有一些关于该代码的问题和疑问(以及一般的创建图标),我想讨论。
非常感谢任何帮助。
答案 0 :(得分:3)
我什么时候才能销毁图标?
只需要为图标和光标调用
DestroyIcon
即可 使用以下函数创建:CreateIconFromResourceEx
(如果 没有LR_SHARED
标志,CreateIconIndirect
和CopyIcon
。请勿使用此功能销毁共享图标。 :一种 只要加载它的模块,共享图标就有效 留在记忆中。以下函数获取共享图标。
LoadIcon
LoadImage
(如果您使用LR_SHARED
标志)CopyImage
(如果您使用LR_COPYRETURNORG
标记且hImage
参数是共享图标)CreateIconFromResource
CreateIconFromResourceEx
(如果您使用LR_SHARED
标志)
所以当您使用完后,需要致电DestroyIcon
不共享图标
ComboBoxEx
不会销毁您使用CBEM_SETIMAGELIST
分配给它的图片列表 - 因此此图片列表必须有效才能ComboBoxEx
生效,您必须稍后自行销毁。
因为系统没有保存hicon,你可以在之后销毁它 宏返回
换句话说ImageList_AddIcon
对您的图标进行复制,并且您可以在宏返回后销毁原始图标
用于创建32位颜色图标尝试代码如下:
HICON CreateGradientColorIcon(COLORREF iconColor, int width, int height)
{
HICON hIcon = 0;
ICONINFO ii = { TRUE };
ULONG n = width * height;
if (PULONG lpBits = new ULONG[n])
{
PULONG p = lpBits;
ULONG x, y = height, t;
do
{
x = width, t = --y << 8;
do
{
*p++ = iconColor | ((t * --x) / n << 24);
} while (x);
} while (y);
if (ii.hbmColor = CreateBitmap(width, height, 1, 32, lpBits))
{
if (ii.hbmMask = CreateBitmap(width, height, 1, 1, 0))
{
hIcon = CreateIconIndirect(&ii);
DeleteObject(ii.hbmMask);
}
DeleteObject(ii.hbmColor);
}
delete [] lpBits;
}
return hIcon;
}
当我绘制( DrawIconEx(, DI_IMAGE|DI_MASK)
)绿色网格上的这个图标时我会查看下一个:
答案 1 :(得分:0)
对于所有偶然发现此解决方案的人,我只是在发布一些有关RbMm答案的书面解决方案。这基本上与他的解决方案相同(也许我不能确定其表现):
static HICON CreateIconFromBytes(HDC DC, int width, int height, uint32* bytes) {
HICON hIcon = NULL;
ICONINFO iconInfo = {
TRUE, // fIcon, set to true if this is an icon, set to false if this is a cursor
NULL, // xHotspot, set to null for icons
NULL, // yHotspot, set to null for icons
NULL, // Monochrome bitmap mask, set to null initially
NULL // Color bitmap mask, set to null initially
};
uint32* rawBitmap = new uint32[width * height];
ULONG uWidth = (ULONG)width;
ULONG uHeight = (ULONG)height;
uint32* bitmapPtr = rawBitmap;
for (ULONG y = 0; y < uHeight; y++) {
for (ULONG x = 0; x < uWidth; x++) {
// Bytes are expected to be in RGB order (8 bits each)
// Swap G and B bytes, so that it is in BGR order for windows
uint32 byte = bytes[x + y * width];
uint8 A = (byte & 0xff000000) >> 24;
uint8 R = (byte & 0xff0000) >> 16;
uint8 G = (byte & 0xff00) >> 8;
uint8 B = (byte & 0xff);
*bitmapPtr = (A << 24) | (R << 16) | (G << 8) | B;
bitmapPtr++;
}
}
iconInfo.hbmColor = CreateBitmap(width, height, 1, 32, rawBitmap);
if (iconInfo.hbmColor) {
iconInfo.hbmMask = CreateCompatibleBitmap(DC, width, height);
if (iconInfo.hbmMask) {
hIcon = CreateIconIndirect(&iconInfo);
if (hIcon == NULL) {
Log::Warning("Failed to create icon.");
}
DeleteObject(iconInfo.hbmMask);
} else {
Log::Warning("Failed to create color mask.");
}
DeleteObject(iconInfo.hbmColor);
} else {
Log::Warning("Failed to create bitmap mask.");
}
delete[] rawBitmap;
return hIcon;
}
此解决方案将与STB图像库一起使用,以加载图像。因此,您可以从字面上仅加载带有stb的图像,然后将字节数据传递给此函数,结果将得到一个图标。我在设置图标时也遇到了一些麻烦,最终做到了这一点:
HICON icon = CreateIconFromBytes(DC, image.m_Width, image.m_Height, image.m_Pixels);
SendMessage(WND, WM_SETICON, ICON_SMALL, (LPARAM)icon);
SendMessage(WND, WM_SETICON, ICON_BIG, (LPARAM)icon);
SendMessage(WND, WM_SETICON, ICON_SMALL2, (LPARAM)icon);
您唯一需要注意的是,您应该为SendMessage()函数使用3个不同大小的图标,但除此之外,这对我来说很有效:)
编辑:
这也是官方MSDN文档的链接。
https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createiconindirect
https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createbitmap
https://docs.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-createcompatiblebitmap
https://docs.microsoft.com/en-us/windows/win32/menurc/using-icons