【问题标题】:How to load a Windows icon using a pixel buffer?如何使用像素缓冲区加载 Windows 图标?
【发布时间】:2011-01-22 07:06:53
【问题描述】:

我正在尝试使用像素缓冲区创建与 Windows 兼容的图标。 Surface 类加载图像并在内部将其保存为无符号整数数组 (0xRRGGBB)。

我正在尝试像这样创建一个图标:

Surface m_Test("Data/Interface/CursorTest.png");
HICON result = CreateIconFromResourceEx( (PBYTE)m_Test.GetBuffer(), 
                                         m_Test.GetWidth() * m_Test.GetHeight(), 
                                         FALSE, 
                                         0, 
                                         24, 
                                         24, 
                                         LR_DEFAULTCOLOR
);

但是,result 始终是 NULL。我在任何地方都找不到CreateIconFromResourceEx 期望的数据格式。

最终我想从外部文件加载图标,而不使用资源文件。

提前致谢。

编辑:我想通了!最终编码:

// m_Cursors is an array of images coming from an image strip
Pixel* buffer   = m_Cursors[i]->GetBuffer();
int width       = m_Cursors[i]->GetWidth();
int height      = m_Cursors[i]->GetHeight();

HDC dc_andmask = CreateCompatibleDC(dc);
HBITMAP cur_andmask = CreateCompatibleBitmap(dc, width, height);
HBITMAP hOldAndMaskBitmap = (HBITMAP)SelectObject(dc_andmask, cur_andmask);

HDC dc_xormask = CreateCompatibleDC(dc);
HBITMAP cur_xormask = CreateCompatibleBitmap(dc, width, height);
HBITMAP hOldXorMaskBitmap = (HBITMAP)SelectObject(dc_xormask, cur_xormask);

for (int y = 0; y < height; ++y)
{
    for (int x = 0; x < width; ++x)
    {
        Pixel currpix = buffer[x + y * width];

        // the images use the alpha channel for transparancy
        if ((currpix & 0xFF000000) == 0
        {
            // transparant
            SetPixel(dc_andmask, x, y, RGB(255, 255, 255));
            SetPixel(dc_xormask, x, y, RGB(0, 0, 0));
        }
        else
        {
            COLORREF curr = RGB(currpix & 0xFF0000 >> 16, currpix & 0x00FF00 >> 8, currpix & 0x0000FF);

            // opaque
            SetPixel(dc_andmask, x, y, RGB(0, 0, 0));
            SetPixel(dc_xormask, x, y, curr);
        }
    }
}

// i don't know why this has to be done, but it fixes things
// so who cares (b ")b
SelectObject(dc_andmask, hOldAndMaskBitmap);
SelectObject(dc_xormask, hOldXorMaskBitmap);

DeleteObject(dc_xormask);
DeleteObject(dc_andmask);

ICONINFO temp = { FALSE, m_OffsetX[i], m_OffsetY[i], cur_andmask, cur_xormask };
m_CursorIDs[i] = CreateIconIndirect(&temp);

【问题讨论】:

  • 尽可能避免使用 SetPixel。这太慢了。尝试使用您的原始字节作为源创建一个 DIB 部分(如果您正确设置了 BITMAPHEADER,Windows 将直接采用您的像素格式)。
  • 没关系,这都是在初始化时完成的。

标签: c++ windows winapi icons


【解决方案1】:

如果您想通过 AND 和 XOR 掩码传递原始字节数据,请使用 CreateIcon

如果您希望能够使用HBITMAPs,则可以使用CreateIconIndirect。使用此 API,您甚至可以根据需要create icons with an alpha channel

【讨论】:

  • 在您的特定情况下,您需要创建一个指向 Surface 类的内部数组的 24 位 DIB 部分并将其传递给 CreateIconIndirect。 (之后销毁HBITMAP)
  • @Koro 你能提供从字节数据创建图标的详细示例代码吗?
【解决方案2】:

看看这门课取自koders.com

它提供了方法

LPICONRESOURCE ReadIconFromICOFile( LPCTSTR szFileName )

LPICONRESOURCE ReadIconFromEXEFile( LPCTSTR szFileName )

【讨论】:

    猜你喜欢
    • 2022-01-26
    • 1970-01-01
    • 2014-02-23
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多