创建上下文菜单项

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. ubuntu 下终端关于调试C++的命令

    先确定安装了vim 和gcc (c语言)或者g++(c++) 如果没有安装可以在终端输入以下命令: sudo apt-get install build-essential sudo apt-get ...

  2. 【二维偏序】【树状数组】【权值分块】【分块】poj2352 Stars

    经典问题:二维偏序.给定平面中的n个点,求每个点左下方的点的个数. 因为 所有点已经以y为第一关键字,x为第二关键字排好序,所以我们按读入顺序处理,仅仅需要计算x坐标小于<=某个点的点有多少个就 ...

  3. Exercise02_17

    import javax.swing.JOptionPane; public class FrostTemperature { public static void main(String[] arg ...

  4. 手把手教你使用FineUI开发一个b/s结构的取送货管理信息系统系列博文索引

    近阶段接到一些b/s类型的软件项目,但是团队成员之前大部分没有这方面的开发经验,于是自己选择了一套目前网上比较容易上手的开发框架(FineUI),计划录制一套视频讲座,来讲解如何利用FineUI快速开 ...

  5. ios如何实现被键盘遮挡时,带有textfield的tableview自动上移

    最正规的办法,用通知step 1:在进入视图的时候添加监视:(viewDidLoad什么的)   复制代码 // Observe keyboard hide and show notification ...

  6. JavaScript的map循环、forEach循环、filter循环、reduce循环、reduceRight循环

    1.map循环 let arr=[1,2,3,4]; arr.map(function(value,key,arr){ //值,索引,数组(默认为选定数组) return item; //如果没有re ...

  7. Kafka 简单实验二(Python实现简单生产者消费者)

    Apache Kafka 是什么? Kafka 是一个开源的分布式流处理平台,其简化了不同数据系统的集成.流指的是一个数据管道,应用能够通过流不断地接收数据.Kafka 作为流处理系统主要有两个用处: ...

  8. 查看某一个开发者代码修改量的脚本(ios平台可用)

    #!/bin/sh # This is a script that help you get your team member's productivity # by analyzing his/he ...

  9. 自己定义modal动画

    在非常多场景中.我们都须要实现各种动画.这回我们来尝试搞一下控制器间跳转的modal动画. - (void)touchesBegan:(NSSet<UITouch *> *)touches ...

  10. 协程基础_context系列函数

    近期想看看协程,对这个的详细实现不太了解.查了下,协程最常规的做法就是基于makecontext,getcontext,swapcontext这类函数在用户空间切换用户上下文. 所以在这通过样例代码尽 ...