以编程方式创建 32 位彩色图标

Sam*_*ime 3 c++ winapi

我想使用 C++ 和 Win API 以编程方式创建 32 位彩色图标。为此,我使用了在此处找到的以下代码。

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;
}
Run Code Online (Sandbox Code Playgroud)

原则上代码有效,我可以使用它在运行时使用 Win API 创建彩色图标。但是,我有一些关于该代码(以及一般创建图标)的问题和疑问,我想讨论一下。

  • 使用此功能创建的图标似乎不是 32 位色深。如果我使用像 RGB(218, 112, 214) 这样的颜色,我希望它是一些浅紫色。但是,实际显示的颜色是灰色。如何更改代码以使颜色真正为 32 位 RGB?
  • 创建的图标完全充满了颜色,我想在它周围有一个薄薄的黑色边框......如何实现?
  • 在 MSDN文档中(有点向下)提到“在关闭之前,您的应用程序必须使用 DestroyIcon 来销毁它使用 CreateIconIndirect 创建的任何图标。没有必要销毁由其他功能创建的图标。”但是,在文档中对于例如MSDN 中的CreateIcon,它说“当您使用完图标时,使用 DestroyIcon 函数销毁它”。这几乎是一个矛盾。我什么时候必须销毁图标?
  • 当我将图标添加到图像列表并将此列表添加到组合框时,这些规则是否也适用?即我必须清理图像列表和每个关联的图标吗?

任何帮助都受到高度赞赏。

RbM*_*bMm 5

我什么时候必须销毁图标?

了解DestroyIcon

只需要调用DestroyIcon使用以下函数创建的图标和光标:(CreateIconFromResourceEx如果不带LR_SHARED标志调用)CreateIconIndirect、 和 CopyIcon。请勿使用此功能销毁共享图标。只要加载它的模块保留在内存中,共享图标就是有效的。以下函数获取共享图标。

  • LoadIcon
  • LoadImage(如果你使用LR_SHARED标志)
  • CopyImage(如果您使用LR_COPYRETURNORG标志并且hImage 参数是共享图标)
  • CreateIconFromResource
  • CreateIconFromResourceEx(如果你使用LR_SHARED标志)

因此,你需要拨打DestroyIcon不共享图标,当你使用完

ComboBoxEx不销毁您分配给它的CBEM_SETIMAGELIST图像列表 - 因此此图像列表必须在有效之前ComboBoxEx有效,并且您必须稍后自己销毁它。

ImageList_AddIcon

因为系统没有保存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;
}
Run Code Online (Sandbox Code Playgroud)

当我DrawIconEx(, DI_IMAGE|DI_MASK)在绿色网格上绘制 ( ) 这个图标时,我接下来查看:

在此处输入图片说明