简体   繁体   English

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

[英]Shell extension for explorer context menu, icon breaks alignment in classic Windows design

I'got following problem, 我没有跟踪问题,

when adding an entry for the context menu of the windows explorer and the windows 7 design is set to classic, the icon breaks the alignment of the menu. 在Windows资源管理器的上下文菜单中添加条目并将Windows 7设计设置为经典时,该图标会中断菜单的对齐方式。

This picture show the menu before adding the entry (Please regard the icon of Microsoft Security Essentials): 此图显示了添加条目之前的菜单(请注意Microsoft Security Essentials的图标):

正常行为

After adding the menu entry it looks like this: 添加菜单项后,它看起来像这样:

错误行为

You see that there is a space between the icon of Microsoft Security Essentials and the menu caption. 您会看到Microsoft Security Essentials的图标和菜单标题之间有一个空格。 The used bitmap is a standard bmp 16 x 16. 使用的位图是标准bmp 16 x 16。

Have anyone an idea why this happens? 有谁知道为什么会这样? Once again, this only happens with the Win 7 classic design, with other designs it works as expected. 再一次,这仅在Win 7经典设计中发生,并且在其他设计中也能按预期运行。

Thanks in advance for your help 在此先感谢您的帮助

EDIT: 编辑:

This is my initial code for adding the item: 这是我添加项目的初始代码:

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

After your help i changed: 在您的帮助之后,我改变了:

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

to: 至:

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; 

} }

Your original code was correct... Don't bother with that IconToBitmap function since your LoadImageW returns HBITMAP when IMAGE_BITMAP is specified. 您的原始代码是正确的...不必理会该IconToBitmap函数,因为当指定IMAGE_BITMAP时,LoadImageW返回HBITMAP。

Menus with bitmaps on XP or using the Classic theme on later versions of Windows seem to reserve space for checkmarks and you sometimes need to call SetMenuInfo with MNS_CHECKORBMP... Try the following code: 在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());
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM