Loading...
墨滴

我只想

2021/07/01  阅读:40  主题:极简黑

windows之shell扩展

windows之shell扩展

本编文章总结下windows之shell扩展的简单开发,开发环境使用的是vs2013

项目创建

  • 创建ATL项目
  • 选择以下选项
  • 生成以下项目

主要使用ATLProject1项目,ATLProject1Ps可不去管他,编译的时候也只要编译ATLProject1

添加右键菜单扩展

  • 添加ATL简单对象
  • 生成以下两个文件
  • 在sample.h中添加右键菜单类
  • 代码如下
// sample.h : Csample 的声明

#pragma once
#include "resource.h"       // 主符号



#include "ATLProject1_i.h"
#include <ShObjIdl.h>
#include <string>
#include <vector>
#include <set>


#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Windows CE 平台(如不提供完全 DCOM 支持的 Windows Mobile 平台)上无法正确支持单线程 COM 对象。定义 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可强制 ATL 支持创建单线程 COM 对象实现并允许使用其单线程 COM 对象实现。rgs 文件中的线程模型已被设置为“Free”,原因是该模型是非 DCOM Windows CE 平台支持的唯一线程模型。"
#endif

using namespace ATL;


// Csample

class ATL_NO_VTABLE Csample :
 public CComObjectRootEx<CComSingleThreadModel>,
 public CComCoClass<Csample, &CLSID_sample>,
 public IDispatchImpl<Isample, &IID_Isample, &LIBID_ATLProject1Lib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
 public IShellExtInit,
 public IContextMenu
{
public:
 Csample()
 {
 }

DECLARE_REGISTRY_RESOURCEID(IDR_SAMPLE)


BEGIN_COM_MAP(Csample)
 COM_INTERFACE_ENTRY(Isample)
 COM_INTERFACE_ENTRY(IDispatch)
 COM_INTERFACE_ENTRY(IShellExtInit)
 COM_INTERFACE_ENTRY(IContextMenu)
END_COM_MAP()



 DECLARE_PROTECT_FINAL_CONSTRUCT()

 HRESULT FinalConstruct()
 {
  return S_OK;
 }

 void FinalRelease()
 {
 }

public:
 STDMETHODIMP Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY);
 virtual HRESULT STDMETHODCALLTYPE QueryContextMenu(
  _In_  HMENU hmenu,
  _In_  UINT indexMenu,
  _In_  UINT idCmdFirst,
  _In_  UINT idCmdLast,
  _In_  UINT uFlags);

 virtual HRESULT STDMETHODCALLTYPE InvokeCommand(
  _In_  CMINVOKECOMMANDINFO* pici);

 virtual 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);

};

OBJECT_ENTRY_AUTO(__uuidof(sample), Csample)

  • sample.cpp代码如下
// sample.cpp : Csample 的实现

#include "stdafx.h"
#include "sample.h"


#include "resource.h"
#include <windows.h>
#include <fstream>

extern HINSTANCE h;
// CCloudAppShellExt
STDMETHODIMP Csample::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hProgID) {

 FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
 STGMEDIUM stg = { TYMED_HGLOBAL };
 HDROP  hDrop;

 // 在数据对象内查找CF_HDROP类型数据。
 // 如果没有数据,返回一个错误(“无效参数”)给Explorer。
 if (FAILED(pDataObj->GetData(&fmt, &stg))) {
  return E_INVALIDARG;
 }

 // 取得指向实际数据的指针。
 hDrop = (HDROP)GlobalLock(stg.hGlobal);
 // 确保非NULL
 if (NULL == hDrop) {
  return E_INVALIDARG;
 }
 // 有效性检查,至少有一个文件名
 UINT uNumFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
 HRESULT hr = S_OK;

 // 有效性检查,至少有一个文件名
 GlobalUnlock(stg.hGlobal);
 ReleaseStgMedium(&stg);
 return hr;
}

HRESULT STDMETHODCALLTYPE Csample::QueryContextMenu(
 _In_  HMENU hmenu,
 _In_  UINT indexMenu,
 _In_  UINT idCmdFirst,
 _In_  UINT idCmdLast,
 _In_  UINT uFlags) {
 // 如果标识包含了 CMF_DEFAULTONLY
 if (uFlags & CMF_DEFAULTONLY) {
  return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0);
 }
 InsertMenu(hmenu, indexMenu, MF_BYPOSITION, idCmdFirst, _T("添加到云应用"));
 InsertMenu(hmenu, indexMenu, MF_BYPOSITION, idCmdFirst + 1, _T("取消添加到云应用"));
 return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 2);
}


HRESULT STDMETHODCALLTYPE Csample::InvokeCommand(
 _In_  CMINVOKECOMMANDINFO* pici) {
 // 如果 lpVerb 指向一个实际串,忽略此次调用并退出
 if (0 != HIWORD(pici->lpVerb)) {
  return E_INVALIDARG;
 }

 // 取得命令索引
 switch (LOWORD(pici->lpVerb)) {
 case 0: {

  DWORD num = 0;
  TCHAR szMsg[MAX_PATH + 32];
  wsprintf(szMsg, _T("云应用配置成功,加入的路径有:%d个"), num);
  MessageBox(pici->hwnd, szMsg, _T("锐捷云应用"), MB_ICONINFORMATION);
  return S_OK;
 }
 case 1: {
  DWORD num = 1;
  TCHAR szMsg[MAX_PATH + 32];
  wsprintf(szMsg, _T("取消云应用配置成功,取消的路径有:%d个"), num);
  MessageBox(pici->hwnd, szMsg, _T("锐捷云应用"), MB_ICONINFORMATION);

  return S_OK;
 }
   break;
 default:
  return E_INVALIDARG;
  break;
 }
}

HRESULT STDMETHODCALLTYPE Csample::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;

 // 由于这里只有一个菜单项,所以idCmd 必须为0
 if (0 != idCmd) {
  return E_INVALIDARG;
 }

 // 如果Explorer请求提示信息,拷贝串到提供的缓冲区
 if (uType & GCS_HELPTEXT) {
  LPCTSTR szText = _T("简单的SHEEL扩展帮助(fly-by help)");

  if (uType & GCS_UNICODE) {
   // 这里,需要把 pszName 转换为 UNICODE
   lstrcpynW((LPWSTR)pszName, T2CW(szText), cchMax);

  }
  else {
   // ANSI版本
   lstrcpynA(pszName, T2CA(szText), cchMax);
  }
  return S_OK;
 }

 return E_INVALIDARG;
}
  • 整体编译项目

  • 编写rgs文件注册特定后缀名的右键菜单这里注册".exe"和".lnk"

结束

欢迎关注公众号zzktkj_8888,获取完整代码。

- END -

我只想

2021/07/01  阅读:40  主题:极简黑

作者介绍

我只想