c++ - 资源管理器上下文菜单的 Shell 扩展,图标打破了经典 Windows 设计中的对齐方式

标签 c++ icons contextmenu explorer shell-extensions

我有以下问题,

当为 windows 资源管理器的上下文菜单添加条目并且 windows 7 设计设置为经典时,图标会破坏菜单的对齐方式。

此图为添加条目前的菜单(请注意Microsoft Security Essentials图标):

normal behaviour

添加菜单条目后,它看起来像这样:

wrong behaviour

您会看到 Microsoft Security Essentials 的图标和菜单标题之间有一个空格。使用的位图是标准的 bmp 16 x 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; 

最佳答案

您的原始代码是正确的...不要理会 IconToBitmap 函数,因为您的 LoadImageW 在指定 IMAGE_BITMAP 时返回 HBITMAP。

在 XP 上带有位图的菜单或在更高版本的 Windows 上使用经典主题似乎为复选标记保留了空间,有时您需要使用 MNS_CHECKORBMP 调用 SetMenuInfo...尝试以下代码:

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());
}

关于c++ - 资源管理器上下文菜单的 Shell 扩展,图标打破了经典 Windows 设计中的对齐方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30325956/

相关文章:

c++ - 我可以在构造函数的初始化列表中执行完整性检查吗?

c++ - 动态 C 字符串访问

java - 如何向警报框添加图标?

javascript - 单击 Handsontable 中的 contextMenu 'Bold' 时,如何允许所选单元格文本变为粗体

wpf - 如何在 ContextMenu 内为 MenuItem 设置 CommandTarget?

c++ - 为什么在推导类型时去除模板参数的限定符?

c++ - 字符串到唯一指针数组

Android Studio 启动器图标为黑色

javascript - 在 JS 中使用默认的谷歌地图标记

c# - 如何使用 C# 自动右键单击系统托盘中的图标