Explorer文件菜单添加

来源:互联网 发布:德国 知乎 编辑:程序博客网 时间:2024/06/05 00:53

这是一个用来添加Explorer文件右键菜单的小工具,支持插件,这样就能减少在COM上打转的时间,将时间真正放到功能的实现上。

如下图显示的菜单,其中打开cmd是用插件加入的。

 

系统提一个头文件和lib文件,按照这个实现这些即可在菜单中添加命令。

简单的接口定义文件

 

#pragma once
#include 
<Windows.h>

#define MAX_DESCRIPTION_SIZE 256

//一个菜单所需要的所有基本数据,这是系统会提供的一个接口,在需要相关数据的时候从这里获取
class IMenuObjectData
{
public:
    
enum FileType {
        File 
= 0x1,
        Directory 
= 0x2,
        None 
= 0x0
    };
    
virtual HWND GetHwnd() = 0;//取得explorer窗口句柄
    virtual UINT GetFileCount() = 0;//取得在弹出菜单时选中的文件个数
    virtual const TCHAR* GetFileName(int index) = 0;//文件名及类型
    virtual FileType GetFileType(int index) = 0;
    
virtual BOOL IsInExplorer() = 0;//是否在Explorer右边窗口弹出(即非左边的数状目录)
};

//这是插件需要实现的接口
class IMenuControl
{
public:
    
virtual ~IMenuControl() = 0 {}
    
virtual void SetMenuObjectData(IMenuObjectData*= 0;//一开始
    virtual UINT GetMenuCount() = 0;//告诉系统你将要几个命令菜单项(Explorer的右键菜单)
    virtual UINT InitMenu(HMENU hMenu, UINT uIndex, UINT uID) = 0;//初始化这个菜单
    virtual UINT GetSubMenuCount() = 0;//告诉系统你将要几个子菜单(扩展工具的子菜单)
    virtual UINT InitSubMenu(HMENU hMenu, UINT uIndex, UINT uID) = 0;//返回增加了菜单之后的index
    virtual BOOL Invoke(UINT uID) = 0;//命令被调用
    virtual BOOL GetCmdDescription(UINT uID, TCHAR* pszDesc) = 0;//需要被显示命令的tip
};

//IMenuControl* 
typedef IMenuControl* (__stdcall* fnGetMenuControl)(void);//从插件中取得IMenuControl接口的方法
typedef void (__stdcall* fnReleaseMenuControl)(IMenuControl*);//告诉插件释放这个接口

void RegisterMenuControl(fnGetMenuControl, fnReleaseMenuControl);//插件将自己的这两个函数注册给系统

注释中已经很详细的说明了使用方法,下面是打开cmd这个菜单的插件的实现样例。

 

// CmdTools.cpp : Defines the entry point for the DLL application.
//

#include 
"stdafx.h"
#include 
"../ExternTools/ExternToolsDef.h"
#include 
<string>

using namespace std;
class CMyMenuControl : public IMenuControl
{
public:
    CMyMenuControl() : m_pMenuData(
0), m_uID(0) {}
    
virtual void SetMenuObjectData(IMenuObjectData* pMenuData) { m_pMenuData = pMenuData; }
    
virtual UINT GetMenuCount() { return 0; }
    
virtual UINT InitMenu(HMENU hMenu, UINT uIndex, UINT uID) { return 0; }
    
virtual UINT GetSubMenuCount();
    
virtual UINT InitSubMenu(HMENU hMenu, UINT uIndex, UINT uID);
    
virtual BOOL Invoke(UINT uID);
    
virtual BOOL GetCmdDescription(UINT uID, TCHAR* pszDesc);
private:
    IMenuObjectData
* m_pMenuData;
    UINT m_uID;
};

IMenuControl
* __stdcall GetMenuControl()
{
    
return new CMyMenuControl();
}

void __stdcall ReleaseMenuControl(IMenuControl* pControl)
{
    delete pControl;
}

BOOL APIENTRY DllMain( HANDLE hModule, 
                      DWORD  ul_reason_for_call, 
                      LPVOID lpReserved
                      )
{
    
if(ul_reason_for_call == DLL_PROCESS_ATTACH)
    {
        RegisterMenuControl(GetMenuControl, ReleaseMenuControl);
    }
    
return TRUE;
}

UINT CMyMenuControl::GetSubMenuCount()
{
    
return 1;
}
UINT CMyMenuControl::InitSubMenu(HMENU hMenu, UINT uIndex, UINT uID)
{
    m_uID 
= uID;
    InsertMenu(hMenu, uIndex, MF_STRING 
| MF_BYPOSITION, uID, "打开cmd(&C)");
    
return uIndex + 1;
}
BOOL CMyMenuControl::Invoke(UINT uID)
{
    
if(uID == m_uID)
    {
        
if(m_pMenuData)
        {
            std::
string str(m_pMenuData->GetFileName(0));
            
if(m_pMenuData->IsInExplorer())
            {
                
string::size_type pos = str.find_last_of('/');
                
if(pos != string::npos)
                {
                    str 
= str.substr(0, pos);
                    
if(str.size() < 3) str += "/";
                }
            }
            STARTUPINFO si;
            si.cb 
= sizeof(si);
            GetStartupInfo(
&si);
            PROCESS_INFORMATION pi;
            
if(::CreateProcess(0"cmd.exe"00, FALSE, 00, str.c_str(), &si, &pi))
            {
                ::CloseHandle(pi.hThread);
                ::CloseHandle(pi.hProcess);
            }
        }
        
return TRUE;
    }
    
return FALSE;
}

BOOL CMyMenuControl::GetCmdDescription(UINT uID, TCHAR
* pszDesc)
{
    
if(uID == m_uID)
    {
        
static TCHAR szDesc[] = "当前目录下打开命令提示符";
        memcpy(pszDesc, szDesc, 
sizeof(szDesc));
        
return TRUE;
    }
    
return FALSE;
}

将插件放在注册表中

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE/SOFTWARE/ExternTools/dlls]
"cmdtool"="E://Develop//CmdTools//Debug//CmdTools.dll"

这样就可以了。

不知道怎么上载源文件,有兴趣的可以Email给我,共同研究

原创粉丝点击