📄 contextmenu.cpp
字号:
// ContextMenu.cpp
#include "StdAfx.h"
#include "ContextMenu.h"
#include "Common/StringConvert.h"
#include "Common/MyCom.h"
#include "Windows/Shell.h"
#include "Windows/Memory.h"
#include "Windows/COM.h"
#include "Windows/FileFind.h"
#include "Windows/FileDir.h"
#include "Windows/FileName.h"
#include "Windows/Thread.h"
#include "Windows/Window.h"
#include "Windows/Menu.h"
#include "Windows/ResourceString.h"
#include "../FileManager/FormatUtils.h"
#include "../FileManager/ProgramLocation.h"
#include "../Common/ZipRegistry.h"
#include "../Common/ArchiveName.h"
#ifdef LANG
#include "../FileManager/LangUtils.h"
#endif
#include "resource.h"
#include "ContextMenuFlags.h"
// #include "ExtractEngine.h"
// #include "TestEngine.h"
// #include "CompressEngine.h"
#include "MyMessages.h"
#include "../GUI/ExtractRes.h"
#include "../Common/CompressCall.h"
using namespace NWindows;
///////////////////////////////
// IShellExtInit
extern LONG g_DllRefCount;
CZipContextMenu::CZipContextMenu() { InterlockedIncrement(&g_DllRefCount); }
CZipContextMenu::~CZipContextMenu() { InterlockedDecrement(&g_DllRefCount); }
HRESULT CZipContextMenu::GetFileNames(LPDATAOBJECT dataObject, UStringVector &fileNames)
{
fileNames.Clear();
if(dataObject == NULL)
return E_FAIL;
FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
NCOM::CStgMedium stgMedium;
HRESULT result = dataObject->GetData(&fmte, &stgMedium);
if (result != S_OK)
return result;
stgMedium._mustBeReleased = true;
NShell::CDrop drop(false);
NMemory::CGlobalLock globalLock(stgMedium->hGlobal);
drop.Attach((HDROP)globalLock.GetPointer());
drop.QueryFileNames(fileNames);
return S_OK;
}
STDMETHODIMP CZipContextMenu::Initialize(LPCITEMIDLIST pidlFolder,
LPDATAOBJECT dataObject, HKEY /* hkeyProgID */)
{
// OutputDebugString(TEXT("::Initialize\r\n"));
_dropMode = false;
_dropPath.Empty();
if (pidlFolder != 0)
{
if (NShell::GetPathFromIDList(pidlFolder, _dropPath))
{
// OutputDebugString(path);
// OutputDebugString(TEXT("\r\n"));
NFile::NName::NormalizeDirPathPrefix(_dropPath);
_dropMode = !_dropPath.IsEmpty();
}
else
_dropPath.Empty();
}
/*
m_IsFolder = false;
if (pidlFolder == 0)
*/
// pidlFolder is NULL :(
return GetFileNames(dataObject, _fileNames);
}
STDMETHODIMP CZipContextMenu::InitContextMenu(const wchar_t * /* folder */,
const wchar_t **names, UINT32 numFiles)
{
_fileNames.Clear();
for (UINT32 i = 0; i < numFiles; i++)
_fileNames.Add(names[i]);
_dropMode = false;
return S_OK;
}
/////////////////////////////
// IContextMenu
static LPCWSTR kMainVerb = L"SevenZip";
/*
static LPCTSTR kOpenVerb = TEXT("SevenOpen");
static LPCTSTR kExtractVerb = TEXT("SevenExtract");
static LPCTSTR kExtractHereVerb = TEXT("SevenExtractHere");
static LPCTSTR kExtractToVerb = TEXT("SevenExtractTo");
static LPCTSTR kTestVerb = TEXT("SevenTest");
static LPCTSTR kCompressVerb = TEXT("SevenCompress");
static LPCTSTR kCompressToVerb = TEXT("SevenCompressTo");
static LPCTSTR kCompressEmailVerb = TEXT("SevenCompressEmail");
static LPCTSTR kCompressToEmailVerb = TEXT("SevenCompressToEmail");
*/
struct CContextMenuCommand
{
UINT32 flag;
CZipContextMenu::ECommandInternalID CommandInternalID;
LPCWSTR Verb;
UINT ResourceID;
UINT ResourceHelpID;
UINT32 LangID;
};
static CContextMenuCommand g_Commands[] =
{
{
NContextMenuFlags::kOpen,
CZipContextMenu::kOpen,
L"Open",
IDS_CONTEXT_OPEN,
IDS_CONTEXT_OPEN_HELP,
0x02000103
},
{
NContextMenuFlags::kExtract,
CZipContextMenu::kExtract,
L"Extract",
IDS_CONTEXT_EXTRACT,
IDS_CONTEXT_EXTRACT_HELP,
0x02000105
},
{
NContextMenuFlags::kExtractHere,
CZipContextMenu::kExtractHere,
L"ExtractHere",
IDS_CONTEXT_EXTRACT_HERE,
IDS_CONTEXT_EXTRACT_HERE_HELP,
0x0200010B
},
{
NContextMenuFlags::kExtractTo,
CZipContextMenu::kExtractTo,
L"ExtractTo",
IDS_CONTEXT_EXTRACT_TO,
IDS_CONTEXT_EXTRACT_TO_HELP,
0x0200010D
},
{
NContextMenuFlags::kTest,
CZipContextMenu::kTest,
L"Test",
IDS_CONTEXT_TEST,
IDS_CONTEXT_TEST_HELP,
0x02000109
},
{
NContextMenuFlags::kCompress,
CZipContextMenu::kCompress,
L"Compress",
IDS_CONTEXT_COMPRESS,
IDS_CONTEXT_COMPRESS_HELP,
0x02000107,
},
{
NContextMenuFlags::kCompressEmail,
CZipContextMenu::kCompressEmail,
L"CompressEmail",
IDS_CONTEXT_COMPRESS_EMAIL,
IDS_CONTEXT_COMPRESS_EMAIL_HELP,
0x02000111
},
{
NContextMenuFlags::kCompressTo7z,
CZipContextMenu::kCompressTo7z,
L"CompressTo7z",
IDS_CONTEXT_COMPRESS_TO,
IDS_CONTEXT_COMPRESS_TO_HELP,
0x0200010F
},
{
NContextMenuFlags::kCompressTo7zEmail,
CZipContextMenu::kCompressTo7zEmail,
L"CompressTo7zEmail",
IDS_CONTEXT_COMPRESS_TO_EMAIL,
IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP,
0x02000113
},
{
NContextMenuFlags::kCompressToZip,
CZipContextMenu::kCompressToZip,
L"CompressToZip",
IDS_CONTEXT_COMPRESS_TO,
IDS_CONTEXT_COMPRESS_TO_HELP,
0x0200010F
},
{
NContextMenuFlags::kCompressToZipEmail,
CZipContextMenu::kCompressToZipEmail,
L"CompressToZipEmail",
IDS_CONTEXT_COMPRESS_TO_EMAIL,
IDS_CONTEXT_COMPRESS_TO_EMAIL_HELP,
0x02000113
}
};
int FindCommand(CZipContextMenu::ECommandInternalID &id)
{
for (int i = 0; i < sizeof(g_Commands) / sizeof(g_Commands[0]); i++)
if (g_Commands[i].CommandInternalID == id)
return i;
return -1;
}
void CZipContextMenu::FillCommand(ECommandInternalID id,
UString &mainString, CCommandMapItem &commandMapItem)
{
int i = FindCommand(id);
if (i < 0)
return;
const CContextMenuCommand &command = g_Commands[i];
commandMapItem.CommandInternalID = command.CommandInternalID;
commandMapItem.Verb = (UString)kMainVerb + (UString)command.Verb;
commandMapItem.HelpString = LangString(command.ResourceHelpID, command.LangID + 1);
mainString = LangString(command.ResourceID, command.LangID);
}
static bool MyInsertMenu(CMenu &menu, int pos, UINT id, const UString &s)
{
CMenuItem menuItem;
menuItem.fType = MFT_STRING;
menuItem.fMask = MIIM_TYPE | MIIM_ID;
menuItem.wID = id;
menuItem.StringValue = s;
return menu.InsertItem(pos, true, menuItem);
}
static const wchar_t *kArcExts[] =
{
L"7z",
L"bz2",
L"gz",
L"rar",
L"zip"
};
static bool IsItArcExt(const UString &ext2)
{
UString ext = ext2;
ext.MakeLower();
for (int i = 0; i < sizeof(kArcExts) / sizeof(kArcExts[0]); i++)
if (ext.Compare(kArcExts[i]) == 0)
return true;
return false;
}
static UString GetSubFolderNameForExtract(const UString &archiveName)
{
int dotPos = archiveName.ReverseFind(L'.');
if (dotPos < 0)
return archiveName + UString(L"~");
const UString ext = archiveName.Mid(dotPos + 1);
UString res = archiveName.Left(dotPos);
res.TrimRight();
dotPos = res.ReverseFind(L'.');
if (dotPos > 0)
{
const UString ext2 = res.Mid(dotPos + 1);
if (ext.CompareNoCase(L"rar") == 0 &&
(ext2.CompareNoCase(L"part001") == 0 ||
ext2.CompareNoCase(L"part01") == 0 ||
ext2.CompareNoCase(L"part1") == 0) ||
IsItArcExt(ext2) && ext.CompareNoCase(L"001") == 0)
res = res.Left(dotPos);
res.TrimRight();
}
return res;
}
static UString GetReducedString(const UString &s)
{
const int kMaxSize = 64;
if (s.Length() < kMaxSize)
return s;
const int kFirstPartSize = kMaxSize / 2;
return s.Left(kFirstPartSize) + UString(L" ... ") + s.Right(kMaxSize - kFirstPartSize);
}
static UString GetQuotedString(const UString &s)
{
return UString(L'\"') + s + UString(L'\"');
}
static UString GetQuotedReducedString(const UString &s)
{
return GetQuotedString(GetReducedString(s));
}
static const wchar_t *kExtractExludeExtensions[] =
{
L"txt", L"htm", L"html", L"xml", L"xsd", L"xsl", L"xslt", L"asp", L"aspx", L"css", L"shtml",
L"bmp", L"gif", L"jpeg", L"jpg", L"png", L"tiff", L"ico",
L"3gp", L"avi", L"mov", L"mpeg", L"mpg", L"mpe", L"wmv",
L"aac", L"ape", L"fla", L"flac", L"la", L"mp3", L"m4a", L"mp4", L"ofr", L"ogg",
L"pac", L"ra", L"rm", L"rka", L"shn", L"swa", L"tta", L"wv", L"wma", L"wav",
L"ps", L"eps",
L"inl", L"inc", L"idl", L"h", L"hpp", L"hxx", L"c", L"cpp", L"cxx", L"rc", L"java",
L"cs", L"pas", L"bas", L"vb", L"cls", L"ctl", L"frm", L"dlg", L"def",
L"f77", L"f", L"f90", L"f95",
L"asm", L"sql", L"manifest", L"dep",
L"mak", L"clw", L"csproj", L"vcproj", L"sln", L"dsp", L"dsw",
L"bat", L"cmd",
L"awk", L"sed", L"hta", L"js", L"php", L"php3", L"php4", L"php5",
L"phptml", L"pl", L"pm", L"py", L"pyo", L"rb", L"sh", L"tcl", L"vbs",
L"tex", L"ans", L"asc", L"srt", L"reg", L"ini", L"rtf", L"pdf"
};
static bool DoNeedExtract(const UString &name)
{
int extPos = name.ReverseFind('.');
if (extPos < 0)
return true;
UString ext = name.Mid(extPos + 1);
ext.MakeLower();
for (int i = 0; i < sizeof(kExtractExludeExtensions) / sizeof(kExtractExludeExtensions[0]); i++)
if (ext.Compare(kExtractExludeExtensions[i]) == 0)
return false;
return true;
}
STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
UINT commandIDFirst, UINT commandIDLast, UINT flags)
{
LoadLangOneTime();
if(_fileNames.Size() == 0)
return E_FAIL;
UINT currentCommandID = commandIDFirst;
if ((flags & 0x000F) != CMF_NORMAL &&
(flags & CMF_VERBSONLY) == 0 &&
(flags & CMF_EXPLORE) == 0)
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID);
_commandMap.Clear();
CMenu popupMenu;
CMenuDestroyer menuDestroyer;
bool cascadedMenu = ReadCascadedMenu();
MENUITEMINFO menuItem;
UINT subIndex = indexMenu;
if (cascadedMenu)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -