IDocHostUIHandler::ShowContextMenu添加自定义菜单的另类实现

转载 2012年03月24日 15:19:38

在很久很久以前(其实也就是IE6时代 - -),要实现在IWebBrowser2弹出原始的IE右键菜单,传统的思路是在ShowContextMenu加载SHDOCLC.DLL,读取菜单资源IDR_BROWSE_CONTEXT_MENU来获取菜单句柄,然后InsertMenu插入自己的菜单项 - -。在IE6.0以后的内核版本是没有提供SHDOCLC.DLL来让你加载的。

 

这里有两种另类的实现方式:

第一种是使用SetWindowLong,接管WndProc,一切尽在接管之中。

第二种是在自己的程序中添加相应的菜单ITEM,弹出菜单后,接管一些ITEM点击事件。

第二种方法的详细实现:

 

STDMETHODIMP CMyDocHostUIHandler::ShowContextMenu(DWORD dwID, POINT* ppt, IUnknown* pcmdtReserved, IDispatch* pdispReserved)
{
// 添加扩展菜单
#define SHDVID_ADDMENUEXTENSIONS        53
// 获取编码菜单
#define SHDVID_GETMIMECSETMENU          27

    CMenu menu;
    menu.LoadMenu( IDR_IE_DEFAULT_POPUP );     // 自己山寨的IE菜单

    // 获取菜单子项位置
    int nSubMenuPos = -1;

    switch ( dwID )
    {
        // 默认
    case CONTEXT_MENU_DEFAULT:
        nSubMenuPos = 0;
        break;

        // 图像
    case CONTEXT_MENU_IMAGE:
        nSubMenuPos = 1;
        break;

        // 锚
    case CONTEXT_MENU_ANCHOR:
        nSubMenuPos = 2;
        break;

        // DYNSRC 图像
    case CONTEXT_MENU_IMGDYNSRC:
        nSubMenuPos = 3;
        break;

        // ART 图像
    case CONTEXT_MENU_IMGART:
        nSubMenuPos = 4;
        break;

    default:
        break;
    }

    if ( nSubMenuPos == -1 )
        return S_FALSE;
    // 获取子菜单位置
    CMenuHandle menuHandle = menu.GetSubMenu( nSubMenuPos );
    if ( menuHandle.IsNull() )
        return S_FALSE;

    // 弹出菜单
    HRESULT hr;
    HWND hwnd;
    CComPtr<IOleCommandTarget> spCT;
    CComPtr<IOleWindow> spWnd;

    hr = pcmdtReserved->QueryInterface(IID_IOleCommandTarget, (void**)&spCT);
    if ( FAILED(hr) )
        return S_FALSE;

    hr = pcmdtReserved->QueryInterface(IID_IOleWindow, (void**)&spWnd);
    if ( FAILED(hr) )
        return S_FALSE;

    hr = spWnd->GetWindow(&hwnd);
    if ( FAILED(hr) )
        return S_FALSE;

    // 添加编码
    CComVariant var;
    hr = spCT->Exec(&CGID_ShellDocView, SHDVID_GETMIMECSETMENU, 0, NULL, &var);
    if ( SUCCEEDED(hr) )
    {
        MENUITEMINFO mii = {0};
        mii.cbSize = sizeof(mii);
        mii.fMask = MIIM_SUBMENU;
        mii.hSubMenu = (HMENU) var.byref;

        // 添加语言栏
        menuHandle.SetMenuItemInfo(IDM_LANGUAGE, FALSE, &mii);
    }

    // 从注册表中加载扩展菜单(MenuExt)
    CComVariant var1;
    V_VT(&var1) = VT_INT_PTR;
    V_BYREF(&var1) = (HMENU)menuHandle;

    CComVariant var2;
    V_VT(&var2) = VT_I4;
    V_I4(&var2) = dwID;

    hr = spCT->Exec(&CGID_ShellDocView, SHDVID_ADDMENUEXTENSIONS, 0, &var1, &var2);
    if ( FAILED(hr) )
    {
        // 删除扩展菜单项
        menuHandle.DeleteMenu(IDM_MENUEXT_PLACEHOLDER, MF_BYCOMMAND);
    }

    // 弹出菜单
    int iSelection = menuHandle.TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD,
        ppt->x, ppt->y, hwnd );
    /************************************************************/
    // iSelection==菜单ITEM ID,对指定的ID项进行特殊处理。咔咔,你懂的。
    /************************************************************/
    // 对菜单进行默认处理
    ::SendMessage(hwnd, WM_COMMAND, iSelection, NULL);

    return S_OK;
}
 

附上山寨的IE右键菜单(用PE Explorer取到的ITEM)

IDR_IE_DEFAULT_POPUP MENU 
BEGIN
    POPUP "默认"
    BEGIN
        MENUITEM "后退(&B)",                      2282
        MENUITEM "前进(&O)",                      2283
        MENUITEM SEPARATOR
        MENUITEM "背景另存为(&S)...",                2263
        MENUITEM "设置为背景(&G)",                   2264
        MENUITEM "复制背景(&C)",                    2265
        MENUITEM "设为桌面项(&D)...",                2278
        MENUITEM SEPARATOR
        MENUITEM "全选(&A)",                      31
        MENUITEM "粘贴(&P)",                      26
        MENUITEM SEPARATOR
        MENUITEM "创建快捷方式(&T)",                  2266
        MENUITEM "添加到收藏夹(&F)...",               2261
        MENUITEM "查看源文件(&V)",                   2139
        MENUITEM SEPARATOR
        MENUITEM "编码(&E)",                      2292
        MENUITEM SEPARATOR
        MENUITEM "打印(&I)",                      27
        MENUITEM "刷新(&R)",                      6042
        MENUITEM ""                      6047
        MENUITEM SEPARATOR
        MENUITEM "属性(&P)",                      28
    END
    POPUP "图像"
    BEGIN
        MENUITEM "打开链接(&O)",                    2136
        MENUITEM "在新窗口中打开链接(&N)",               2137
        MENUITEM "目标另存为(&A)...",                2268
        MENUITEM "打印目标(&P)",                    2273
        MENUITEM SEPARATOR
        MENUITEM "显示图片(&H)",                    2269
        MENUITEM "图片另存为(&S)...",                2270
        MENUITEM "电子邮件图片(&E)...",               2288
        MENUITEM "打印图片(&I)...",                 2289
        MENUITEM "转到图片收藏(&G)",                  2287
        MENUITEM "设置为背景(&G)",                   2264
        MENUITEM "设为桌面项(&D)...",                2278
        MENUITEM SEPARATOR
        MENUITEM "剪切(&T)",                      16
        MENUITEM "复制(&C)",                      15
        MENUITEM "复制快捷方式(&T)",                  2262
        MENUITEM "粘贴(&P)",                      26
        MENUITEM SEPARATOR
        MENUITEM "添加到收藏夹(&F)...",               2261
        MENUITEM ""                      6047
        MENUITEM SEPARATOR
        MENUITEM "属性(&P)",                      28
    END
    POPUP "锚"
    BEGIN
        MENUITEM "打开(&O)",                      2136
        MENUITEM "在新窗口中打开(&N)",                 2137
        MENUITEM "目标另存为(&A)...",                2268
        MENUITEM "打印目标(&P)",                    2273
        MENUITEM SEPARATOR
        MENUITEM "剪切(&T)",                      16
        MENUITEM "复制(&C)",                      15
        MENUITEM "复制快捷方式(&T)",                  2262
        MENUITEM "粘贴(&P)",                      26
        MENUITEM SEPARATOR
        MENUITEM "添加到收藏夹(&F)...",               2261
        MENUITEM ""                      6047
        MENUITEM SEPARATOR
        MENUITEM "属性(&P)",                      28
    END
    POPUP "DYNSRC 图像"
    BEGIN
        MENUITEM "打开链接(&O)",                    2136
        MENUITEM "在新窗口中打开链接(&N)",               2137
        MENUITEM "目标另存为(&A)...",                2268
        MENUITEM "打印目标(&P)",                    2273
        MENUITEM SEPARATOR
        MENUITEM "显示图片(&H)",                    2269
        MENUITEM "图片另存为(&S)...",                2270
        MENUITEM "设置为背景(&G)",                   2264
        MENUITEM "设为桌面项(&D)...",                2278
        MENUITEM SEPARATOR
        MENUITEM "剪切(&T)",                      16
        MENUITEM "复制(&C)",                      15
        MENUITEM "复制快捷方式(&T)",                  2262
        MENUITEM "粘贴(&P)",                      26
        MENUITEM SEPARATOR
        MENUITEM "添加到收藏夹(&F)...",               2261
        MENUITEM ""                      6047
        MENUITEM SEPARATOR
        MENUITEM "播放",                          2271
        MENUITEM "停止",                          2272
        MENUITEM "属性(&R)",                      28
    END
    POPUP "ART 图像"
    BEGIN
        MENUITEM "打开链接(&O)",                    2136
        MENUITEM "在新窗口中打开链接(&N)",               2137
        MENUITEM "目标另存为(&A)...",                2268
        MENUITEM "打印目标(&P)",                    2273
        MENUITEM SEPARATOR
        MENUITEM "显示图片(&H)",                    2269
        MENUITEM "图片另存为(&S)...",                2270
        MENUITEM "设置为背景(&G)",                   2264
        MENUITEM "设为桌面项(&D)...",                2278
        MENUITEM SEPARATOR
        MENUITEM "剪切(&T)",                      16
        MENUITEM "复制(&C)",                      15
        MENUITEM "复制快捷方式(&T)",                  2262
        MENUITEM "粘贴(&P)",                      26
        MENUITEM SEPARATOR
        MENUITEM "添加到收藏夹(&F)...",               2261
        MENUITEM SEPARATOR
        MENUITEM "播放",                          2274
        MENUITEM "停止",                          2275
        MENUITEM "重绕",                          2276
        MENUITEM ""                      6047
        MENUITEM SEPARATOR
        MENUITEM "属性(&P)",                      28
    END
END

IDocHostUIHandler::ShowContextMenu添加自定义菜单的另类实现

这里有两种另类的实现方式: 第一种是使用SetWindowLong,接管WndProc,一切尽在接管之中。 第二种是在自己的程序中添加相应的菜单ITEM,弹出菜单后,接管一些ITEM点击事件。 ...
  • fuxiucheng
  • fuxiucheng
  • 2013年04月01日 14:08
  • 296

(转)续 WebBrowser 的扩展

上次写了WebBrowser这个容器( 详细参看: http://blog.csdn.net/norsd/archive/2008/09/13/2921389.aspx ) 今天来说说如...
  • gxj1680
  • gxj1680
  • 2014年02月14日 18:53
  • 842

情景菜单ContextMenu的创建

各位大大我也是初学者,写这些主要是为了对其认识更加清晰,同时也为了以后忘记时可以快速的回忆起。这是我第一次看源码在结合其他大大的思想得到的总结,可能会有很多问题,如果你们发现怎么不对可以告诉我,我很希...
  • u012646150
  • u012646150
  • 2015年05月29日 15:34
  • 591

【Android】上下文菜单ContextMenu的使用

上下文菜单 又称长按菜单。当一个视图注册了上下文菜单时,执行一个在该对象上长按(2秒)的动作,将出现一个具有相关功能的浮动菜单。 类概述 扩展自Menu的上下文菜单提供了修改上下文菜单头(hea...
  • oYunTaoLianWu
  • oYunTaoLianWu
  • 2013年09月29日 00:14
  • 13794

Win7系统如何在桌面右键菜单里添加自定义程序或网址?

先来看一下效果展示: 步骤: 1、点击【开始】->【运行】(如果没有【运行】请点击http://jingyan.baidu.com/article/1e5468f961f04f484961b7...
  • baidu_38494049
  • baidu_38494049
  • 2017年07月11日 15:14
  • 423

Qt之右键菜单实现

最近在看C++ GUI  Qt4部分其中有个例子对于扩展一个应用程序提供一个上下文菜单,其中该程序只是定义一个变量来实现其中用到了一个函数(下文会给予解答)。但是更高级的是重新定义事件处理函数void...
  • bzhxuexi
  • bzhxuexi
  • 2015年11月20日 10:50
  • 1918

如何实现jquery自定义点击右键菜单显示

jquery自定义点击右键菜单显示其实很简单,只要下载一个smartMenu.js和一个smartMenu.css两个文件之后,将两个文件分别加入到css和js文件夹下面,然后在前台写上以下代码,就可...
  • yu13767514297
  • yu13767514297
  • 2015年07月24日 15:16
  • 2933

【Unity编辑器】使用反射和Attribute实现自定义右键菜单

unity中使用自定义Attribute实现右键菜单
  • mobilebbki399
  • mobilebbki399
  • 2016年07月10日 15:48
  • 1713

PyQt4在TextEdit控件中创建右键菜单

今天开发界面遇到一个问题,想将textedit的显示内容及时清空,但是由于系统自带的caidan...
  • qingyang1014
  • qingyang1014
  • 2014年08月17日 00:23
  • 1910

给win8、win10系统添加自定义右键菜单项目

首先我们打开注册表,按下键盘上win+R组合键打开运行,输入regedit,然后回车即可打开注册表了。 然后我们定位到HKEY_CLASSES_ROOT\Directory\background\s...
  • netoT
  • netoT
  • 2015年12月15日 13:26
  • 12474
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:IDocHostUIHandler::ShowContextMenu添加自定义菜单的另类实现
举报原因:
原因补充:

(最多只允许输入30个字)