Changeset e8d7c96d50b5…
Parent 7b0b3f373832…
by
Changes to 5 files · Browse files at e8d7c96d50b5 Showing diff from parent 7b0b3f373832 Diff from another changeset...
|
|
@@ -0,0 +1,180 @@ + #include "stdafx.h"
+#include "TortoiseUtils.h"
+
+#include "CShellExtDnd.h"
+
+
+// According to http://msdn.microsoft.com/en-us/library/bb776094%28VS.85%29.aspx
+// the help texts for the commands should be reasonably short (under 40 characters)
+
+static MenuDescription CDndMenuDescList[] =
+{
+ {"drag_move", L"Hg Move versioned item(s) here",
+ L"", "hg.ico", 0},
+ {"drag_copy", L"Hg Copy versioned item(s) here",
+ L"", "hg.ico", 0},
+ /* Add new items here */
+
+ // template
+ //{"", L"", L"", ".ico", 0},
+};
+
+
+static const char* const DropMenu =
+ "drag_move drag_copy"
+;
+
+static MenuDescriptionMap CDndMenuDescMap;
+
+MenuDescriptionMap& CShellExtDnd::GetMenuDescriptionMap()
+{
+ return CDndMenuDescMap;
+}
+
+#define ResultFromShort(i) ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, 0, (USHORT)(i)))
+
+// IContextMenu
+STDMETHODIMP
+CShellExtDnd::QueryContextMenu(
+ HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
+{
+ TDEBUG_TRACE("CShellExtDnd::QueryContextMenu");
+
+ if ((uFlags & CMF_DEFAULTONLY)!=0)
+ return S_OK; //we don't change the default action
+
+ if (((uFlags & 0x000f)!=CMF_NORMAL)&&(!(uFlags & CMF_EXPLORE))&&(!(uFlags & CMF_VERBSONLY)))
+ return S_OK;
+
+
+ UINT idCmd = idCmdFirst;
+
+ InitMenuMaps(CDndMenuDescList, sizeof(CDndMenuDescList) / sizeof(MenuDescription));
+
+ typedef std::vector<std::string> entriesT;
+ typedef entriesT::const_iterator entriesIter;
+
+ const char* entries_string = DropMenu;
+ entriesT entries;
+ Tokenize(entries_string, entries, " ");
+
+ for (entriesIter i = entries.begin(); i != entries.end(); i++)
+ {
+ std::string name = *i;
+ InsertMenuItemByName(
+ hMenu, name, indexMenu++,
+ idCmd++, idCmdFirst, L""
+ );
+ }
+
+ // separator
+ if (idCmd != idCmdFirst)
+ InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL);
+
+ TweakMenuForVista(hMenu);
+
+ return ResultFromShort(idCmd - idCmdFirst);
+}
+
+
+void CShellExtDnd::RunDialog(const std::string &cmd)
+{
+ if (cmd == "drag_move" || cmd == "drag_copy") {
+ //Append the current directory as the dest
+ myFiles.push_back(myFolder);
+ }
+ CShellExtCMenu::RunDialog(cmd);
+}
+
+
+STDMETHODIMP CShellExtDnd::Initialize(
+ LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj, HKEY hRegKey)
+{
+ TCHAR name[MAX_PATH+1];
+
+ PrintDebugHeader(pIDFolder, pDataObj);
+
+ myFolder.clear();
+ myFiles.clear();
+
+ // if a directory background
+ if (pIDFolder)
+ {
+ SHGetPathFromIDList(pIDFolder, name);
+ TDEBUG_TRACE(" Folder " << name);
+ myFolder = name;
+ }
+
+ std::string root;
+
+ //short circuit if we're dragging into a non-Hg repository
+ if (myFolder.empty() || (root = GetHgRepoRoot(myFolder)).empty())
+ {
+ TDEBUG_TRACE(" drag into a non-Hg repos directory");
+ return E_FAIL;
+ }
+
+ if (pDataObj)
+ {
+ FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ STGMEDIUM stg = { TYMED_HGLOBAL };
+ if (SUCCEEDED(pDataObj->GetData(&fmt, &stg)) && stg.hGlobal)
+ {
+ HDROP hDrop = (HDROP) GlobalLock(stg.hGlobal);
+
+ if (hDrop)
+ {
+ UINT uNumFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
+ TDEBUG_TRACE(" hDrop uNumFiles = " << uNumFiles);
+ for (UINT i = 0; i < uNumFiles; ++i) {
+ if (DragQueryFile(hDrop, i, name, MAX_PATH) > 0)
+ {
+ TDEBUG_TRACE(" DragQueryFile [" << i << "] = " << name);
+ if (GetHgRepoRoot(name) != root)
+ {
+ TDEBUG_TRACE(" " << name << " isn't in target dir repository");
+ myFiles.clear();
+ break;
+ }
+ myFiles.push_back(name);
+ }
+ }
+ }
+ else
+ {
+ TDEBUG_TRACE(" hDrop is NULL ");
+ }
+
+ GlobalUnlock(stg.hGlobal);
+ if (stg.pUnkForRelease)
+ {
+ IUnknown* relInterface = (IUnknown*) stg.pUnkForRelease;
+ relInterface->Release();
+ }
+ }
+ else
+ {
+ TDEBUG_TRACE(" pDataObj->GetData failed");
+ }
+ }
+
+ // disable context menu if neither the folder nor the files
+ // have been found
+ if (myFiles.empty()) {
+ TDEBUG_TRACE(" shell extension not available on this object");
+ return E_FAIL;
+ } else {
+ return S_OK;
+ }
+}
+
+
+CShellExtDnd::CShellExtDnd(const char dummy) :
+ CShellExtCMenu(dummy)
+{
+}
+
+
+CShellExtDnd::~CShellExtDnd()
+{
+}
|
|
@@ -0,0 +1,30 @@ + #ifndef _CShellExtDnd_h_
+#define _CShellExtDnd_h_
+
+#include "CShellExtCMenu.h"
+
+
+//CShellExtCMenu implements IContextMenu3, IShellExtInit
+class CShellExtDnd: public CShellExtCMenu
+{
+
+protected:
+ virtual void RunDialog(const std::string&);
+ virtual MenuDescriptionMap& GetMenuDescriptionMap();
+
+public:
+ explicit CShellExtDnd(const char dummy);
+ ~CShellExtDnd();
+
+ // IContextMenu3
+ STDMETHODIMP QueryContextMenu(
+ HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast,
+ UINT uFlags);
+
+ // IShellExtInit
+ STDMETHODIMP Initialize(
+ LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj, HKEY hKeyID);
+};
+
+
+#endif
|
@@ -9,6 +9,7 @@ OBJECTS_THGSGELL = $(OBJECTS_DIRSTATE) \
InitStatus.obj \
CShellExtCMenu.obj \
+ CShellExtDnd.obj \
CShellExtOverlay.obj \
TortoiseIconBitmap.obj \
IconBitmapUtils.obj \
|
@@ -5,6 +5,7 @@ #include "InitStatus.h"
#include "ThgClassFactory.h"
#include "CShellExtCMenu.h"
+#include "CShellExtDnd.h"
#include "CShellExtOverlay.h"
#include "ThgCLSIDs.h"
@@ -13,6 +14,7 @@#define TOLSTR2(x) TOLSTR(x)
#define CLSID_TortoiseHgCmenu TOLSTR2(THG_CLSID_TortoiseHgCmenu)
+#define CLSID_TortoiseHgDropHandler TOLSTR2(THG_CLSID_TortoiseHgDropHandler)
#define CLSID_TortoiseHgNormal TOLSTR2(THG_CLSID_TortoiseHgNormal)
#define CLSID_TortoiseHgAdded TOLSTR2(THG_CLSID_TortoiseHgAdded)
#define CLSID_TortoiseHgModified TOLSTR2(THG_CLSID_TortoiseHgModified)
@@ -88,6 +90,7 @@
typedef ThgClassFactory<CShellExtOverlay> FactOvl;
typedef ThgClassFactory<CShellExtCMenu> FactCmenu;
+ typedef ThgClassFactory<CShellExtDnd> FactDnd;
if (clsid == CLSID_TortoiseHgCmenu)
{
@@ -95,6 +98,12 @@ TDEBUG_TRACE("DllGetClassObject clsname = " << "CLSID_TortoiseHgCmenu");
return pcf->QueryInterface(riid, ppvOut);
}
+ else if (clsid == CLSID_TortoiseHgDropHandler)
+ {
+ FactDnd *pcf = new FactDnd(0);
+ TDEBUG_TRACE("DllGetClassObject clsname = " << "CLSID_TortoiseHgDropHandler");
+ return pcf->QueryInterface(riid, ppvOut);
+ }
else if (clsid == CLSID_TortoiseHgNormal)
{
FactOvl *pcf = new FactOvl('C'); // clean
|
@@ -2,9 +2,11 @@ #define _THGCLSID_H_
#define THG_CLSID_TortoiseHgCmenu {46605027-5B8C-4DCE-BFE0-051B7972D64C}
+#define THG_CLSID_TortoiseHgDropHandler {CEBD95BE-B733-415F-82A8-673D9158466E}
#define THG_CLSID_TortoiseHgNormal {869C8877-2C3C-438D-844B-31B86BFE5E8A}
#define THG_CLSID_TortoiseHgAdded {AF42ADAB-8C2E-4285-B746-99B31094708E}
#define THG_CLSID_TortoiseHgModified {CDA1C89D-E9B5-4981-A857-82DD932EA2FD}
#define THG_CLSID_TortoiseHgUnversioned {9E3D4EC9-0624-4393-8B48-204C217ED1FF}
+
#endif
|
Loading...