Index: src/ch/CfgProperties.cpp =================================================================== diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -r0373359eff650e8cf04a5992711ef9f20347536f --- src/ch/CfgProperties.cpp (.../CfgProperties.cpp) (revision d5c3edd0d167db9b5d47d04248820fda49499a5e) +++ src/ch/CfgProperties.cpp (.../CfgProperties.cpp) (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -84,8 +84,9 @@ pManager->register_bool(_t("Shell/Show 'Copy to,Move to special' command"), true); pManager->register_bool(_t("Shell/Show free space along with shortcut"), true); pManager->register_bool(_t("Shell/Show shell icons in shortcuts menu"), false); - pManager->register_bool(_t("Shell/Use drag&drop default menu item override"), true); - pManager->register_signed_num(_t("Shell/Default action when dragging"), 3, 0, 0xffffffff); + pManager->register_bool(_t("Shell/Intercept drag&drop"), true); + pManager->register_bool(_t("Shell/Intercept keyboard actions"), true); + pManager->register_bool(_t("Shell/Intercept context menu actions"), false); pManager->register_bool(_t("Buffer/Use only default buffer"), false); pManager->register_signed_num(_t("Buffer/Default buffer size"), 2097152, 1, 0xffffffff); Index: src/ch/CfgProperties.h =================================================================== diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -r0373359eff650e8cf04a5992711ef9f20347536f --- src/ch/CfgProperties.h (.../CfgProperties.h) (revision d5c3edd0d167db9b5d47d04248820fda49499a5e) +++ src/ch/CfgProperties.h (.../CfgProperties.h) (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -80,8 +80,9 @@ PP_SHSHOWCOPYMOVETO, PP_SHSHOWFREESPACE, PP_SHSHOWSHELLICONS, - PP_SHUSEDRAGDROP, - PP_SHDEFAULTACTION, + PP_SHINTERCEPTDRAGDROP, + PP_SHINTERCEPTKEYACTIONS, + PP_SHINTERCEPTCTXMENUACTIONS, PP_BFUSEONLYDEFAULT, PP_BFDEFAULT, Index: src/ch/MainWnd.cpp =================================================================== diff -u -rbfe720fda9529e7a77b4fb6410b4d4945b69188b -r0373359eff650e8cf04a5992711ef9f20347536f --- src/ch/MainWnd.cpp (.../MainWnd.cpp) (revision bfe720fda9529e7a77b4fb6410b4d4945b69188b) +++ src/ch/MainWnd.cpp (.../MainWnd.cpp) (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -380,15 +380,15 @@ // copying or moving ? bool bMove=false; - switch(pCopyDataStruct->dwData & OPERATION_MASK) + switch(pCopyDataStruct->dwData & CSharedConfigStruct::OPERATION_MASK) { - case DD_MOVE_FLAG: - case EC_MOVETO_FLAG: + case CSharedConfigStruct::DD_MOVE_FLAG: + case CSharedConfigStruct::EC_MOVETO_FLAG: bMove=true; break; - case EC_PASTE_FLAG: - case EC_PASTESPECIAL_FLAG: - bMove=(pCopyDataStruct->dwData & ~OPERATION_MASK) != 0; + case CSharedConfigStruct::EC_PASTE_FLAG: + case CSharedConfigStruct::EC_PASTESPECIAL_FLAG: + bMove=(pCopyDataStruct->dwData & ~CSharedConfigStruct::OPERATION_MASK) != 0; break; } @@ -429,11 +429,11 @@ BOOL bIgnoreDirs=FALSE; BOOL bForceDirectories=FALSE; unsigned char ucCopies=1; - switch(pCopyDataStruct->dwData & OPERATION_MASK) + switch(pCopyDataStruct->dwData & CSharedConfigStruct::OPERATION_MASK) { - case DD_COPYMOVESPECIAL_FLAG: - case EC_PASTESPECIAL_FLAG: - case EC_COPYMOVETOSPECIAL_FLAG: + case CSharedConfigStruct::DD_COPYMOVESPECIAL_FLAG: + case CSharedConfigStruct::EC_PASTESPECIAL_FLAG: + case CSharedConfigStruct::EC_COPYMOVETOSPECIAL_FLAG: CCustomCopyDlg dlg; dlg.m_ccData.m_astrPaths.Copy(astrFiles); dlg.m_ccData.m_iOperation=bMove ? 1 : 0; @@ -634,8 +634,9 @@ // experimental - doesn't work on all systems g_pscsShared->bShowShortcutIcons=rConfig.get_bool(PP_SHSHOWSHELLICONS); - g_pscsShared->bOverrideDefault=rConfig.get_bool(PP_SHUSEDRAGDROP); // only for d&d - g_pscsShared->uiDefaultAction=(UINT)rConfig.get_signed_num(PP_SHDEFAULTACTION); + g_pscsShared->uiFlags = (rConfig.get_bool(PP_SHINTERCEPTDRAGDROP) ? CSharedConfigStruct::eFlag_InterceptDragAndDrop : 0) | + (rConfig.get_bool(PP_SHINTERCEPTKEYACTIONS) ? CSharedConfigStruct::eFlag_InterceptKeyboardActions : 0) | + (rConfig.get_bool(PP_SHINTERCEPTCTXMENUACTIONS) ? CSharedConfigStruct::eFlag_InterceptCtxMenuActions : 0); // sizes for (int i=0;i<6;i++) @@ -651,45 +652,45 @@ { g_pscsShared->iCommandCount=3; g_pscsShared->iShortcutsCount=0; - g_pscsShared->uiFlags=(rConfig.get_bool(PP_SHSHOWCOPY) ? DD_COPY_FLAG : 0) - | (rConfig.get_bool(PP_SHSHOWMOVE) ? DD_MOVE_FLAG : 0) - | (rConfig.get_bool(PP_SHSHOWCOPYMOVE) ? DD_COPYMOVESPECIAL_FLAG : 0); + g_pscsShared->uiFlags |= (rConfig.get_bool(PP_SHSHOWCOPY) ? CSharedConfigStruct::DD_COPY_FLAG : 0) + | (rConfig.get_bool(PP_SHSHOWMOVE) ? CSharedConfigStruct::DD_MOVE_FLAG : 0) + | (rConfig.get_bool(PP_SHSHOWCOPYMOVE) ? CSharedConfigStruct::DD_COPYMOVESPECIAL_FLAG : 0); - pCommand[0].uiCommandID=DD_COPY_FLAG; + pCommand[0].uiCommandID=CSharedConfigStruct::DD_COPY_FLAG; GetResManager().LoadStringCopy(IDS_MENUCOPY_STRING, pCommand[0].szCommand, 128); GetResManager().LoadStringCopy(IDS_MENUTIPCOPY_STRING, pCommand[0].szDesc, 128); - pCommand[1].uiCommandID=DD_MOVE_FLAG; + pCommand[1].uiCommandID=CSharedConfigStruct::DD_MOVE_FLAG; GetResManager().LoadStringCopy(IDS_MENUMOVE_STRING, pCommand[1].szCommand, 128); GetResManager().LoadStringCopy(IDS_MENUTIPMOVE_STRING, pCommand[1].szDesc, 128); - pCommand[2].uiCommandID=DD_COPYMOVESPECIAL_FLAG; + pCommand[2].uiCommandID=CSharedConfigStruct::DD_COPYMOVESPECIAL_FLAG; GetResManager().LoadStringCopy(IDS_MENUCOPYMOVESPECIAL_STRING, pCommand[2].szCommand, 128); GetResManager().LoadStringCopy(IDS_MENUTIPCOPYMOVESPECIAL_STRING, pCommand[2].szDesc, 128); } break; case GC_EXPLORER: { g_pscsShared->iCommandCount=5; - g_pscsShared->uiFlags=(rConfig.get_bool(PP_SHSHOWPASTE) ? EC_PASTE_FLAG : 0) - | (rConfig.get_bool(PP_SHSHOWPASTESPECIAL) ? EC_PASTESPECIAL_FLAG : 0) - | (rConfig.get_bool(PP_SHSHOWCOPYTO) ? EC_COPYTO_FLAG : 0) - | (rConfig.get_bool(PP_SHSHOWMOVETO) ? EC_MOVETO_FLAG : 0) - | (rConfig.get_bool(PP_SHSHOWCOPYMOVETO) ? EC_COPYMOVETOSPECIAL_FLAG : 0); + g_pscsShared->uiFlags |= (rConfig.get_bool(PP_SHSHOWPASTE) ? CSharedConfigStruct::EC_PASTE_FLAG : 0) + | (rConfig.get_bool(PP_SHSHOWPASTESPECIAL) ? CSharedConfigStruct::EC_PASTESPECIAL_FLAG : 0) + | (rConfig.get_bool(PP_SHSHOWCOPYTO) ? CSharedConfigStruct::EC_COPYTO_FLAG : 0) + | (rConfig.get_bool(PP_SHSHOWMOVETO) ? CSharedConfigStruct::EC_MOVETO_FLAG : 0) + | (rConfig.get_bool(PP_SHSHOWCOPYMOVETO) ? CSharedConfigStruct::EC_COPYMOVETOSPECIAL_FLAG : 0); - pCommand[0].uiCommandID=EC_PASTE_FLAG; + pCommand[0].uiCommandID=CSharedConfigStruct::EC_PASTE_FLAG; GetResManager().LoadStringCopy(IDS_MENUPASTE_STRING, pCommand[0].szCommand, 128); GetResManager().LoadStringCopy(IDS_MENUTIPPASTE_STRING, pCommand[0].szDesc, 128); - pCommand[1].uiCommandID=EC_PASTESPECIAL_FLAG; + pCommand[1].uiCommandID=CSharedConfigStruct::EC_PASTESPECIAL_FLAG; GetResManager().LoadStringCopy(IDS_MENUPASTESPECIAL_STRING, pCommand[1].szCommand, 128); GetResManager().LoadStringCopy(IDS_MENUTIPPASTESPECIAL_STRING, pCommand[1].szDesc, 128); - pCommand[2].uiCommandID=EC_COPYTO_FLAG; + pCommand[2].uiCommandID=CSharedConfigStruct::EC_COPYTO_FLAG; GetResManager().LoadStringCopy(IDS_MENUCOPYTO_STRING, pCommand[2].szCommand, 128); GetResManager().LoadStringCopy(IDS_MENUTIPCOPYTO_STRING, pCommand[2].szDesc, 128); - pCommand[3].uiCommandID=EC_MOVETO_FLAG; + pCommand[3].uiCommandID=CSharedConfigStruct::EC_MOVETO_FLAG; GetResManager().LoadStringCopy(IDS_MENUMOVETO_STRING, pCommand[3].szCommand, 128); GetResManager().LoadStringCopy(IDS_MENUTIPMOVETO_STRING, pCommand[3].szDesc, 128); - pCommand[4].uiCommandID=EC_COPYMOVETOSPECIAL_FLAG; + pCommand[4].uiCommandID=CSharedConfigStruct::EC_COPYMOVETOSPECIAL_FLAG; GetResManager().LoadStringCopy(IDS_MENUCOPYMOVETOSPECIAL_STRING, pCommand[4].szCommand, 128); GetResManager().LoadStringCopy(IDS_MENUTIPCOPYMOVETOSPECIAL_STRING, pCommand[4].szDesc, 128); Index: src/ch/OptionsDlg.cpp =================================================================== diff -u -r449a5b399ab21ca0d06050b47b264f2f704af966 -r0373359eff650e8cf04a5992711ef9f20347536f --- src/ch/OptionsDlg.cpp (.../OptionsDlg.cpp) (revision 449a5b399ab21ca0d06050b47b264f2f704af966) +++ src/ch/OptionsDlg.cpp (.../OptionsDlg.cpp) (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -281,8 +281,9 @@ PROP_BOOL(IDS_CFGSHCMTOSPECIAL_STRING, GetConfig().get_bool(PP_SHSHOWCOPYMOVETO)) PROP_BOOL(IDS_CFGSHSHOWFREESPACE_STRING, GetConfig().get_bool(PP_SHSHOWFREESPACE)) PROP_BOOL(IDS_CFGSHSHOWICONS_STRING, GetConfig().get_bool(PP_SHSHOWSHELLICONS)) - PROP_BOOL(IDS_CFGSHOVERRIDEDRAG_STRING, GetConfig().get_bool(PP_SHUSEDRAGDROP)) - PROP_COMBO(IDS_CFGOVERRIDEDEFACTION_STRING, IDS_CFGACTIONS_STRING, GetConfig().get_signed_num(PP_SHDEFAULTACTION)); + PROP_BOOL(IDS_CFGSHINTERCEPTDRAG_STRING, GetConfig().get_bool(PP_SHINTERCEPTDRAGDROP)) + PROP_BOOL(IDS_CFGINTERCEPTKEYACTION_STRING, GetConfig().get_bool(PP_SHINTERCEPTKEYACTIONS)); + PROP_BOOL(IDS_CFGINTERCEPTCONTEXTMENU_STRING, GetConfig().get_bool(PP_SHINTERCEPTCTXMENUACTIONS)); PROP_SEPARATOR(IDS_PROCESSINGTHREAD_STRING) PROP_BOOL(IDS_AUTOCOPYREST_STRING, GetConfig().get_bool(PP_CMUSEAUTOCOMPLETEFILES)) @@ -396,8 +397,9 @@ rConfig.set_bool(PP_SHSHOWCOPYMOVETO, GetBoolProp(iPosition++)); rConfig.set_bool(PP_SHSHOWFREESPACE, GetBoolProp(iPosition++)); rConfig.set_bool(PP_SHSHOWSHELLICONS, GetBoolProp(iPosition++)); - rConfig.set_bool(PP_SHUSEDRAGDROP, GetBoolProp(iPosition++)); - rConfig.set_signed_num(PP_SHDEFAULTACTION, GetIndexProp(iPosition++)); + rConfig.set_bool(PP_SHINTERCEPTDRAGDROP, GetBoolProp(iPosition++)); + rConfig.set_bool(PP_SHINTERCEPTKEYACTIONS, GetBoolProp(iPosition++)); + rConfig.set_bool(PP_SHINTERCEPTCTXMENUACTIONS, GetBoolProp(iPosition++)); SKIP_SEPARATOR(iPosition) rConfig.set_bool(PP_CMUSEAUTOCOMPLETEFILES, GetBoolProp(iPosition++)); Index: src/ch/ch.rc =================================================================== diff -u -rf6706e71721e6828e4e3be894caec6808e27630b -r0373359eff650e8cf04a5992711ef9f20347536f --- src/ch/ch.rc (.../ch.rc) (revision f6706e71721e6828e4e3be894caec6808e27630b) +++ src/ch/ch.rc (.../ch.rc) (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -747,15 +747,15 @@ STRINGTABLE BEGIN IDS_CFGSHSHOWICONS_STRING "Show icons with shortcuts (experimental)" - IDS_CFGSHOVERRIDEDRAG_STRING - "Intercept drag&drop operation by left mouse button (experimental)" + IDS_CFGSHINTERCEPTDRAG_STRING + "Intercept drag&drop operations (experimental)" IDS_CFGSHORTCUTS_STRING "Shortcuts" IDS_CFGRECENT_STRING "Recently used paths" IDS_CFGSHELL_STRING "Shell" IDS_CFGSCCOUNT_STRING "Defined shortcuts' count" IDS_CFGRPCOUNT_STRING "Count of recent paths" - IDS_CFGOVERRIDEDEFACTION_STRING - "Default action for dragging by left mouse button" + IDS_CFGINTERCEPTKEYACTION_STRING "Intercept shell keyboard actions (experimental)" + IDS_CFGINTERCEPTCONTEXTMENU_STRING "Intercept standard Windows operations (experimental/not recommended)" IDS_CFGPRIORITYCLASS_STRING "Application's priority class" IDS_CFGDISABLEPRIORITYBOOST_STRING "Disable priority boosting" IDS_BOOLTEXT_STRING "No!Yes" @@ -1000,7 +1000,6 @@ BEGIN IDS_CFGFDSHORTCUTSSTYLES_STRING "Large icons!Small icons!List!Report" IDS_CFGPRIORITYCLASSITEMS_STRING "Idle!Normal!High!Real-time" - IDS_CFGACTIONS_STRING "Copy!Move!Special operation!Autodetect" IDS_PLUGSFOLDER_STRING "Folder with plugins" IDS_PLUGSFOLDERCHOOSE_STRING "!Choose folder with plugins" IDS_CFGLOGFILE_STRING "Main log file" Index: src/ch/resource.h =================================================================== diff -u -rf6706e71721e6828e4e3be894caec6808e27630b -r0373359eff650e8cf04a5992711ef9f20347536f --- src/ch/resource.h (.../resource.h) (revision f6706e71721e6828e4e3be894caec6808e27630b) +++ src/ch/resource.h (.../resource.h) (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -393,13 +393,13 @@ #define IDS_CFGSHCMTOSPECIAL_STRING 8062 #define IDS_CFGSHSHOWFREESPACE_STRING 8063 #define IDS_CFGSHSHOWICONS_STRING 8064 -#define IDS_CFGSHOVERRIDEDRAG_STRING 8065 +#define IDS_CFGSHINTERCEPTDRAG_STRING 8065 #define IDS_CFGSHORTCUTS_STRING 8066 #define IDS_CFGRECENT_STRING 8067 #define IDS_CFGSHELL_STRING 8068 #define IDS_CFGSCCOUNT_STRING 8069 #define IDS_CFGRPCOUNT_STRING 8070 -#define IDS_CFGOVERRIDEDEFACTION_STRING 8071 +#define IDS_CFGINTERCEPTKEYACTION_STRING 8071 #define IDS_CFGPRIORITYCLASS_STRING 8072 #define IDS_CFGDISABLEPRIORITYBOOST_STRING 8073 #define IDS_BOOLTEXT_STRING 8074 @@ -410,7 +410,6 @@ #define IDS_FORCESHUTDOWNVALUES_STRING 8079 #define IDS_CFGFDSHORTCUTSSTYLES_STRING 8080 #define IDS_CFGPRIORITYCLASSITEMS_STRING 8081 -#define IDS_CFGACTIONS_STRING 8082 #define IDS_PLUGSFOLDER_STRING 8083 #define IDS_PLUGSFOLDERCHOOSE_STRING 8084 #define IDS_CFGLOGFILE_STRING 8085 @@ -424,6 +423,7 @@ #define IDS_LANGUAGESFOLDER_STRING 8093 #define IDS_LANGSFOLDERCHOOSE_STRING 8094 #define IDS_ABOUT_LANGUAGE_STRING 8095 +#define IDS_CFGINTERCEPTCONTEXTMENU_STRING 8096 #define IDS_MENUCOPY_STRING 9000 #define IDS_MENUMOVE_STRING 9001 #define IDS_MENUCOPYMOVESPECIAL_STRING 9002 Index: src/chext/ActionSelector.cpp =================================================================== diff -u --- src/chext/ActionSelector.cpp (revision 0) +++ src/chext/ActionSelector.cpp (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -0,0 +1,221 @@ +// ============================================================================ +// Copyright (C) 2001-2008 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file ActionSelector.cpp +/// @brief Implementation of TActionSelector. +// ============================================================================ +#include "stdafx.h" +#include "ActionSelector.h" + +// ============================================================================ +/// TActionSelector::TActionSelector +/// @date 2009/03/12 +/// +/// @brief Constructs the action selector object. +// ============================================================================ +TActionSelector::TActionSelector() : + m_ulKeysState(eKey_None), + m_ulPreferredDropEffect(0), + m_eDefaultOperation(eAction_None), + m_eDefaultMenuItem(eAction_None), + m_ulActionOptions(eOption_None) +{ +} + +// ============================================================================ +/// TActionSelector::~TActionSelector +/// @date 2009/03/12 +/// +/// @brief Destructs the action selection object. +// ============================================================================ +TActionSelector::~TActionSelector() +{ +} + +// ============================================================================ +/// TActionSelector::ResetState +/// @date 2009/03/12 +/// +/// @brief Resets the state contained in this class. +// ============================================================================ +void TActionSelector::ResetState() +{ + m_ulKeysState = eKey_None; + m_ulPreferredDropEffect = 0; + m_eDefaultOperation = eAction_None; + m_eDefaultMenuItem = eAction_None; + m_ulActionOptions = eOption_None; +} + +// ============================================================================ +/// TActionSelector::ReadKeysState +/// @date 2009/03/12 +/// +/// @brief Retrieves the keyboard state at a time of call. +// ============================================================================ +void TActionSelector::ReadKeyboardState() +{ + m_ulKeysState = ((GetKeyState(VK_SHIFT) & 0x80) ? eKey_Shift : 0) | + ((GetKeyState(VK_CONTROL) & 0x80) ? eKey_Ctrl : 0) | + ((GetKeyState(VK_MENU) & 0x80) ? eKey_Alt : 0); +} + +// ============================================================================ +/// TActionSelector::ReadStateFromDataObject +/// @date 2009/03/12 +/// +/// @brief Retrieves the state from data object. +/// @param[in] piDataObject Data object to retrieve the information from. +/// @param[in] pszDestinationPath Destination path for the operation (used with simple heuristics). +/// @return Result of the operation. +// ============================================================================ +HRESULT TActionSelector::ReadStateFromDataObject(IDataObject* piDataObject, PCTSTR pszDestinationPath) +{ + if(!piDataObject || !pszDestinationPath || pszDestinationPath[0] == _T('\0')) + return E_INVALIDARG; + + // try to retrieve the preferred drop effect from the input data object + UINT uiPreferredDropEffect = RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT); + if(!uiPreferredDropEffect) + return E_FAIL; + + FORMATETC fe = { (CLIPFORMAT)uiPreferredDropEffect, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + STGMEDIUM medium; + + // if the drop effect does not exist - just report it + m_ulPreferredDropEffect = 0; + HRESULT hResult = piDataObject->QueryGetData(&fe); + if(hResult == S_OK) + { + hResult = piDataObject->GetData(&fe, &medium); + if(SUCCEEDED(hResult) && !medium.hGlobal) + { + ReleaseStgMedium(&medium); + hResult = E_FAIL; + } + if(SUCCEEDED(hResult)) + { + // specify operation + DWORD* pdwData = (DWORD*)GlobalLock(medium.hGlobal); + if(pdwData) + { + m_ulPreferredDropEffect = *pdwData; + GlobalUnlock(medium.hGlobal); + } + else + hResult = E_FAIL; + ReleaseStgMedium(&medium); + } + } + + // now try to get into the CF_HDROP information and use a simple heuristic to determine operation + m_eDefaultOperation = eAction_None; + fe.cfFormat = CF_HDROP; + + // are the data available? + hResult = piDataObject->QueryGetData(&fe); + if(hResult != S_OK) + return S_FALSE; + + hResult = piDataObject->GetData(&fe, &medium); + if(SUCCEEDED(hResult) && !medium.hGlobal) + { + ReleaseStgMedium(&medium); + hResult = E_FAIL; + } + if(SUCCEEDED(hResult)) + { + // copy is the default + m_eDefaultOperation = eAction_Copy; + + // autodetecting - copy or move - check the last path + UINT uiCount = DragQueryFile((HDROP)medium.hGlobal, 0xffffffff, NULL, 0); + TCHAR szPath[_MAX_PATH]; + if(DragQueryFile((HDROP)medium.hGlobal, uiCount - 1, szPath, _MAX_PATH)) + { + // check if the path has some common elements with destination paths + if(_tcsncmp(szPath, _T("\\\\"), 2) == 0) + { + TCHAR* pFnd = _tcsstr(szPath+2, _T("\\")); + if(pFnd) + { + int iCount; + // find another + TCHAR *pSecond = _tcsstr(pFnd + 1, _T("\\")); + if(pSecond) + iCount = pSecond - szPath; + else + iCount = _tcslen(szPath); + + // found - compare + if(_tcsnicmp(szPath, pszDestinationPath, iCount) == 0) + m_eDefaultOperation = eAction_Move; + } + } + else if(pszDestinationPath[0] == szPath[0]) // when processing within the same disk drive - we move by default + m_eDefaultOperation = eAction_Move; + } + + ReleaseStgMedium(&medium); + } + + return hResult; +} + +// ============================================================================ +/// TActionSelector::ReadStateFromMenu +/// @date 2009/03/12 +/// +/// @brief Reads the state from menu handle. +/// @param[in] hMenu Handle to a menu containing basic items. +// ============================================================================ +void TActionSelector::ReadStateFromMenu(HMENU hMenu) +{ + // it's none by default + m_eDefaultMenuItem = eAction_None; + + _ASSERTE(hMenu != NULL); + if(!hMenu) + return; + + MENUITEMINFO mii; + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_STATE; + + if(::GetMenuItemInfo(hMenu, 1, FALSE, &mii) && mii.fState & MFS_DEFAULT) + m_eDefaultMenuItem = eAction_Copy; + if(::GetMenuItemInfo(hMenu, 2, FALSE, &mii) && mii.fState & MFS_DEFAULT) + m_eDefaultMenuItem = eAction_Move; + if(::GetMenuItemInfo(hMenu, 3, FALSE, &mii) && mii.fState & MFS_DEFAULT) + m_eDefaultMenuItem = eAction_Shortcut; +} + +// ============================================================================ +/// TActionSelector::GetActionSource +/// @date 2009/03/12 +/// +/// @brief Calculates the action source based on the state collected so far. +/// @return Combination of eSrc_* with eAction_* +// ============================================================================ +ulong_t TActionSelector::GetActionSource() +{ + unsigned long ulSrc = (m_ulPreferredDropEffect != 0) ? (m_ulKeysState != eKey_None ? eSrc_Keyboard : eSrc_CtxMenu) : eSrc_DropMenu; + unsigned long ulAction = m_eDefaultMenuItem != eAction_None ? m_eDefaultMenuItem : m_eDefaultOperation; + + return ulSrc | ulAction; +} Index: src/chext/ActionSelector.h =================================================================== diff -u --- src/chext/ActionSelector.h (revision 0) +++ src/chext/ActionSelector.h (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -0,0 +1,91 @@ +// ============================================================================ +// Copyright (C) 2001-2009 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +/// @file ActionSelector.h +/// @date 2009/03/12 +/// @brief Contains a class handling the action selection for drag&drop menu. +// ============================================================================ +#ifndef __ACTIONSELECTOR_H__ +#define __ACTIONSELECTOR_H__ + +class TActionSelector +{ +public: + /// State of the keyboard + enum EStateKeys + { + eKey_None = 0, + eKey_Ctrl = 1, + eKey_Alt = 2, + eKey_Shift = 4 + }; + + /// Default operation + enum EAction + { + eAction_None = 0x0000, + eAction_Copy = 0x0001, + eAction_Move = 0x0002, + eAction_Shortcut = 0x0004 + }; + + enum EActionSource + { + eSrc_None = 0x0000, + eSrc_CtxMenu = 0x0100, + eSrc_DropMenu = 0x0200, + eSrc_Keyboard = 0x0400, + }; + + enum EActionOptions + { + eOption_None = 0x0000, ///< No integration at all + eOption_BasicIntegration = 0x0001, ///< Basic integration (CH menu items, no override) + eOption_DragAndDropOverride = 0x0002, ///< Intercepts drag&drop operation using the left mouse button + eOption_KeyboardOverride = 0x0004 ///< Intercepts Ctrl+V operation + }; + +public: + TActionSelector(); + ~TActionSelector(); + + /// Reads current keyboard state + void ReadKeyboardState(); + /// Retrieves all informations available in IDataObject related to the action selection process + HRESULT ReadStateFromDataObject(IDataObject* piDataObject, PCTSTR pszDestinationPath); + /// Retrieves the state information from a menu handle + void ReadStateFromMenu(HMENU hMenu); + + /// Retrieves the action source using the + ulong_t GetActionSource(); + + /// Sets the action options (EActionOptions) + void SetActionOptions(ulong_t ulOptions) { m_ulActionOptions = ulOptions; } + + /// Resets all states + void ResetState(); + +protected: + ulong_t m_ulKeysState; ///< State of the ctrl/shift/alt keys + ulong_t m_ulPreferredDropEffect; ///< Preferred drop effect from IDataObject + EAction m_eDefaultOperation; ///< Default operation determined from IDataObject (detected with simple heuristics) + EAction m_eDefaultMenuItem; ///< Default operation retrieved using the menu handle + unsigned long m_ulActionOptions; ///< Options determining the final action to be performed +}; + +#endif Index: src/chext/DropMenuExt.cpp =================================================================== diff -u -rcd5a36f1507a4131ce652879565c0770b36dd953 -r0373359eff650e8cf04a5992711ef9f20347536f --- src/chext/DropMenuExt.cpp (.../DropMenuExt.cpp) (revision cd5a36f1507a4131ce652879565c0770b36dd953) +++ src/chext/DropMenuExt.cpp (.../DropMenuExt.cpp) (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -28,14 +28,10 @@ extern CSharedConfigStruct* g_pscsShared; -#define DE_COPY 0 -#define DE_MOVE 1 -#define DE_SPECIAL 2 -#define DE_AUTO 3 - CDropMenuExt::CDropMenuExt() : m_piShellExtControl(NULL) { + m_szDstPath[0] = _T('\0'); CoCreateInstance(CLSID_CShellExtControl, NULL, CLSCTX_ALL, IID_IShellExtControl, (void**)&m_piShellExtControl); } @@ -48,8 +44,68 @@ } } -STDMETHODIMP CDropMenuExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT /*uFlags*/) +HRESULT CDropMenuExt::ReadFileData(IDataObject* piDataObject) { + _ASSERTE(piDataObject); + if(!piDataObject) + return E_INVALIDARG; + + // retrieve some informations from the data object + STGMEDIUM medium; + FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; + + // retrieve the CF_HDROP-type data from data object + HRESULT hResult = piDataObject->QueryGetData(&fe); + if(hResult != S_OK) + return hResult; + hResult = piDataObject->GetData(&fe, &medium); + if(SUCCEEDED(hResult)) + GetDataFromClipboard(static_cast(medium.hGlobal), m_szDstPath, &m_bBuffer.m_pszFiles, &m_bBuffer.m_iDataSize); + + ReleaseStgMedium(&medium); + + return hResult; +} + +STDMETHODIMP CDropMenuExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject* piDataObject, HKEY /*hkeyProgID*/) +{ + ATLTRACE(_T("CDropMenuExt::Initialize()\n")); + if(!piDataObject) + return E_FAIL; + + // remember the keyboard state for later + m_asSelector.ResetState(); + m_asSelector.ReadKeyboardState(); + + // check if this extension is enabled + HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); + if(FAILED(hResult) || hResult == S_FALSE) + return hResult; + + // find window + HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + if(hWnd == NULL) + return E_FAIL; + + // retrieve config from CH + ::SendMessage(hWnd, WM_GETCONFIG, GC_DRAGDROP, 0); + + // get dest folder + m_szDstPath[0]=_T('\0'); + if(!SHGetPathFromIDList(pidlFolder, m_szDstPath)) + return E_FAIL; + + // now retrieve the preferred drop effect from IDataObject + hResult = m_asSelector.ReadStateFromDataObject(piDataObject, m_szDstPath); + if(SUCCEEDED(hResult)) + hResult = ReadFileData(piDataObject); + + return hResult; +} + +STDMETHODIMP CDropMenuExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT uFlags) +{ + ATLTRACE(_T("CDropMenuExt::QueryContextMenu()\n")); // check options HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); if(FAILED(hResult) || hResult == S_FALSE) @@ -58,73 +114,59 @@ // find CH's window HWND hWnd; hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if (hWnd) - { - // get state of keys - bool bShift=(GetKeyState(VK_SHIFT) & 0x80) != 0; - bool bCtrl=(GetKeyState(VK_CONTROL) & 0x80) != 0; - bool bAlt=(GetKeyState(VK_MENU) & 0x80) != 0; + if(!hWnd) + return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); -/* OTF2("CDropMenuExt::QueryContextMenu - uFlags=%lu (", uFlags); - if (uFlags & CMF_CANRENAME) - OTF2("CMF_CANRENAME "); - if (uFlags & CMF_DEFAULTONLY) - OTF2("CMF_DEFAULTONLY "); - if (uFlags & CMF_EXPLORE) - OTF2("CMF_EXPLORE "); - if (uFlags & CMF_EXTENDEDVERBS) - OTF2("CMF_EXTENDEDVERBS "); - if (uFlags & CMF_INCLUDESTATIC) - OTF2("CMF_INCLUDESTATIC "); - if (uFlags & CMF_NODEFAULT) - OTF2("CMF_NODEFAULT "); - if (uFlags & CMF_NORMAL) - OTF2("CMF_NORMAL "); - if (uFlags & CMF_NOVERBS) - OTF2("CMF_NOVERBS "); - if (uFlags & CMF_VERBSONLY) - OTF2("CMF_VERBSONLY "); - OTF2(")\r\n"); - OTF2("Keys State: Shift:%u, ctrl:%u, alt:%u\r\n", bShift, bCtrl, bAlt); -*/ - // got a config - _COMMAND* pCommand = g_pscsShared->GetCommandsPtr(); - int iCommandCount=0; + // retrieve the default menu item; if not available, fallback to the default heuristics + m_asSelector.ReadStateFromMenu(hmenu); - if (g_pscsShared->uiFlags & DD_COPY_FLAG) - { - ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+0, pCommand[0].szCommand); - if (g_pscsShared->bOverrideDefault) - ::SetMenuDefaultItem(hmenu, idCmdFirst+0, FALSE); - iCommandCount++; - } + // retrieve the action information to be performed + ulong_t ulActionSource = m_asSelector.GetActionSource(); - if (g_pscsShared->uiFlags & DD_MOVE_FLAG) - { - ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+1, pCommand[1].szCommand); - if (g_pscsShared->bOverrideDefault && (bShift || (m_uiDropEffect == DE_MOVE && (m_bExplorer || !bCtrl))) ) - ::SetMenuDefaultItem(hmenu, idCmdFirst+1, FALSE); - iCommandCount++; - } + // determine if we want to perform override based on user options and detected action source + bool bIntercept = (g_pscsShared->uiFlags & CSharedConfigStruct::eFlag_InterceptDragAndDrop && ulActionSource & TActionSelector::eSrc_DropMenu || + g_pscsShared->uiFlags & CSharedConfigStruct::eFlag_InterceptKeyboardActions && ulActionSource & TActionSelector::eSrc_Keyboard || + g_pscsShared->uiFlags & CSharedConfigStruct::eFlag_InterceptCtxMenuActions && ulActionSource & TActionSelector::eSrc_CtxMenu); - if (g_pscsShared->uiFlags & DD_COPYMOVESPECIAL_FLAG) - { - ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+2, pCommand[2].szCommand); - if (g_pscsShared->bOverrideDefault && (bAlt || (bCtrl && bShift) || m_uiDropEffect == DE_SPECIAL) && !(m_uiDropEffect == DE_MOVE)) - ::SetMenuDefaultItem(hmenu, idCmdFirst+2, FALSE); - iCommandCount++; - } - - if (iCommandCount) - { - ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_SEPARATOR, idCmdFirst+3, NULL); - iCommandCount++; - } + // now convert our information to the + // got a config + _COMMAND* pCommand = g_pscsShared->GetCommandsPtr(); + int iCommandCount=0; - return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 4); + // ad new menu items, depending on the received configuration + if(g_pscsShared->uiFlags & CSharedConfigStruct::DD_COPY_FLAG) + { + ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+0, pCommand[0].szCommand); + if(bIntercept && ulActionSource & TActionSelector::eAction_Copy) + ::SetMenuDefaultItem(hmenu, idCmdFirst+0, FALSE); + iCommandCount++; } - else - return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); + + if(g_pscsShared->uiFlags & CSharedConfigStruct::DD_MOVE_FLAG) + { + ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+1, pCommand[1].szCommand); + if(bIntercept && ulActionSource & TActionSelector::eAction_Move) + ::SetMenuDefaultItem(hmenu, idCmdFirst+1, FALSE); + iCommandCount++; + } + + if(g_pscsShared->uiFlags & CSharedConfigStruct::DD_COPYMOVESPECIAL_FLAG) + { + ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_STRING, idCmdFirst+2, pCommand[2].szCommand); +/* + if(g_pscsShared->bOverrideDefault && m_eDropEffect == eEffect_Special) + ::SetMenuDefaultItem(hmenu, idCmdFirst+2, FALSE); +*/ + iCommandCount++; + } + + if(iCommandCount) + { + ::InsertMenu(hmenu, indexMenu+iCommandCount, MF_BYPOSITION | MF_SEPARATOR, idCmdFirst+3, NULL); + iCommandCount++; + } + + return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 4); } STDMETHODIMP CDropMenuExt::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* /*pwReserved*/, LPSTR pszName, UINT cchMax) @@ -137,14 +179,14 @@ return hResult; } - if (uFlags == GCS_HELPTEXTW) + if(uFlags == GCS_HELPTEXTW) { USES_CONVERSION; // find CH's window HWND hWnd; hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if (hWnd) + if(hWnd) { _COMMAND* pCommand = g_pscsShared->GetCommandsPtr(); @@ -166,13 +208,13 @@ else wcsncpy(reinterpret_cast(pszName), L"", cchMax); } - if (uFlags == GCS_HELPTEXTA) + if(uFlags == GCS_HELPTEXTA) { // find CH's window HWND hWnd; hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if (hWnd) + if(hWnd) { _COMMAND* pCommand = g_pscsShared->GetCommandsPtr(); @@ -198,156 +240,16 @@ return S_OK; } -STDMETHODIMP CDropMenuExt::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT lpdobj, HKEY /*hkeyProgID*/) -{ -// OTF2("Initialize cdropmenuext\r\n"); - HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult) || hResult == S_FALSE) - return hResult; - - // find window - HWND hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if (hWnd == NULL) - return E_FAIL; - - // gets the config from CH - ::SendMessage(hWnd, WM_GETCONFIG, GC_DRAGDROP, 0); - -// OTF2("========================================================\r\n"); -// OTF2("Initialize drag&drop context menu handler pidlFolder=%lu, lpdobj=%lu\r\n", pidlFolder, lpdobj); - - // get dest folder - m_szDstPath[0]=_T('\0'); - if (!SHGetPathFromIDList(pidlFolder, m_szDstPath)) - return E_FAIL; - - // get data from IDataObject - files to copy/move - if (lpdobj) - { -// ReportAvailableFormats(lpdobj); - // file list - STGMEDIUM medium; - FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; - - HRESULT hr = lpdobj->GetData(&fe, &medium); - if (FAILED(hr)) - return E_FAIL; - - GetDataFromClipboard(static_cast(medium.hGlobal), m_szDstPath, &m_bBuffer.m_pszFiles, &m_bBuffer.m_iDataSize); - - // set std text - switch (g_pscsShared->uiDefaultAction) - { - case 1: - // move action - m_uiDropEffect=DE_MOVE; - break; - case 2: - // special operation - m_uiDropEffect=DE_SPECIAL; - break; - case 3: - { - // autodetecting - copy or move - check the last path - UINT uiCount=DragQueryFile((HDROP)medium.hGlobal, 0xffffffff, NULL, 0); - TCHAR szPath[_MAX_PATH]; - if (DragQueryFile((HDROP)medium.hGlobal, uiCount-1, szPath, _MAX_PATH)) - { - if (_tcsncmp(szPath, _T("\\\\"), 2) == 0) - { - TCHAR* pFnd=_tcsstr(szPath+2, _T("\\")); - - if (pFnd) - { - int iCount; - // find another - TCHAR *pSecond=_tcsstr(pFnd+1, _T("\\")); - if (pSecond) - { - iCount=pSecond-szPath; -// OTF2("Counted: %lu\r\n", iCount); - } - else - iCount=_tcslen(szPath); - - // found - compare -// OTF2("Compare %s and %s\r\n", szPath, m_szDstPath); - if (_tcsnicmp(szPath, m_szDstPath, iCount) == 0) - { -// OTF2("OP: MOVE\r\n"); - m_uiDropEffect=DE_MOVE; - } - else - { -// OTF2("OP: COPY\r\n"); - m_uiDropEffect=DE_COPY; - } - } - else - m_uiDropEffect=DE_COPY; - - } - else - { - // local path - check drive letter - if (m_szDstPath[0] == szPath[0]) - m_uiDropEffect=DE_MOVE; - else - m_uiDropEffect=DE_COPY; - } - } - else - m_uiDropEffect=DE_COPY; - } - break; - - default: - m_uiDropEffect=DE_COPY; // std copying - break; - } - - ReleaseStgMedium(&medium); - - // get operation type - UINT cf=RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT); - fe.cfFormat=(unsigned short)cf; - - // if explorer knows better - change effect - m_bExplorer=false; - hr=lpdobj->GetData(&fe, &medium); - if (SUCCEEDED(hr)) - { - // specify operation - LPVOID lpv=GlobalLock(medium.hGlobal); - if (lpv) - { - UINT uiDrop=*((DWORD*)lpv); - if (uiDrop & DROPEFFECT_MOVE) - m_uiDropEffect=DE_MOVE; - else - m_uiDropEffect=DE_COPY; - m_bExplorer=true; - -// OTF2("Detected operation %lu\r\n", m_uiDropEffect); - GlobalUnlock(medium.hGlobal); - } - - ReleaseStgMedium(&medium); - } - } - - return S_OK; -} - STDMETHODIMP CDropMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) { + ATLTRACE(_T("CDropMenuExt::InvokeCommand()\n")); HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); if(FAILED(hResult) || hResult == S_FALSE) return E_FAIL; // required to process other InvokeCommand handlers. // find window HWND hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if (hWnd == NULL) + if(hWnd == NULL) return E_FAIL; // commands @@ -365,4 +267,15 @@ m_bBuffer.Destroy(); return S_OK; -} \ No newline at end of file +} + +STDMETHODIMP CDropMenuExt::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + return HandleMenuMsg2(uMsg, wParam, lParam, NULL); +} + +STDMETHODIMP CDropMenuExt::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plResult) +{ + ATLTRACE(_T("CDropMenuExt::HandleMenuMsg2(): uMsg = %lu, wParam = %lu, lParam = %lu\n"), uMsg, wParam, lParam); + return S_FALSE; +} Index: src/chext/DropMenuExt.h =================================================================== diff -u -rcd5a36f1507a4131ce652879565c0770b36dd953 -r0373359eff650e8cf04a5992711ef9f20347536f --- src/chext/DropMenuExt.h (.../DropMenuExt.h) (revision cd5a36f1507a4131ce652879565c0770b36dd953) +++ src/chext/DropMenuExt.h (.../DropMenuExt.h) (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -20,14 +20,13 @@ #define __DROPMENUEXT_H_ #include "resource.h" // main symbols +#include "ActionSelector.h" ///////////////////////////////////////////////////////////////////////////// // CDropMenuExt class ATL_NO_VTABLE CDropMenuExt : public CComObjectRootEx, public CComCoClass, - public IObjectWithSiteImpl, - public IDispatchImpl, public IShellExtInit, public IContextMenu3 { @@ -41,31 +40,28 @@ DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CDropMenuExt) - COM_INTERFACE_ENTRY(IDropMenuExt) - COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IShellExtInit) COM_INTERFACE_ENTRY(IContextMenu) - COM_INTERFACE_ENTRY(IObjectWithSite) END_COM_MAP() -// IDropMenuExt public: STDMETHOD(InvokeCommand)(LPCMINVOKECOMMANDINFO lpici); - STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder, LPDATAOBJECT lpdobj, HKEY /*hkeyProgID*/); + STDMETHOD(Initialize)(LPCITEMIDLIST pidlFolder, IDataObject* piDataObject, HKEY /*hkeyProgID*/); STDMETHOD(GetCommandString)(UINT_PTR idCmd, UINT uFlags, UINT* /*pwReserved*/, LPSTR pszName, UINT cchMax); STDMETHOD(QueryContextMenu)(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT uFlags); - STDMETHOD(HandleMenuMsg)(UINT, WPARAM, LPARAM) - { - return S_FALSE; - } + STDMETHOD(HandleMenuMsg)(UINT uMsg, WPARAM wParam, LPARAM lParam); + STDMETHOD(HandleMenuMsg2)(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plResult); - STDMETHOD(HandleMenuMsg2)(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, LRESULT* /*plResult*/) - { - return S_FALSE; - } +protected: + HRESULT ReadFileData(IDataObject* piDataObject); protected: + TCHAR m_szDstPath[_MAX_PATH]; + + IShellExtControl* m_piShellExtControl; + TActionSelector m_asSelector; + class CBuffer { public: @@ -77,12 +73,6 @@ TCHAR *m_pszFiles; UINT m_iDataSize; } m_bBuffer; - - TCHAR m_szDstPath[_MAX_PATH]; - UINT m_uiDropEffect; - bool m_bExplorer; // if the operation has been retrieved from explorer or from the program - - IShellExtControl* m_piShellExtControl; }; #endif //__DROPMENUEXT_H_ Index: src/chext/MenuExt.cpp =================================================================== diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -r0373359eff650e8cf04a5992711ef9f20347536f --- src/chext/MenuExt.cpp (.../MenuExt.cpp) (revision d5c3edd0d167db9b5d47d04248820fda49499a5e) +++ src/chext/MenuExt.cpp (.../MenuExt.cpp) (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -62,126 +62,198 @@ } } -HRESULT CMenuExt::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) +STDMETHODIMP CMenuExt::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT lpdobj, HKEY /*hkeyProgID*/) { -// OTF("CMenuExt::HandleMenuMsg\r\n"); - return HandleMenuMsg2(uMsg, wParam, lParam, NULL); -} + ATLTRACE(_T("CMenuExt::Initialize()\n")); + // check options + HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); + if(FAILED(hResult) || hResult == S_FALSE) + return hResult; -HRESULT CMenuExt::HandleMenuMsg2(UINT uMsg, WPARAM /*wParam*/, LPARAM lParam, LRESULT* /*plResult*/) -{ - switch(uMsg) - { - case WM_INITMENUPOPUP: - { -// OTF("CMenuExt::HandleMenuMsg2 / Init menu popup\r\n"); - break; - } - - case WM_DRAWITEM: - { -// OTF("CMenuExt::HandleMenuMsg2 / Drawitem\r\n"); - LPDRAWITEMSTRUCT lpdis=(LPDRAWITEMSTRUCT) lParam; - DrawMenuItem(lpdis); - break; - } - - case WM_MEASUREITEM: - { -// OTF("CMenuExt::HandleMenuMsg2 / MeasureItem\r\n"); - LPMEASUREITEMSTRUCT lpmis=(LPMEASUREITEMSTRUCT)lParam; + // find ch window + HWND hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + if (hWnd == NULL) + return E_FAIL; - // establish display text - int iShortcutIndex=(lpmis->itemID-m_uiFirstID-5)%g_pscsShared->iShortcutsCount; - _SHORTCUT* pShortcuts = g_pscsShared->GetShortcutsPtr(); + // get cfg from ch + ::SendMessage(hWnd, WM_GETCONFIG, GC_EXPLORER, 0); - // measure the text - HWND hDesktop=GetDesktopWindow(); - HDC hDC=GetDC(hDesktop); + // read dest folder + m_szDstPath[0]=_T('\0'); - // get menu logfont - NONCLIENTMETRICS ncm; - ncm.cbSize=sizeof(NONCLIENTMETRICS); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0); + // get data from IDataObject - files to copy/move + bool bPathFound=false; + m_bGroupFiles=false; + if (lpdobj) + { + STGMEDIUM medium; + FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; - HFONT hFont=CreateFontIndirect(&ncm.lfMenuFont); - HFONT hOldFont=(HFONT)SelectObject(hDC, hFont); + HRESULT hr = lpdobj->GetData(&fe, &medium); + if (FAILED(hr)) + return E_FAIL; - // calc text size - SIZE size; - GetTextExtentPoint32(hDC, pShortcuts[iShortcutIndex].szName, (int)_tcslen(pShortcuts[iShortcutIndex].szName), &size); + // copy all filenames to a table + GetDataFromClipboard(static_cast(medium.hGlobal), NULL, &m_bBuffer.m_pszFiles, &m_bBuffer.m_iDataSize); - // restore old settings - SelectObject(hDC, hOldFont); - ReleaseDC(hDesktop, hDC); + // find the first non-empty entry + UINT fileCount = DragQueryFile((HDROP)medium.hGlobal, 0xFFFFFFFF, NULL, 0); + TCHAR szPath[_MAX_PATH]; + UINT uiRes; + for (UINT i=0;iitemWidth=size.cx+GetSystemMetrics(SM_CXMENUCHECK)+2*GetSystemMetrics(SM_CXSMICON); - lpmis->itemHeight = __max(size.cy+3, GetSystemMetrics(SM_CYMENU)+3); + // check if there are files + if (!(GetFileAttributes(szPath) & FILE_ATTRIBUTE_DIRECTORY)) + m_bGroupFiles=true; - break; + if (bPathFound && m_bGroupFiles) + break; } + + ReleaseStgMedium(&medium); } + // if all paths are empty - check pidlfolder + if (!bPathFound) + { + if (!SHGetPathFromIDList(pidlFolder, m_szDstPath)) + return E_FAIL; + + // empty path - error + if (_tcslen(m_szDstPath) == 0) + return E_FAIL; + } + + // background or folder ? + m_bBackground=(lpdobj == NULL) && (pidlFolder != NULL); + return S_OK; } -void CMenuExt::DrawMenuItem(LPDRAWITEMSTRUCT lpdis) +STDMETHODIMP CMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) { - // check if menu - if (lpdis->CtlType != ODT_MENU) - return; + ATLTRACE(_T("CMenuExt::InvokeCommand()\n")); + // check options + HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); + if(FAILED(hResult) || hResult == S_FALSE) + return E_FAIL; // required to process other InvokeCommand handlers. - // margins and other stuff - const int iSmallIconWidth=GetSystemMetrics(SM_CXSMICON); - const int iSmallIconHeight=GetSystemMetrics(SM_CYSMICON); - const int iLeftMargin=GetSystemMetrics(SM_CXMENUCHECK)/2; - const int iRightMargin=GetSystemMetrics(SM_CXMENUCHECK)-iLeftMargin; - - int iShortcutIndex=(lpdis->itemID-m_uiFirstID-5)%g_pscsShared->iShortcutsCount; - _SHORTCUT* pShortcuts=g_pscsShared->GetShortcutsPtr(); + // find window + HWND hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + if (hWnd == NULL) + return E_FAIL; - // text color - HBRUSH hbr; - if (lpdis->itemState & ODS_SELECTED) + // commands + _COMMAND* pCommand = g_pscsShared->GetCommandsPtr(); + + // OTF("Invoke Command\r\n"); + // command type + switch (LOWORD(lpici->lpVerb)) { - SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); - SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); - hbr=CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); - } - else - { - SetTextColor(lpdis->hDC, GetSysColor(COLOR_MENUTEXT)); - SetBkColor(lpdis->hDC, GetSysColor(COLOR_MENU)); - hbr=CreateSolidBrush(GetSysColor(COLOR_MENU)); - } + // paste & paste special + case 0: + case 1: + { + // search for data in a clipboard + if (IsClipboardFormatAvailable(CF_HDROP)) + { + bool bMove=false; // 0-copy, 1-move - // draw background - RECT rcSelect=lpdis->rcItem; - rcSelect.top++; - rcSelect.bottom--; + // get data + OpenClipboard(lpici->hwnd); + HANDLE handle=GetClipboardData(CF_HDROP); + TCHAR *pchBuffer=NULL; + UINT uiSize; - FillRect(lpdis->hDC, &rcSelect, hbr); - DeleteObject(hbr); + GetDataFromClipboard(static_cast(handle), m_szDstPath, &pchBuffer, &uiSize); - // get img list - SHFILEINFO sfi; - HIMAGELIST himl=(HIMAGELIST)SHGetFileInfo(pShortcuts[iShortcutIndex].szPath, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), SHGFI_SMALLICON | SHGFI_ICON | SHGFI_SYSICONINDEX); - ImageList_Draw(himl, sfi.iIcon, lpdis->hDC, lpdis->rcItem.left+iLeftMargin, - lpdis->rcItem.top+(lpdis->rcItem.bottom-lpdis->rcItem.top+1-iSmallIconHeight)/2, ILD_TRANSPARENT); + // register clipboard format nad if exists in it + UINT nFormat=RegisterClipboardFormat(_T("Preferred DropEffect")); + if (IsClipboardFormatAvailable(nFormat)) + { + handle=GetClipboardData(nFormat); + LPVOID addr=GlobalLock(handle); + if(!addr) + return E_FAIL; + DWORD dwData=((DWORD*)addr)[0]; + if (dwData & DROPEFFECT_MOVE) + bMove=true; - RECT rcText; - rcText.left=iLeftMargin+iSmallIconWidth+iRightMargin; - rcText.top=lpdis->rcItem.top; - rcText.right=lpdis->rcItem.right; - rcText.bottom=lpdis->rcItem.bottom; + GlobalUnlock(handle); + } -// OTF("Drawing text: %s\r\n", pShortcuts[iShortcutIndex].szName); - DrawText(lpdis->hDC, pShortcuts[iShortcutIndex].szName, -1, &rcText, DT_LEFT | DT_SINGLELINE | DT_VCENTER); + CloseClipboard(); + + // fill struct + COPYDATASTRUCT cds; + cds.dwData=(((DWORD)bMove) << 31) | pCommand[LOWORD(lpici->lpVerb)].uiCommandID; + cds.lpData=pchBuffer; + cds.cbData=uiSize * sizeof(TCHAR); + + // send a message + ::SendMessage(hWnd, WM_COPYDATA, reinterpret_cast(lpici->hwnd), reinterpret_cast(&cds)); + + // delete buffer + delete [] pchBuffer; + } + } + break; + + // case 2: + // case 3: + // case 4: + default: + { + // out of range - may be a shortcut + if (LOWORD(lpici->lpVerb) < g_pscsShared->iCommandCount+(m_bBackground ? 0 : 3*g_pscsShared->iShortcutsCount)) + { + // addr of a table with shortcuts + _SHORTCUT* stShortcuts = g_pscsShared->GetShortcutsPtr(); + + // find command for which this command is generated + int iCommandIndex=(int)(((LOWORD(lpici->lpVerb)-5) / g_pscsShared->iShortcutsCount))+2; // command index + int iShortcutIndex=((LOWORD(lpici->lpVerb)-5) % g_pscsShared->iShortcutsCount); // shortcut index + + // buffer for data + UINT uiSize=_tcslen(stShortcuts[iShortcutIndex].szPath)+1+m_bBuffer.m_iDataSize; + TCHAR *pszBuffer=new TCHAR[uiSize]; + _tcscpy(pszBuffer, stShortcuts[iShortcutIndex].szPath); // �cie�ka docelowa + + // buffer with files + memcpy(pszBuffer+_tcslen(stShortcuts[iShortcutIndex].szPath)+1, m_bBuffer.m_pszFiles, m_bBuffer.m_iDataSize*sizeof(TCHAR)); + + // fill struct + COPYDATASTRUCT cds; + cds.dwData=pCommand[iCommandIndex].uiCommandID; + cds.lpData=pszBuffer; + cds.cbData=uiSize * sizeof(TCHAR); + + // send message + ::SendMessage(hWnd, WM_COPYDATA, reinterpret_cast(lpici->hwnd), reinterpret_cast(&cds)); + + // delete buffer + delete [] pszBuffer; + m_bBuffer.Destroy(); + } + else + return E_FAIL; + } + break; + } + + return S_OK; } STDMETHODIMP CMenuExt::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT /*uFlags*/) { + ATLTRACE(_T("CMenuExt::QueryContextMenu()\n")); // check options HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); if(FAILED(hResult) || hResult == S_FALSE) @@ -193,27 +265,6 @@ if(!hWnd) return S_OK; -/* OTF("CMenuExt::QueryContextMenu - idCmdFirst=%lu, uFlags=%lu (", idCmdFirst, uFlags); - if (uFlags & CMF_CANRENAME) - OTF("CMF_CANRENAME "); - if (uFlags & CMF_DEFAULTONLY) - OTF("CMF_DEFAULTONLY "); - if (uFlags & CMF_EXPLORE) - OTF("CMF_EXPLORE "); - if (uFlags & CMF_EXTENDEDVERBS) - OTF("CMF_EXTENDEDVERBS "); - if (uFlags & CMF_INCLUDESTATIC) - OTF("CMF_INCLUDESTATIC "); - if (uFlags & CMF_NODEFAULT) - OTF("CMF_NODEFAULT "); - if (uFlags & CMF_NORMAL) - OTF("CMF_NORMAL "); - if (uFlags & CMF_NOVERBS) - OTF("CMF_NOVERBS "); - if (uFlags & CMF_VERBSONLY) - OTF("CMF_VERBSONLY "); - OTF(")\r\n"); -*/ // remember ID of the first command m_uiFirstID=idCmdFirst; @@ -231,7 +282,7 @@ for (int i=0;iGetCommandsPtr(); // data about commands int iCommandCount=0; - + if (!m_bGroupFiles) { // paste - if (g_pscsShared->uiFlags & EC_PASTE_FLAG) + if (g_pscsShared->uiFlags & CSharedConfigStruct::EC_PASTE_FLAG) { ::InsertMenu(hmenu, indexMenu++, MF_BYPOSITION | MF_STRING | (IsClipboardFormatAvailable(CF_HDROP) ? MF_ENABLED : MF_GRAYED), idCmdFirst+0, pCommand[0].szCommand); iCommandCount++; } - - if (g_pscsShared->uiFlags & EC_PASTESPECIAL_FLAG) + + if (g_pscsShared->uiFlags & CSharedConfigStruct::EC_PASTESPECIAL_FLAG) { ::InsertMenu(hmenu, indexMenu++, MF_BYPOSITION | MF_STRING | (IsClipboardFormatAvailable(CF_HDROP) ? MF_ENABLED : MF_GRAYED), idCmdFirst+1, pCommand[1].szCommand); iCommandCount++; } } -// OTF("After group files\r\n"); - if (!m_bBackground) { CreateShortcutsMenu(idCmdFirst+5, g_pscsShared->bShowShortcutIcons); -// OTF("after creating shortcuts menu\r\n"); - + // copy to > - if (g_pscsShared->uiFlags & EC_COPYTO_FLAG) + if (g_pscsShared->uiFlags & CSharedConfigStruct::EC_COPYTO_FLAG) { mii.cbSize=sizeof(MENUITEMINFO); mii.fMask=MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE; @@ -303,14 +349,13 @@ mii.cch=_tcslen(pCommand[2].szCommand); ::InsertMenuItem(hmenu, indexMenu++, TRUE, &mii); -// ::InsertMenu(hmenu, indexMenu++, MF_BYPOSITION | MF_POPUP | MF_STRING | ((g_pscsShared->iShortcutsCount > 0) ? MF_ENABLED : MF_GRAYED), -// (UINT)m_mMenus.hShortcuts[0], pCommand[2].szCommand); + // ::InsertMenu(hmenu, indexMenu++, MF_BYPOSITION | MF_POPUP | MF_STRING | ((g_pscsShared->iShortcutsCount > 0) ? MF_ENABLED : MF_GRAYED), + // (UINT)m_mMenus.hShortcuts[0], pCommand[2].szCommand); iCommandCount++; -// OTF("added menu item\r\n"); } - + // move to > - if (g_pscsShared->uiFlags & EC_MOVETO_FLAG) + if (g_pscsShared->uiFlags & CSharedConfigStruct::EC_MOVETO_FLAG) { mii.cbSize=sizeof(MENUITEMINFO); mii.fMask=MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE; @@ -322,13 +367,13 @@ mii.cch=_tcslen(pCommand[3].szCommand); ::InsertMenuItem(hmenu, indexMenu++, TRUE, &mii); -// ::InsertMenu(hmenu, indexMenu++, MF_BYPOSITION | MF_POPUP | MF_STRING | ((g_pscsShared->iShortcutsCount > 0) ? MF_ENABLED : MF_GRAYED), -// (UINT)m_mMenus.hShortcuts[1], pCommand[3].szCommand); + // ::InsertMenu(hmenu, indexMenu++, MF_BYPOSITION | MF_POPUP | MF_STRING | ((g_pscsShared->iShortcutsCount > 0) ? MF_ENABLED : MF_GRAYED), + // (UINT)m_mMenus.hShortcuts[1], pCommand[3].szCommand); iCommandCount++; } - + // copy/move to special... > - if (g_pscsShared->uiFlags & EC_COPYMOVETOSPECIAL_FLAG) + if (g_pscsShared->uiFlags & CSharedConfigStruct::EC_COPYMOVETOSPECIAL_FLAG) { mii.cbSize=sizeof(MENUITEMINFO); mii.fMask=MIIM_ID | MIIM_STATE | MIIM_SUBMENU | MIIM_TYPE; @@ -340,21 +385,131 @@ mii.cch=_tcslen(pCommand[4].szCommand); ::InsertMenuItem(hmenu, indexMenu++, TRUE, &mii); -// ::InsertMenu(hmenu, indexMenu++, MF_BYPOSITION | MF_POPUP | MF_STRING | ((g_pscsShared->iShortcutsCount > 0) ? MF_ENABLED : MF_GRAYED), -// (UINT)m_mMenus.hShortcuts[2], pCommand[4].szCommand); + // ::InsertMenu(hmenu, indexMenu++, MF_BYPOSITION | MF_POPUP | MF_STRING | ((g_pscsShared->iShortcutsCount > 0) ? MF_ENABLED : MF_GRAYED), + // (UINT)m_mMenus.hShortcuts[2], pCommand[4].szCommand); iCommandCount++; } } -// OTF("before return\r\n"); return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, g_pscsShared->iCommandCount+(m_bBackground ? 0 : 3*g_pscsShared->iShortcutsCount)); } -void CMenuExt::CreateShortcutsMenu(UINT uiIDBase, bool bOwnerDrawn) +HRESULT CMenuExt::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam) { -// OTF("CreateShortcutsMenu\r\n"); + return HandleMenuMsg2(uMsg, wParam, lParam, NULL); +} - // tw�rz puste menu +HRESULT CMenuExt::HandleMenuMsg2(UINT uMsg, WPARAM /*wParam*/, LPARAM lParam, LRESULT* /*plResult*/) +{ + ATLTRACE(_T("CMenuExt::HandleMenuMsg2()\n")); + + switch(uMsg) + { + case WM_INITMENUPOPUP: + break; + + case WM_DRAWITEM: + { + LPDRAWITEMSTRUCT lpdis=(LPDRAWITEMSTRUCT) lParam; + DrawMenuItem(lpdis); + break; + } + + case WM_MEASUREITEM: + { + LPMEASUREITEMSTRUCT lpmis=(LPMEASUREITEMSTRUCT)lParam; + + // establish display text + int iShortcutIndex=(lpmis->itemID-m_uiFirstID-5)%g_pscsShared->iShortcutsCount; + _SHORTCUT* pShortcuts = g_pscsShared->GetShortcutsPtr(); + + // measure the text + HWND hDesktop=GetDesktopWindow(); + HDC hDC=GetDC(hDesktop); + + // get menu logfont + NONCLIENTMETRICS ncm; + ncm.cbSize=sizeof(NONCLIENTMETRICS); + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0); + + HFONT hFont=CreateFontIndirect(&ncm.lfMenuFont); + HFONT hOldFont=(HFONT)SelectObject(hDC, hFont); + + // calc text size + SIZE size; + GetTextExtentPoint32(hDC, pShortcuts[iShortcutIndex].szName, (int)_tcslen(pShortcuts[iShortcutIndex].szName), &size); + + // restore old settings + SelectObject(hDC, hOldFont); + ReleaseDC(hDesktop, hDC); + + // set + lpmis->itemWidth=size.cx+GetSystemMetrics(SM_CXMENUCHECK)+2*GetSystemMetrics(SM_CXSMICON); + lpmis->itemHeight = __max(size.cy+3, GetSystemMetrics(SM_CYMENU)+3); + + break; + } + } + + return S_OK; +} + +void CMenuExt::DrawMenuItem(LPDRAWITEMSTRUCT lpdis) +{ + // check if menu + if (lpdis->CtlType != ODT_MENU) + return; + + // margins and other stuff + const int iSmallIconWidth=GetSystemMetrics(SM_CXSMICON); + const int iSmallIconHeight=GetSystemMetrics(SM_CYSMICON); + const int iLeftMargin=GetSystemMetrics(SM_CXMENUCHECK)/2; + const int iRightMargin=GetSystemMetrics(SM_CXMENUCHECK)-iLeftMargin; + + int iShortcutIndex=(lpdis->itemID-m_uiFirstID-5)%g_pscsShared->iShortcutsCount; + _SHORTCUT* pShortcuts=g_pscsShared->GetShortcutsPtr(); + + // text color + HBRUSH hbr; + if (lpdis->itemState & ODS_SELECTED) + { + SetTextColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); + SetBkColor(lpdis->hDC, GetSysColor(COLOR_HIGHLIGHT)); + hbr=CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT)); + } + else + { + SetTextColor(lpdis->hDC, GetSysColor(COLOR_MENUTEXT)); + SetBkColor(lpdis->hDC, GetSysColor(COLOR_MENU)); + hbr=CreateSolidBrush(GetSysColor(COLOR_MENU)); + } + + // draw background + RECT rcSelect=lpdis->rcItem; + rcSelect.top++; + rcSelect.bottom--; + + FillRect(lpdis->hDC, &rcSelect, hbr); + DeleteObject(hbr); + + // get img list + SHFILEINFO sfi; + HIMAGELIST himl=(HIMAGELIST)SHGetFileInfo(pShortcuts[iShortcutIndex].szPath, FILE_ATTRIBUTE_NORMAL, &sfi, sizeof(SHFILEINFO), SHGFI_SMALLICON | SHGFI_ICON | SHGFI_SYSICONINDEX); + ImageList_Draw(himl, sfi.iIcon, lpdis->hDC, lpdis->rcItem.left+iLeftMargin, + lpdis->rcItem.top+(lpdis->rcItem.bottom-lpdis->rcItem.top+1-iSmallIconHeight)/2, ILD_TRANSPARENT); + + RECT rcText; + rcText.left=iLeftMargin+iSmallIconWidth+iRightMargin; + rcText.top=lpdis->rcItem.top; + rcText.right=lpdis->rcItem.right; + rcText.bottom=lpdis->rcItem.bottom; + + DrawText(lpdis->hDC, pShortcuts[iShortcutIndex].szName, -1, &rcText, DT_LEFT | DT_SINGLELINE | DT_VCENTER); +} + +void CMenuExt::CreateShortcutsMenu(UINT uiIDBase, bool bOwnerDrawn) +{ + // create empty menus m_mMenus.hShortcuts[0]=CreatePopupMenu(); m_mMenus.hShortcuts[1]=CreatePopupMenu(); m_mMenus.hShortcuts[2]=CreatePopupMenu(); @@ -372,7 +527,6 @@ _sntprintf(szText, 256 - 1, _T("%s (%s)"), pShortcuts[i].szName, GetSizeString(ullFree, szSize, 32)); szText[256 - 1] = _T('\0'); _tcsncpy(pShortcuts[i].szName, szText, 127); -// OTF("Text to display=%s\r\n", pShortcuts[i].szName); pShortcuts[i].szName[127]=_T('\0'); } @@ -476,195 +630,3 @@ return S_OK; } - - -STDMETHODIMP CMenuExt::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT lpdobj, HKEY /*hkeyProgID*/) -{ - // check options - HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult) || hResult == S_FALSE) - return hResult; - - // find ch window - HWND hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); - if (hWnd == NULL) - return E_FAIL; - - // get cfg from ch - ::SendMessage(hWnd, WM_GETCONFIG, GC_EXPLORER, 0); - - // read dest folder - m_szDstPath[0]=_T('\0'); - - // TEMP -// OTF("****************************************************************\r\n"); -// OTF("CMenuExt::Initialize: pidlFolder=%lu, lpdobj=%lu\r\n", pidlFolder, lpdobj); - - // get data from IDataObject - files to copy/move - bool bPathFound=false; - m_bGroupFiles=false; - if (lpdobj) - { - STGMEDIUM medium; - FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL}; - - HRESULT hr = lpdobj->GetData(&fe, &medium); - if (FAILED(hr)) - return E_FAIL; - - // copy all filenames to a table - GetDataFromClipboard(static_cast(medium.hGlobal), NULL, &m_bBuffer.m_pszFiles, &m_bBuffer.m_iDataSize); - - // find the first non-empty entry - UINT fileCount = DragQueryFile((HDROP)medium.hGlobal, 0xFFFFFFFF, NULL, 0); - TCHAR szPath[_MAX_PATH]; - UINT uiRes; - for (UINT i=0;iGetCommandsPtr(); - -// OTF("Invoke Command\r\n"); - // command type - switch (LOWORD(lpici->lpVerb)) - { - // paste & paste special - case 0: - case 1: - { - // search for data in a clipboard - if (IsClipboardFormatAvailable(CF_HDROP)) - { - bool bMove=false; // 0-copy, 1-move - - // get data - OpenClipboard(lpici->hwnd); - HANDLE handle=GetClipboardData(CF_HDROP); - TCHAR *pchBuffer=NULL; - UINT uiSize; - - GetDataFromClipboard(static_cast(handle), m_szDstPath, &pchBuffer, &uiSize); - - // register clipboard format nad if exists in it - UINT nFormat=RegisterClipboardFormat(_T("Preferred DropEffect")); - if (IsClipboardFormatAvailable(nFormat)) - { - handle=GetClipboardData(nFormat); - LPVOID addr=GlobalLock(handle); - if(!addr) - return E_FAIL; - DWORD dwData=((DWORD*)addr)[0]; - if (dwData & DROPEFFECT_MOVE) - bMove=true; - - GlobalUnlock(handle); - } - - CloseClipboard(); - - // fill struct - COPYDATASTRUCT cds; - cds.dwData=(((DWORD)bMove) << 31) | pCommand[LOWORD(lpici->lpVerb)].uiCommandID; - cds.lpData=pchBuffer; - cds.cbData=uiSize * sizeof(TCHAR); - - // send a message - ::SendMessage(hWnd, WM_COPYDATA, reinterpret_cast(lpici->hwnd), reinterpret_cast(&cds)); - - // delete buffer - delete [] pchBuffer; - } - } - break; - -// case 2: -// case 3: -// case 4: - default: - { - // out of range - may be a shortcut - if (LOWORD(lpici->lpVerb) < g_pscsShared->iCommandCount+(m_bBackground ? 0 : 3*g_pscsShared->iShortcutsCount)) - { - // addr of a table with shortcuts - _SHORTCUT* stShortcuts = g_pscsShared->GetShortcutsPtr(); - - // find command for which this command is generated - int iCommandIndex=(int)(((LOWORD(lpici->lpVerb)-5) / g_pscsShared->iShortcutsCount))+2; // command index - int iShortcutIndex=((LOWORD(lpici->lpVerb)-5) % g_pscsShared->iShortcutsCount); // shortcut index - - // buffer for data - UINT uiSize=_tcslen(stShortcuts[iShortcutIndex].szPath)+1+m_bBuffer.m_iDataSize; - TCHAR *pszBuffer=new TCHAR[uiSize]; - _tcscpy(pszBuffer, stShortcuts[iShortcutIndex].szPath); // �cie�ka docelowa - - // buffer with files - memcpy(pszBuffer+_tcslen(stShortcuts[iShortcutIndex].szPath)+1, m_bBuffer.m_pszFiles, m_bBuffer.m_iDataSize*sizeof(TCHAR)); - - // fill struct - COPYDATASTRUCT cds; - cds.dwData=pCommand[iCommandIndex].uiCommandID; - cds.lpData=pszBuffer; - cds.cbData=uiSize * sizeof(TCHAR); - - // send message - ::SendMessage(hWnd, WM_COPYDATA, reinterpret_cast(lpici->hwnd), reinterpret_cast(&cds)); - - // delete buffer - delete [] pszBuffer; - m_bBuffer.Destroy(); - } - else - return E_FAIL; - } - break; - } - - return S_OK; -} Index: src/chext/MenuExt.h =================================================================== diff -u -rcd5a36f1507a4131ce652879565c0770b36dd953 -r0373359eff650e8cf04a5992711ef9f20347536f --- src/chext/MenuExt.h (.../MenuExt.h) (revision cd5a36f1507a4131ce652879565c0770b36dd953) +++ src/chext/MenuExt.h (.../MenuExt.h) (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -30,8 +30,6 @@ class ATL_NO_VTABLE CMenuExt : public CComObjectRootEx, public CComCoClass, - public IObjectWithSiteImpl, - public IDispatchImpl, public IShellExtInit, public IContextMenu3 { @@ -45,13 +43,10 @@ DECLARE_PROTECT_FINAL_CONSTRUCT() BEGIN_COM_MAP(CMenuExt) - COM_INTERFACE_ENTRY(IMenuExt) - COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IShellExtInit) COM_INTERFACE_ENTRY(IContextMenu) COM_INTERFACE_ENTRY(IContextMenu2) COM_INTERFACE_ENTRY(IContextMenu3) - COM_INTERFACE_ENTRY(IObjectWithSite) END_COM_MAP() // IMenuExt Index: src/chext/chext.idl =================================================================== diff -u -rd0fdcc905035e648382256101a3d99f429af6d56 -r0373359eff650e8cf04a5992711ef9f20347536f --- src/chext/chext.idl (.../chext.idl) (revision d0fdcc905035e648382256101a3d99f429af6d56) +++ src/chext/chext.idl (.../chext.idl) (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -24,66 +24,38 @@ import "oaidl.idl"; import "ocidl.idl"; - [ - v1_enum, - uuid(54F8BFDD-6685-4792-94BD-40DF00099F9B), - helpstring("Shell extension flags") - ] - enum EShellExtFlags - { - eShellExt_None = 0, - eShellExt_Enabled = 1 - }; +import "shobjidl.idl"; - [ - object, - uuid(413AA618-E769-4E6E-A610-7BDC8A189FB2), - dual, - helpstring("IMenuExt Interface"), - pointer_default(unique) - ] - interface IMenuExt : IDispatch - { -// [id(1), helpstring("method QueryContextMenu")] HRESULT QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags); -// [id(1), helpstring("method GetCommandString")] HRESULT GetCommandString(UINT idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax); -// [id(2), helpstring("method InvokeCommand")] HRESULT InvokeCommand(LPCMINVOKECOMMANDINFO lpici); -// [id(1), helpstring("method Initialize")] HRESULT Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT lpdobj, HKEY hkeyProgID); -// [id(1), helpstring("method Initialize")] HRESULT Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT lpdobj, HKEY hkeyProgID); - }; - [ - object, - uuid(4AEAD637-8A55-47B9-AA1A-DACEA3DE9B71), - dual, - helpstring("IDropMenuExt Interface"), - pointer_default(unique) - ] - interface IDropMenuExt : IDispatch - { -// [id(1), helpstring("method QueryContextMenu")] HRESULT QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags); -// [id(1), helpstring("method GetCommandString")] HRESULT GetCommandString(UINT idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax); -// [id(1), helpstring("method Initialize")] HRESULT Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT lpdobj, HKEY hkeyProgID); -// [id(1), helpstring("method InvokeCommand")] HRESULT InvokeCommand(LPCMINVOKECOMMANDINFO lpici); - }; +[ + v1_enum, + uuid(54F8BFDD-6685-4792-94BD-40DF00099F9B), + helpstring("Shell extension flags") +] +enum EShellExtFlags +{ + eShellExt_None = 0, + eShellExt_Enabled = 1 +}; - [ - object, - uuid(317E503A-9D2F-4f42-995E-D314CB9D89B0), - dual, - helpstring("IShellExtControl Interface"), - pointer_default(unique) - ] - interface IShellExtControl : IDispatch - { - // Shell extension version (numeric and readable) - [id(1),helpstring("Retrieves the extension version information")] - HRESULT GetVersion([out]LONG* plVersion, [out]BSTR* pbstrVersion); +[ + object, + uuid(317E503A-9D2F-4f42-995E-D314CB9D89B0), + dual, + helpstring("IShellExtControl Interface"), + pointer_default(unique) +] +interface IShellExtControl : IDispatch +{ + // Shell extension version (numeric and readable) + [id(1),helpstring("Retrieves the extension version information")] + HRESULT GetVersion([out]LONG* plVersion, [out]BSTR* pbstrVersion); - // Flag setting/retrieving - [id(2),helpstring("Sets the flags for shell extension")] - HRESULT SetFlags(LONG lFlags, LONG lMask); - [id(3),helpstring("Retrieves the shell extension flags")] - HRESULT GetFlags(LONG* plFlags); - }; + // Flag setting/retrieving + [id(2),helpstring("Sets the flags for shell extension")] + HRESULT SetFlags(LONG lFlags, LONG lMask); + [id(3),helpstring("Retrieves the shell extension flags")] + HRESULT GetFlags(LONG* plFlags); +}; [ uuid(68FAFC14-8EB8-4DA1-90EB-6B3D22010505), @@ -101,15 +73,17 @@ ] coclass MenuExt { - [default] interface IMenuExt; + [default] interface IContextMenu3; + interface IShellExtControl; }; [ uuid(B46F8244-86E6-43CF-B8AB-8C3A89928A48), helpstring("DropMenuExt Class") ] coclass DropMenuExt { - [default] interface IDropMenuExt; + [default] interface IContextMenu3; + interface IShellExtControl; }; [ uuid(3D855ACA-8274-4f1f-94E9-6BEF4FC2A2AF), Index: src/chext/chext.vc90.vcproj =================================================================== diff -u -r8f31c461b6a91ce6818c646814bd19e740b109ef -r0373359eff650e8cf04a5992711ef9f20347536f --- src/chext/chext.vc90.vcproj (.../chext.vc90.vcproj) (revision 8f31c461b6a91ce6818c646814bd19e740b109ef) +++ src/chext/chext.vc90.vcproj (.../chext.vc90.vcproj) (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -413,6 +413,14 @@ Name="Tools" > + + + + Index: src/common/ipcstructs.h =================================================================== diff -u -rd5c3edd0d167db9b5d47d04248820fda49499a5e -r0373359eff650e8cf04a5992711ef9f20347536f --- src/common/ipcstructs.h (.../ipcstructs.h) (revision d5c3edd0d167db9b5d47d04248820fda49499a5e) +++ src/common/ipcstructs.h (.../ipcstructs.h) (revision 0373359eff650e8cf04a5992711ef9f20347536f) @@ -19,18 +19,6 @@ #ifndef __SHAREDDATA_H__ #define __SHAREDDATA_H__ -// drag&drop flags -#define OPERATION_MASK 0x00ffffff -#define DD_COPY_FLAG 0x00000001 -#define DD_MOVE_FLAG 0x00000002 -#define DD_COPYMOVESPECIAL_FLAG 0x00000004 - -#define EC_PASTE_FLAG 0x00000010 -#define EC_PASTESPECIAL_FLAG 0x00000020 -#define EC_COPYTO_FLAG 0x00000040 -#define EC_MOVETO_FLAG 0x00000080 -#define EC_COPYMOVETOSPECIAL_FLAG 0x00000100 - // messages used #define WM_GETCONFIG WM_USER+20 @@ -64,6 +52,25 @@ class CSharedConfigStruct { public: + enum EFlags + { + // drag&drop flags + OPERATION_MASK = 0x00ffffff, + DD_COPY_FLAG = 0x00000001, + DD_MOVE_FLAG = 0x00000002, + DD_COPYMOVESPECIAL_FLAG = 0x00000004, + + EC_PASTE_FLAG = 0x00000010, + EC_PASTESPECIAL_FLAG = 0x00000020, + EC_COPYTO_FLAG = 0x00000040, + EC_MOVETO_FLAG = 0x00000080, + EC_COPYMOVETOSPECIAL_FLAG = 0x00000100, + + eFlag_InterceptDragAndDrop = 0x00000200, + eFlag_InterceptKeyboardActions = 0x00000400, + eFlag_InterceptCtxMenuActions = 0x00000800 + }; +public: _SHORTCUT* GetShortcutsPtr() const { return (_SHORTCUT*)(byData + iCommandCount * sizeof(_COMMAND)); } _COMMAND* GetCommandsPtr() const { return (_COMMAND*)byData; } @@ -73,8 +80,7 @@ bool bShowFreeSpace; // showthe free space by the shortcuts ? TCHAR szSizes[6][64]; // names of the kB, GB, ... bool bShowShortcutIcons; // show shell icons with shortcuts ? - bool bOverrideDefault; // only for d&d - want to change menu default item to the one from ch ? - UINT uiDefaultAction; // default action for drag&drop when using above option + int iCommandCount; // count of commands stored at the beginning of a buffer int iShortcutsCount; // count of shortcuts to display in submenus