c++ - 以编程方式创建 32 位颜色图标

标签 c++ winapi

我想使用 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 创建彩色图标。但是,我有一些关于该代码(以及一般创建图标)的问题和疑问,我想讨论一下。

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

非常感谢任何帮助。

最佳答案

When do I actually have to destroy the icon?

了解 DestroyIcon

It is only necessary to call DestroyIcon for icons and cursors created with the following functions: CreateIconFromResourceEx (if called without the LR_SHARED flag), CreateIconIndirect, and CopyIcon. Do not use this function to destroy a shared icon. A shared icon is valid as long as the module from which it was loaded remains in memory. The following functions obtain a shared icon.

  • LoadIcon
  • LoadImage (if you use the LR_SHARED flag)
  • CopyImage (if you use the LR_COPYRETURNORG flag and the hImage parameter is a shared icon)
  • CreateIconFromResource
  • CreateIconFromResourceEx (if you use the LR_SHARED flag)

所以当你使用完未共享图标时,你需要调用DestroyIcon

ComboBoxEx 不会破坏您使用 CBEM_SETIMAGELIST 分配给它的图像列表 - 因此此图像列表必须有效直到 ComboBoxEx 有效并且您必须稍后自行销毁。

ImageList_AddIcon

Because the system does not save hicon, you can destroy it after the macro returns

换句话说 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)) 这个图标时,我接下来会看到:

enter image description here

关于c++ - 以编程方式创建 32 位颜色图标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41533158/

相关文章:

c++ - 模板参数中的函数调用

c++ - Boost 异步定时器仍然阻塞主线程

c++ - Windows OS的I/O优先级

c++ - 您可以在不重新打开重新打开 win32 窗口的情况下执行需要提升的任务吗?

c++ - 具有特定宽度和高度的 DrawState

c++ - C#'s "其中 T : type"in C++

c++ - 翻转从 Kinect 收到的深度帧

C++如何将整数存储到二进制文件中?

windows - NTSD 和 WinDbg 之间到底有什么区别?

c - 为什么Windows中的BOOL是int类型?