Расширение оболочки для контекстного меню проводника, выравнивание значков в классическом дизайне Windows

У меня возникла следующая проблема,

при добавлении записи для контекстного меню проводника Windows и дизайна Windows 7, установленного на классический, значок нарушает выравнивание меню.

На этом рисунке показано меню перед добавлением записи (см. Значок Microsoft Security Essentials):

нормальное поведение

После добавления пункта меню это выглядит так:

неправильное поведение

Вы видите, что между значком Microsoft Security Essentials и заголовком меню есть пробел. Используемое растровое изображение является стандартным BMP 16 х 16.

У кого-нибудь есть идея, почему это происходит? Еще раз, это случается только с классическим дизайном Win 7, с другими проектами это работает как ожидалось.

Заранее спасибо за помощь

РЕДАКТИРОВАТЬ:

Это мой начальный код для добавления элемента:

iconHandle = LoadImageW(NULL, iconPath.c_str(), IMAGE_BITMAP, 0, 0,   LR_DEFAULTSIZE | LR_LOADTRANSPARENT | LR_LOADFROMFILE);

MENUITEMINFOW contextEntryAppSuite = { sizeof(contextEntryAppSuite) };
contextMenuItem.fMask =  MIIM_STRING | MIIM_STATE | MIIM_BITMAP | MIIM_FTYPE | MIIM_ID;
contextMenuItem.dwTypeData = caption;
contextMenuItem.wID = 0;
contextMenuItem.fType = MFT_STRING;
contextMenuItem.fState = MFS_ENABLED;
contextMenuItem.hbmpItem = static_cast<HBITMAP>(iconHandle);
if(!InsertMenuItemW(hMenu, indexMenu, TRUE, &contextMenuItem))
{
return HRESULT_FROM_WIN32(GetLastError());
}

После вашей помощи я изменился:

contextMenuItem.hbmpItem = static_cast<HBITMAP>(iconHandle);

чтобы:

contextMenuItem.hbmpItem = IconToBitmap(pathToIcon);

// the function from your posted link

HBITMAP IconToBitmap(std::string sIcon)
{
RECT rect;
rect.right = ::GetSystemMetrics(SM_CXMENUCHECK);
rect.bottom = ::GetSystemMetrics(SM_CYMENUCHECK);

rect.left = rect.top  = 0;

HICON hIcon = (HICON)LoadImageA(NULL, sIcon.c_str(), IMAGE_ICON,    rect.right, rect.bottom, LR_DEFAULTCOLOR | LR_LOADFROMFILE);
if (!hIcon)
return NULL;

HWND desktop = ::GetDesktopWindow();
if (desktop == NULL)
{
DestroyIcon(hIcon);
return NULL;
}

HDC screen_dev = ::GetDC(desktop);
if (screen_dev == NULL)
{
DestroyIcon(hIcon);
return NULL;
}

// Create a compatible DC
HDC dst_hdc = ::CreateCompatibleDC(screen_dev);
if (dst_hdc == NULL)
{
DestroyIcon(hIcon);
::ReleaseDC(desktop, screen_dev);
return NULL;
}

// Create a new bitmap of icon size
HBITMAP bmp = ::CreateCompatibleBitmap(screen_dev, rect.right, rect.bottom);
if (bmp == NULL)
{
DestroyIcon(hIcon);
::DeleteDC(dst_hdc);
::ReleaseDC(desktop, screen_dev);
return NULL;
}

// Select it into the compatible DC
HBITMAP old_dst_bmp = (HBITMAP)::SelectObject(dst_hdc, bmp);
if (old_dst_bmp == NULL)
{
DestroyIcon(hIcon);
return NULL;
}

// Fill the background of the compatible DC with the given colour
::SetBkColor(dst_hdc, RGB(255, 255, 255));
::ExtTextOut(dst_hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);

// Draw the icon into the compatible DC
::DrawIconEx(dst_hdc, 0, 0, hIcon, rect.right, rect.bottom, 0, NULL, DI_NORMAL);

// Restore settings
::SelectObject(dst_hdc, old_dst_bmp);
::DeleteDC(dst_hdc);
::ReleaseDC(desktop, screen_dev);
DestroyIcon(hIcon);
return bmp;

}

0

Решение

Ваш исходный код был верным … Не беспокойтесь об этой функции IconToBitmap, поскольку ваш LoadImageW возвращает HBITMAP, если указан IMAGE_BITMAP.

Меню с растровыми изображениями в XP или с использованием классической темы в более поздних версиях Windows, кажется, оставляют место для галочек, и иногда вам нужно вызвать SetMenuInfo с MNS_CHECKORBMP … Попробуйте следующий код:

iconHandle = LoadImageW(NULL, iconPath.c_str(), IMAGE_BITMAP, 0, 0,   LR_DEFAULTSIZE | LR_LOADTRANSPARENT | LR_LOADFROMFILE);

MENUITEMINFOW contextEntryAppSuite = { sizeof(contextEntryAppSuite) };
contextMenuItem.fMask =  MIIM_STRING | MIIM_STATE | MIIM_BITMAP | MIIM_FTYPE | MIIM_ID;
contextMenuItem.dwTypeData = caption;
contextMenuItem.wID = 0;
contextMenuItem.fType = MFT_STRING;
contextMenuItem.fState = MFS_ENABLED;
contextMenuItem.hbmpItem = static_cast<HBITMAP>(iconHandle);

MENUINFO menuInfo;
menuInfo.cbSize = sizeof(MENUINFO);
menuInfo.fMask = MIM_STYLE;
menuInfo.dwStyle = MNS_CHECKORBMP;
SetMenuInfo(hMenu, &menuInfo);

if(!InsertMenuItemW(hMenu, indexMenu, TRUE, &contextMenuItem))
{
return HRESULT_FROM_WIN32(GetLastError());
}
2

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


По вопросам рекламы ammmcru@yandex.ru
Adblock
detector