【问题标题】:How to convert HICON to HBITMAP in VC++?如何在 VC++ 中将 HICON 转换为 HBITMAP?
【发布时间】:2011-11-14 13:22:03
【问题描述】:

如何在VC++中将HICON转换为HBITMAP?

我知道这是一个常见问题解答,但我在 Google 上找到的所有解决方案都不起作用。我需要的是一个接受参数 HICON 并返回 HBITMAP 的函数。

即使图标是 24 位、16 位或 8 位,也尽可能将其转换为 32 位位图。

这是代码,不知道哪里出错了:

HBITMAP icon_to_bitmap(HICON Icon_Handle) {
  HDC Screen_Handle = GetDC(NULL);
  HDC Device_Handle = CreateCompatibleDC(Screen_Handle);

  HBITMAP Bitmap_Handle = 
  CreateCompatibleBitmap(Device_Handle,GetSystemMetrics(SM_CXICON),
  GetSystemMetrics(SM_CYICON));

  HBITMAP Old_Bitmap = (HBITMAP)SelectObject(Device_Handle,Bitmap_Handle);
  DrawIcon(Device_Handle, 0,0, Icon_Handle);
  SelectObject(Device_Handle,Old_Bitmap);

  DeleteDC(Device_Handle);
  ReleaseDC(NULL,Screen_Handle);
  return Bitmap_Handle;
}

【问题讨论】:

    标签: c++ winapi visual-c++ bitmap icons


    【解决方案1】:
    HDC hDC = GetDC(NULL);
    HDC hMemDC = CreateCompatibleDC(hDC);
    HBITMAP hMemBmp = CreateCompatibleBitmap(hDC, x, y);
    HBITMAP hResultBmp = NULL;
    HGDIOBJ hOrgBMP = SelectObject(hMemDC, hMemBmp);
    
    DrawIconEx(hMemDC, 0, 0, hIcon, x, y, 0, NULL, DI_NORMAL);
    
    hResultBmp = hMemBmp;
    hMemBmp = NULL;
    
    SelectObject(hMemDC, hOrgBMP);
    DeleteDC(hMemDC);
    ReleaseDC(NULL, hDC);
    DestroyIcon(hIcon);
    return hResultBmp;
    

    【讨论】:

      【解决方案2】:

      这段代码做到了:

      HICON hIcon = (HICON)LoadImage(instance, MAKEINTRESOURCEW(IDI_ICON), IMAGE_ICON, width, height, 0);
      ICONINFO iconinfo;
      GetIconInfo(hIcon, &iconinfo);
      HBITMAP hBitmap = iconinfo.hbmColor;
      

      这是 *.rc 文件中的代码:

      IDI_ICON ICON "example.ico"
      

      这是 *.h 文件中的代码:

      #define IDI_ICON 4000
      

      【讨论】:

      • 您能详细说明一下这个解决方案吗? hbmColor 是否足以代表 HBITMAP 中的图标? hbmMask 呢?
      【解决方案3】:

      我没有现成的代码可供分享,但我认为这很容易。您必须创建 HBITMAP,创建设备上下文,将位图选择到 DC(这将使位图成为此 DC 的绘图区域)。最后调用 DrawIcon() 函数在这个 DC 上绘制你的图标。之后从 DC 中分离位图并销毁 DC。您的位图现在应该可以使用了。

      查看您的代码后更新:

      我相信问题出在 createCompatibleBitmap 调用中。您要求的是与内存 DC 兼容的位图,但内存 DC 以选择其中的 1 位/像素位图开始。尝试请求与屏幕 DC 兼容的位图。

      更新 2:您可能需要查看 this question,因为它似乎与您的问题有关。

      【讨论】:

      • 我在做同样的事情,但生成的位图始终是 1 位/像素。好奇怪.......
      • 请用示例代码扩展您的问题。听起来您的位图不是使用正确的位/像素创建的,但如果不查看代码就无法确定。
      • 添加了代码,DC是从屏幕创建的,所以应该是32位/像素,请看看....
      • 我已经更新了我的答案,试试看,如果有帮助,请告诉我!
      • 查看我添加到问题中的链接,它可能会有所帮助。
      【解决方案4】:

      我发现了这个(类似的代码适用于我 - 带有或不带有 alpha 数据的 32x32 图标):
      用过CopyImage (msdn link)

      HICON hICON = /*your code here*/
      HBITMAP hBITMAPcopy;
      ICONINFOEX IconInfo;
      BITMAP BM_32_bit_color;
      BITMAP BM_1_bit_mask;
      
      // 1. From HICON to HBITMAP for color and mask separately
      //.cbSize required
      //memset((void*)&IconInfo, 0, sizeof(ICONINFOEX));
      IconInfo.cbSize = sizeof(ICONINFOEX);
      GetIconInfoEx( hICON , &IconInfo);
      
      
      //HBITMAP IconInfo.hbmColor is 32bit per pxl, however alpha bytes can be zeroed or can be not.
      //HBITMAP IconInfo.hbmMask is 1bit per pxl
      
      // 2. From HBITMAP to BITMAP for color
      //    (HBITMAP without raw data -> HBITMAP with raw data)
      //         LR_CREATEDIBSECTION - DIB section will be created,
      //         so .bmBits pointer will not be null
      hBITMAPcopy = (HBITMAP)CopyImage(IconInfo.hbmColor, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
      //    (HBITMAP to BITMAP)
      GetObject(hBITMAPcopy, sizeof(BITMAP), &BM_32_bit_color);
      //Now: BM_32_bit_color.bmBits pointing to BGRA data.(.bmWidth * .bmHeight * (.bmBitsPixel/8))
      
      // 3. From HBITMAP to BITMAP for mask
      hBITMAPcopy = (HBITMAP)CopyImage(IconInfo.hbmMask, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
      GetObject(hBITMAPcopy, sizeof(BITMAP), &BM_1_bit_mask);
      //Now: BM_1_bit_mask.bmBits pointing to mask data (.bmWidth * .bmHeight Bits!)
      

      BM_32_bit_color 位图可能已经设置了 Alpha *通道*(每个第 4 字节)!所以 - 在你将掩码位添加到颜色数据之前检查它。

      【讨论】:

        猜你喜欢
        • 2013-07-10
        • 1970-01-01
        • 2021-08-02
        • 2013-02-23
        • 1970-01-01
        • 2011-10-23
        • 2013-04-02
        • 1970-01-01
        • 2019-01-29
        相关资源
        最近更新 更多