CMFCToolBar添加HBitmap出现黑色背景问题求助
问题:CMFCToolBar直接添加HBitmap显示黑底,经CImageList中转却正常的原因
我尝试将Bitmap添加到CMFCToolBar中,按钮已成功插入,但显示黑色背景。更换不同Bitmap后问题依旧,但将同一Bitmap添加到CButton、CTreeCtrl等其他控件时,可正常显示无黑底。我认为问题出在CMFCToolBar上,但无法定位原因。若通过CImageList将Bitmap添加到CMFCToolBar则可正常显示,我无法理解其中缘由,以下为相关代码:
使用NanoSVG将SVG转换为HBitmap的函数
HBITMAP SvgToHbitmap(const char* filename) { NSVGimage* image = nsvgParseFromFile(filename, "px", 96); int OriginalWidth = (int)image->width; int OriginalHeight = (int)image->height; int TargetWidth = 16; int TargetHeight = 16; BITMAPINFO bmpinfo = { 0 }; bmpinfo.bmiHeader.biSize = sizeof(bmpinfo.bmiHeader); bmpinfo.bmiHeader.biWidth = static_cast<LONG>(TargetWidth); bmpinfo.bmiHeader.biHeight = -static_cast<LONG>(TargetHeight); bmpinfo.bmiHeader.biPlanes = 1; bmpinfo.bmiHeader.biBitCount = 32; bmpinfo.bmiHeader.biCompression = BI_RGB; void* bits = nullptr; HBITMAP hbitmap = CreateDIBSection(NULL, &bmpinfo, DIB_RGB_COLORS, &bits, nullptr, 0); NSVGrasterizer* rast = nsvgCreateRasterizer(); float a = (2 * (TargetWidth + TargetHeight)); float b = (2 * (OriginalWidth + OriginalHeight)); float ReScaleFactor = a / b; nsvgRasterize(rast, image, 0, 0, ReScaleFactor, (unsigned char*)bits, TargetWidth, TargetHeight, static_cast<int>(TargetWidth * 4)); nsvgDeleteRasterizer(rast); nsvgDelete(image); return hbitmap; }
向对话框添加按钮及带HBitmap的MFCToolBar(黑底问题代码)
BOOL CSvgDlg::OnInitDialog(){ CDialogEx::OnInitDialog(); ..... ..... ..... // Create the button m_button.Create(_T(" "), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,CRect(50, 50, 100, 100), this, 3); //create MFCToolBar if (!m_wndToolBar.Create(this, AFX_DEFAULT_TOOLBAR_STYLE, 100)) { return FALSE; } m_wndToolBar.SetPaneStyle(m_wndToolBar.GetPaneStyle() & ~(CBRS_GRIPPER | CBRS_SIZE_DYNAMIC | CBRS_BORDER_ANY)); CSize sizeToolBar = m_wndToolBar.CalcFixedLayout(FALSE, TRUE); m_wndToolBar.SetWindowPos(NULL, 0, 0, sizeToolBar.cx, sizeToolBar.cy, SWP_NOACTIVATE | SWP_NOZORDER); HBITMAP bitmap = SvgToHbitmap("XXX.svg"); m_button.SetBitmap(bitmap); int ImageIdx = m_wndToolBar.GetImages()->AddImage(bitmap); m_wndToolBar.InsertButton(CMFCToolBarButton(ID_APP_MENU, -1, _T("Menu"))); m_wndToolBar.InsertButton(CMFCToolBarButton(ID_APP_ABOUT, ImageIdx, _T("About"))); m_wndToolBar.InsertButton(CMFCToolBarButton(ID_APP_EXIT, -1, _T("Exit"))); }
使用CImageList的有效代码
m_CImageList.Create(16, 16, ILC_COLORDDB | ILC_MASK, 0, 1); CBitmap lcbitmap; lcbitmap.Attach(bitmap); const COLORREF rgbWhite = 0x00FFFFFF; int ImageIdx = m_CImageList.Add(&lcbitmap, rgbWhite); m_wndToolBar.GetImages()->CreateFromImageList(m_CImageList);
原因分析
- CMFCToolBar图像列表依赖掩码机制:
GetImages()返回的CMFCToolBarImages类默认使用传统的掩码位图处理透明,而非原生支持32位ARGB的Alpha通道。直接调用AddImage(bitmap)时,它不会自动识别Alpha通道,导致透明区域被渲染为黑色背景。 - CImageList自动生成透明掩码:通过
CImageList中转时,Add(&lcbitmap, rgbWhite)指定了白色为透明色,CImageList会自动生成对应的掩码位图,将白色区域标记为透明。CreateFromImageList把带掩码的图像列表传给工具栏后,能正确识别透明区域,所以显示正常。 - 控件处理逻辑差异:CButton、CTreeCtrl等控件支持直接解析32位ARGB位图的Alpha通道实现透明,而
CMFCToolBarImages的AddImage方法未实现该逻辑,更适配传统的掩码位图模式。
内容的提问来源于stack exchange,提问作者latosvarun
相关产品推荐
相关产品推荐

