CMFCStatusBar :: SetPaneIcon поддерживает альфа-значок?

Значки настроек моего приложения для панелей в строке состояния (класс CMFCStatusBar). Для этой задачи есть только один метод — CMFCStatusBar :: SetPaneIcon (). Но если значок имеет альфа-канал, этот метод загружает неправильное изображение (на черном фоне).
Я посмотрел в исходный код и увидел, что CMFCStatusBar использует внутренние HIMAGELIST для каждой панели. Все это HIMAGELIST создает с флагом ILC_MASK | ILC_COLORDDB, а не ILC_COLOR32 или ILC_COLOR24.

Это ошибка!

Итак, есть ли способ использовать значки с альфа-каналом на панелях CMFCStatusBar?

Пример:

HICON hIcon = ::LoadImage(hModule, MAKEINTRESOURCE(nIconID), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
m_StatusBar.SetPaneIcon(m_StatusBar.CommandToIndex(ID_INDICATOR_1), hIcon);

0

Решение

Microsoft разработала классы CMFC (Feature Pack) из BCG инструментарий. Если вы сравните CMFCStatusBar::SetPaneIcon() метод с BCG Метод из того же класса, вы заметите несколько тонких различий.

BCG определяет свой метод с флагом для альфа-смеси. Метод выглядит так:

void CBCGPStatusBar::SetPaneIcon (int nIndex, HBITMAP hBmp,
COLORREF clrTransparent, BOOL bUpdate, BOOL bAlphaBlend/* = FALSE*/)

Эквивалент CMFC убирает флаг «bAlphaBlend».
Сравнивая код метода, вы увидите, что BCG использует следующий код, который был удален из версии CMFC:

DWORD dwFlags = ILC_MASK | ILC_COLORDDB;
if (bAlphaBlend)
{
dwFlags = ILC_COLOR32;
}

pSBP->hImage = ::ImageList_Create (pSBP->cxIcon, pSBP->cyIcon, dwFlags, 1, 0);

Я не уверен, почему версия CMFC так сильно отличается (у Microsoft может быть веская причина), но я включил версию BCG ниже. Я изучил бы версию BCG и, возможно, создал бы свой собственный метод SetPaneIcon из этого кода (на свой страх и риск).

void CBCGPStatusBar::SetPaneIcon (int nIndex, HBITMAP hBmp,
COLORREF clrTransparent, BOOL bUpdate, BOOL bAlphaBlend/* = FALSE*/)
{
ASSERT_VALID(this);

CBCGStatusBarPaneInfo* pSBP = _GetPanePtr(nIndex);
if (pSBP == NULL)
{
ASSERT (FALSE);
return;
}

// Disable animation (if exist):
SetPaneAnimation (nIndex, NULL, 0, FALSE);

if (hBmp == NULL)
{
if (pSBP->hImage != NULL)
{
::ImageList_Destroy (pSBP->hImage);
}

pSBP->hImage = NULL;

if (bUpdate)
{
InvalidatePaneContent (nIndex);
}

return;
}

BITMAP bitmap;
::GetObject (hBmp, sizeof (BITMAP), &bitmap);

if (pSBP->hImage == NULL)
{
pSBP->cxIcon = bitmap.bmWidth;
pSBP->cyIcon = bitmap.bmHeight;

DWORD dwFlags = ILC_MASK | ILC_COLORDDB;
if (bAlphaBlend)
{
dwFlags = ILC_COLOR32;
}

pSBP->hImage = ::ImageList_Create (pSBP->cxIcon, pSBP->cyIcon, dwFlags, 1, 0);
RecalcLayout ();
}
else
{
ASSERT (pSBP->cxIcon == bitmap.bmWidth);
ASSERT (pSBP->cyIcon == bitmap.bmHeight);

::ImageList_Remove (pSBP->hImage, 0);
}

//---------------------------------------------------------
// Because ImageList_AddMasked changes the original bitmap,
// we need to create a copy:
//---------------------------------------------------------
HBITMAP hbmpCopy = (HBITMAP) ::CopyImage (hBmp, IMAGE_BITMAP, 0, 0, 0);

if (bAlphaBlend)
{
::ImageList_Add (pSBP->hImage, hbmpCopy, NULL);
}
else
{
::ImageList_AddMasked (pSBP->hImage, hbmpCopy, clrTransparent);
}

::DeleteObject (hbmpCopy);

if (bUpdate)
{
InvalidatePaneContent (nIndex);
}
}
1

Другие решения

Мое решение, основанное на rrirower код.

CMFCStatusBarPaneInfo* CMyStatusBar::GetPane(int nIndex) const {
if (nIndex == 255 && m_nCount < 255) {
// Special case for the simple pane
for (int i = 0; i < m_nCount; i++)
{
CMFCStatusBarPaneInfo* pSBP = GetPane(i);
ENSURE(pSBP != NULL);

if (pSBP->nStyle & SBPS_STRETCH) {
return pSBP;
}
}
}

if (nIndex < 0 || nIndex >= m_nCount) {
return NULL;
}

if (m_pData == NULL) {
ASSERT(FALSE);
return NULL;
}

return((CMFCStatusBarPaneInfo*)m_pData) + nIndex;
}void CMyStatusBar::SetPaneIcon(int nIndex, HICON hIcon, BOOL bUpdate /*= TRUE*/)
{
ASSERT_VALID(this);

CMFCStatusBarPaneInfo* pSBP = GetPane(nIndex);
if (pSBP == NULL)
{
ASSERT(FALSE);
return;
}

// Disable animation(if exist):
SetPaneAnimation(nIndex, NULL, 0, FALSE);

if (hIcon == NULL)
{
if (pSBP->hImage != NULL)
{
::ImageList_Destroy(pSBP->hImage);
}

pSBP->hImage = NULL;

if (bUpdate)
{
InvalidatePaneContent(nIndex);
}

return;
}

ICONINFO iconInfo;
::GetIconInfo(hIcon, &iconInfo);

BITMAP bitmap;
::GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bitmap);

::DeleteObject(iconInfo.hbmColor);
::DeleteObject(iconInfo.hbmMask);

if (pSBP->hImage == NULL)
{
pSBP->cxIcon = bitmap.bmWidth;
pSBP->cyIcon = bitmap.bmHeight;

pSBP->hImage = ::ImageList_Create(pSBP->cxIcon, pSBP->cyIcon, ILC_COLOR32 | ILC_MASK, 1, 0);
::ImageList_AddIcon(pSBP->hImage, hIcon);

RecalcLayout();
}
else
{
ASSERT(pSBP->cxIcon == bitmap.bmWidth);
ASSERT(pSBP->cyIcon == bitmap.bmHeight);

::ImageList_ReplaceIcon(pSBP->hImage, 0, hIcon);
}

if (bUpdate)
{
InvalidatePaneContent(nIndex);
}
}
0

По вопросам рекламы [email protected]