创建上下文菜单项

1、新建一个ATL Project。

2、建议将Project Property中Linker – General - “Register Output” 设为no,C/C++ - “Code Generation” - “Runtime Library” 设为 /MTd。

3、在Solution Explorer中右键Add Class,选择ATL Simple Object。并在弹出的对话框中为该Class命名。

4、添加完成后建议Build一下Project,MIDL compiler将根据 .idl文件生成IIDs and CLSIDs。

5、(可选)在Solution Explorer中右键Add Resource导入图标资源。

6、切换到新增Class的 .h文件中,使其继承接口IShellExtInit和IContextMenu。并在 .cpp文件中,参照MSDN给出实现。

 // MyContextMenu.h : Declaration of the CMyContextMenu

 #pragma once
#include "resource.h" // main symbols #include "ContextMenuExample_i.h"
#include <Shlobj.h> #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif using namespace ATL; // CMyContextMenu class ATL_NO_VTABLE CMyContextMenu :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CMyContextMenu, &CLSID_MyContextMenu>,
public IDispatchImpl<IMyContextMenu, &IID_IMyContextMenu,
&LIBID_ContextMenuExampleLib, /*wMajor =*/ , /*wMinor =*/ >,
public IShellExtInit,
public IContextMenu
{
public:
CMyContextMenu()
{
} DECLARE_REGISTRY_RESOURCEID(IDR_MYCONTEXTMENU) BEGIN_COM_MAP(CMyContextMenu)
COM_INTERFACE_ENTRY(IMyContextMenu)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IShellExtInit)
COM_INTERFACE_ENTRY(IContextMenu)
END_COM_MAP() DECLARE_PROTECT_FINAL_CONSTRUCT() HRESULT FinalConstruct(); void FinalRelease(); public:
// IShellExtInit Method
HRESULT STDMETHODCALLTYPE Initialize(
_In_opt_ PCIDLIST_ABSOLUTE pidlFolder,
_In_opt_ IDataObject *pdtobj,
_In_opt_ HKEY hkeyProgID); // IContextMenu Method
HRESULT STDMETHODCALLTYPE QueryContextMenu(
_In_ HMENU hmenu,
_In_ UINT indexMenu,
_In_ UINT idCmdFirst,
_In_ UINT idCmdLast,
_In_ UINT uFlags); HRESULT STDMETHODCALLTYPE InvokeCommand(
_In_ CMINVOKECOMMANDINFO *pici); HRESULT STDMETHODCALLTYPE GetCommandString(
_In_ UINT_PTR idCmd,
_In_ UINT uType,
_Reserved_ UINT *pReserved,
_Out_writes_bytes_((uType & GCS_UNICODE) ? (cchMax * sizeof(wchar_t)) : cchMax) _When_(!(uType & (GCS_VALIDATEA | GCS_VALIDATEW)), _Null_terminated_) CHAR *pszName,
_In_ UINT cchMax); private:
HBITMAP MenuIcon1;
HBITMAP MenuIcon2;
HBITMAP MenuIcon3;
HBITMAP MenuIcon4; }; OBJECT_ENTRY_AUTO(__uuidof(MyContextMenu), CMyContextMenu)

MyContextMenu.h

 // MyContextMenu.cpp : Implementation of CMyContextMenu

 #include "stdafx.h"
#include "MyContextMenu.h" // CMyContextMenu HRESULT CMyContextMenu::FinalConstruct()
{
HINSTANCE hInstance = _AtlBaseModule.GetModuleInstance();
MenuIcon1 = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP1));
MenuIcon2 = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP2));
MenuIcon3 = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP3));
MenuIcon4 = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP4)); return S_OK;
} void CMyContextMenu::FinalRelease()
{
if (MenuIcon1 != NULL)
{
DeleteObject(MenuIcon1);
}
if (MenuIcon2 != NULL)
{
DeleteObject(MenuIcon2);
}
if (MenuIcon3 != NULL)
{
DeleteObject(MenuIcon3);
}
if (MenuIcon4 != NULL)
{
DeleteObject(MenuIcon4);
}
} HRESULT CMyContextMenu::Initialize(
_In_opt_ PCIDLIST_ABSOLUTE pidlFolder,
_In_opt_ IDataObject *pdtobj,
_In_opt_ HKEY hkeyProgID) {
HRESULT hr;
UINT nFileCount; FORMATETC fmt =
{
CF_HDROP,
NULL,
DVASPECT_CONTENT,
-,
TYMED_HGLOBAL
}; STGMEDIUM sm =
{
TYMED_HGLOBAL
}; hr = pdtobj->GetData(&fmt, &sm); if (FAILED(hr))
{
return hr;
} // query quantity of selected files
nFileCount = DragQueryFile((HDROP)sm.hGlobal, 0xFFFFFFFF, NULL, ); if (nFileCount == ) // deal with only one file
{
// analyze selected file }
else
{
hr = E_INVALIDARG;
} ReleaseStgMedium(&sm); return hr;
} // IContextMenu Method
HRESULT CMyContextMenu::QueryContextMenu(
_In_ HMENU hmenu,
_In_ UINT indexMenu,
_In_ UINT idCmdFirst,
_In_ UINT idCmdLast,
_In_ UINT uFlags) { UINT uCmdID = idCmdFirst;
LPCWSTR text1 = TEXT("新增层叠菜单项1");
LPCWSTR text2 = TEXT("新增菜单项2");
LPCWSTR text3 = TEXT("新增菜单项3");
LPCWSTR text4 = TEXT("新增菜单项4");
// do nothing when flag includes CMF_DEFAULTONLY.
if (uFlags & CMF_DEFAULTONLY)
{
return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, );
}
InsertMenu(hmenu, indexMenu, MF_SEPARATOR | MF_BYPOSITION, , NULL);
indexMenu++;
HMENU hSubMenu = CreateMenu();
if (hSubMenu)
{
InsertMenu(hSubMenu, , MF_STRING | MF_BYPOSITION, uCmdID++, text2);
SetMenuItemBitmaps(hSubMenu, , MF_BYPOSITION, MenuIcon2, MenuIcon2);
InsertMenu(hSubMenu, , MF_STRING | MF_BYPOSITION, uCmdID++, text3);
SetMenuItemBitmaps(hSubMenu, , MF_BYPOSITION, MenuIcon3, MenuIcon3);
InsertMenu(hSubMenu, , MF_STRING | MF_BYPOSITION, uCmdID++, text4);
SetMenuItemBitmaps(hSubMenu, , MF_BYPOSITION, MenuIcon4, MenuIcon4);
// InsertMenu(hSubMenu, 3, MF_SEPARATOR | MF_BYPOSITION, 0, NULL);//插入分隔线
}
InsertMenu(hmenu, indexMenu, MF_STRING | MF_POPUP | MF_BYPOSITION, (UINT_PTR)hSubMenu, text1);
SetMenuItemBitmaps(hmenu, indexMenu, MF_BYPOSITION, MenuIcon1, MenuIcon1);
indexMenu++;
InsertMenu(hmenu, indexMenu, MF_SEPARATOR | MF_BYPOSITION, , NULL);
indexMenu++; // inform the explorer how many menu item we have added
return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, uCmdID - idCmdFirst);
} HRESULT CMyContextMenu::InvokeCommand(
_In_ CMINVOKECOMMANDINFO *pici) {
if ( != HIWORD(pici->lpVerb))
return E_INVALIDARG;
// get index of added menu item
switch (LOWORD(pici->lpVerb))
{
case :
{
// 执行新增菜单项2触发的操作
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
TCHAR szCommandLine[] = TEXT("notepad");
BOOL bCreateRet = CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, , NULL, NULL, &si, &pi); break;
}
case :
{
// 执行新增菜单项3触发的操作
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
TCHAR szCommandLine[] = TEXT("write");
BOOL bCreateRet = CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, , NULL, NULL, &si, &pi); break;
}
case :
{
// 执行新增菜单项4触发的操作
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
TCHAR szCommandLine[] = TEXT("cmd");
BOOL bCreateRet = CreateProcess(NULL, szCommandLine, NULL, NULL, FALSE, , NULL, NULL, &si, &pi); break;
}
default:
{
return E_INVALIDARG;
break;
}
}
return S_OK;
} HRESULT CMyContextMenu::GetCommandString(
_In_ UINT_PTR idCmd,
_In_ UINT uType,
_Reserved_ UINT *pReserved,
_Out_writes_bytes_((uType & GCS_UNICODE) ? (cchMax * sizeof(wchar_t)) : cchMax) _When_(!(uType & (GCS_VALIDATEA | GCS_VALIDATEW)), _Null_terminated_) CHAR *pszName,
_In_ UINT cchMax) {
USES_CONVERSION;
LPCTSTR szPrompt;
// copy help info to cache when explorer ask
if (uType & GCS_HELPTEXT)
{
switch (idCmd)
{
case :
szPrompt = _T("新增菜单项2说明文字");
break;
case :
szPrompt = _T("新增菜单项3说明文字");
break;
case :
szPrompt = _T("新增菜单项4说明文字");
break;
default:
//ATLASSERT(0); // should never get here
return E_INVALIDARG;
break;
}
if (uType & GCS_UNICODE)
{
lstrcpynW((LPWSTR)pszName, T2CW(szPrompt), cchMax);
}
else
{
lstrcpynA(pszName, T2CA(szPrompt), cchMax);
}
return S_OK;
}
return E_INVALIDARG;
}

7、在 .rgs文件中添加注册表信息,确保各GUID与 .idl文件中的一致。

 HKCR
{
NoRemove CLSID
{
ForceRemove {9C50C98F-E1FF-41CF-BD54-E9A3BBDDDEF8} = s 'MyContextMenu Class'
{
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Apartment'
}
TypeLib = s '{EB1C2F43-315D-4D8F-9A2A-70E67BE888E2}'
Version = s '1.0'
}
} NoRemove *
{
NoRemove ShellEx
{
NoRemove ContextMenuHandlers
{
ForceRemove MyContextMenu = s '{9C50C98F-E1FF-41CF-BD54-E9A3BBDDDEF8}'
}
}
}
}

8、Build Project 后打开cmd.exe,通过regsvr32命令注册或解注册生成的 .dll文件。

10、查看效果如下图所示。

——————————————————

本文为本人原创,如需转载请注明出处。

http://www.cnblogs.com/lantingji/p/5857380.html

Creating Context Menu / 创建上下文菜单项 / VC++, Windows, DLL, ATL, COM的更多相关文章

  1. Creating Contextual Menus创建上下文菜单

    A contextual menu offers actions that affect a specific item or context frame in the UI. You can pro ...

  2. Creating Icon Overlay Handlers / 创建图标标记 Handlers (续) / VC++, Windows, DLL, ATL, COM

    创建图标标记 Handlers (续) 1.新建一个ATL Project. 2.建议将 Project Property 中 Linker – General - “Register Output” ...

  3. Creating Icon Overlay Handlers / 创建图标标记 Handlers (翻译自MSDN) / VC++, Windows, DLL, ATL, COM

    创建图标标记 Handlers Creating Icon Overlay Handlers 图标标记是放在代表着某个 Shell 对象的图标之左下角的小图像.它们通常被加在一个对象的图标的身上来提供 ...

  4. Android Dialog 创建上下文菜单

    Android Dialog中的listview创建上下文菜单 listView.setOnCreateContextMenuListener(new OnCreateContextMenuListe ...

  5. ContextMenu菜单创建 上下文菜单的基本认识q

    MainActivity.class public class MainActivity extends AppCompatActivity { @Override protected void on ...

  6. android 开发-(Contextual Menu)上下文菜单的实现

    在android3.0以后,安卓设备不在提供物理的菜单按键,同时,android应用提供了另外的菜单实现机制,来替代之前的菜单创建方式.安卓设备中,平常可以使用长按住某个内容弹出菜单选项.这就是我们需 ...

  7. Android开发之Menu:OptionMenu(选项菜单)、ContextMenu(上下文菜单)、SubMenu(子菜单)

    菜单的概念,现在已经很普及了.Windows系统.Mac.桌面版Linux.Java Swing等,都有可视化菜单.一.Android平台3种菜单  选项菜单(OptionMenu).上下文菜单(Co ...

  8. 安卓开发笔记——Menu菜单组件(选项菜单,上下文菜单,子菜单)

    菜单是用户界面中最常见的元素之一,使用非常频繁,在Android中,菜单被分为如下三种,选项菜单(OptionsMenu).上下文菜单(ContextMenu)和子菜单(SubMenu). 菜单的实现 ...

  9. Android菜单详解(四)——使用上下文菜单ContextMenu

    之前在<Android菜单详解(二)——创建并响应选项菜单>和<Android菜单详解(三)——SubMenu和IconMenu>中详细讲解了选项菜单,子菜单和图标菜单.今天接 ...

随机推荐

  1. python url拼接

    import datetime,requests import json,time,urllib import hashlib self.url_domain = “www.baidu,com/” u ...

  2. Codeforces 716 E Digit Tree

    E. Digit Tree time limit per test 3 seconds memory limit per test 256 megabytes input standard input ...

  3. 【线段树】Codeforces Round #393 (Div. 1) C. Nikita and stack

    就是给你一些元素的进栈 出栈操作,不按给定的顺序,要求你对于每次输入,都依据其及其之前的输入,判断出栈顶的元素是谁. 用线段树维护,每次push,将其位置的值+1,pop,将其位置的值-1.相当于寻找 ...

  4. 【后缀数组】【二分答案】poj3261

    注意:对整型数组求sa时,s[n]请置成-1. 请离散化. 可重叠的 k 次最长重复子串(pku3261)给定一个字符串,求至少出现 k 次的最长重复子串,这 k 个子串可以重叠.算法分析:先二分答案 ...

  5. python3开发进阶-Django框架的中间件的五种用法和逻辑过程

    阅读目录 什么是中间件 中间件的执行流程 中间件的逻辑过程 一.什么是中间件? 官方的说法:中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量.低级别的插件系统,用于在全局范围 ...

  6. Linux中安装MySql 5.7.21的详细操作步骤

    一:到mysql官网下载最新的mysql包 mysql-5.7.21-linux-glibc2.12-x86_64 官方下载地址:https://dev.mysql.com/downloads/mys ...

  7. c++基础类型之signed、unsigned的一个细节

    数值型 c++中,对于 int.long.int64....等这些数值类型,如果是有符合的,则类型前加不加 signed 其效果都是一样的. 比如如下声明: int nA; // 与 signed i ...

  8. Scala实战高手****第9课:Scala类和对象彻底实战和Spark源码鉴赏

    scala类和对象 RDD中创建_sc和deps相比java更加的简洁. 在Spark的例如SparkContext.sqlSpark等全局成员在完成实例化. 在唯一实例的时候一般不会去使用伴生对象a ...

  9. 【转载】Mini6410启动过程

    这段时间在尝试使用uBoot来替代友善的Superboot,让板子支持从SD卡启动,所以就仔细研究了一下友善提供的内核和它的启动参数,发现 友善真的蛮聪明,把电脑的启动方式借鉴到它们自己的开发板上了. ...

  10. VSM(Virtual Storage Manager For Ceph)安装教程

    转载注明出处,陈小跑 http://www.cnblogs.com/chenxianpao/p/5770271.html 一.安装环境 OS:CentOS7.2 VSM:v2.1 released 二 ...