+++ /dev/null
-#include "DragDrop.h"
-#include <memory>
-#include "paths.h"
-
-//
-// OnDropFiles code from CDropEdit
-// Copyright 1997 Chris Losinger
-//
-// shortcut expansion code modified from :
-// CShortcut, 1996 Rob Warner
-//
-
-bool GetDroppedFiles(HDROP dropInfo, std::vector<String>& files)
-{
-// Get the number of pathnames that have been dropped
- UINT wNumFilesDropped = DragQueryFile(dropInfo, 0xFFFFFFFF, NULL, 0);
- UINT fileCount = 0;
-
- // get all file names. but we'll only need the first one.
- for (WORD x = 0 ; x < wNumFilesDropped; x++)
- {
- // Get the number of bytes required by the file's full pathname
- UINT wPathnameSize = DragQueryFile(dropInfo, x, NULL, 0);
-
- // Allocate memory to contain full pathname & zero byte
- wPathnameSize += 1;
- std::unique_ptr<TCHAR[]> npszFile(new TCHAR[wPathnameSize]);
-
- // Copy the pathname into the buffer
- DragQueryFile(dropInfo, x, npszFile.get(), wPathnameSize);
-
- if (x < 3)
- {
- files.resize(x + 1);
- files[x] = npszFile.get();
- fileCount++;
- }
- }
-
- // Free the memory block containing the dropped-file information
- DragFinish(dropInfo);
-
- for (UINT i = 0; i < fileCount; i++)
- {
- if (paths_IsShortcut(files[i]))
- {
- // if this was a shortcut, we need to expand it to the target path
- String expandedFile = ExpandShortcut(files[i]);
-
- // if that worked, we should have a real file name
- if (!expandedFile.empty())
- files[i] = expandedFile;
- }
- }
- return true;
-}
+++ /dev/null
-#pragma once
-
-#include "UnicodeString.h"
-#include <windows.h>
-#include <vector>
-
-bool GetDroppedFiles(HDROP dropInfo, std::vector<String>& files);
#include "SuperComboBox.h"
#include <shlwapi.h>
#include <vector>
-#include "DragDrop.h"
+#include "DropHandler.h"
#ifdef _DEBUG
#define new DEBUG_NEW
HIMAGELIST CSuperComboBox::m_himlSystem = NULL;
CSuperComboBox::CSuperComboBox(BOOL bAdd /*= TRUE*/, UINT idstrAddText /*= 0*/)
+ : m_pDropHandler(NULL)
{
m_bEditChanged=FALSE;
m_bDoComplete = FALSE;
ON_CONTROL_REFLECT_EX(CBN_EDITCHANGE, OnEditchange)
ON_CONTROL_REFLECT_EX(CBN_SELCHANGE, OnSelchange)
ON_WM_CREATE()
- ON_WM_DROPFILES()
+ ON_WM_DESTROY()
ON_NOTIFY_REFLECT(CBEN_GETDISPINFO, OnGetDispInfo)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSuperComboBox message handlers
+void CSuperComboBox::PreSubclassWindow()
+{
+ CComboBoxEx::PreSubclassWindow();
+ m_pDropHandler = new DropHandler(std::bind(&CSuperComboBox::OnDropFiles, this, std::placeholders::_1));
+ RegisterDragDrop(m_hWnd, m_pDropHandler);
+}
+
/**
* @brief Returns whether the window associated with this object is ComboBoxEx.
*/
int CSuperComboBox::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
- if (CComboBox::OnCreate(lpCreateStruct) == -1)
+ if (CComboBoxEx::OnCreate(lpCreateStruct) == -1)
return -1;
SetAutoAdd(!m_strAutoAdd.IsEmpty());
- DragAcceptFiles(TRUE);
+ m_pDropHandler = new DropHandler(std::bind(&CSuperComboBox::OnDropFiles, this, std::placeholders::_1));
+ RegisterDragDrop(m_hWnd, m_pDropHandler);
return 0;
}
+void CSuperComboBox::OnDestroy(void)
+{
+ if (m_pDropHandler)
+ RevokeDragDrop(m_hWnd);
+}
/////////////////////////////////////////////////////////////////////////////
//
// shortcut expansion code modified from :
// CShortcut, 1996 Rob Warner
//
-void CSuperComboBox::OnDropFiles(HDROP dropInfo)
+void CSuperComboBox::OnDropFiles(const std::vector<String>& files)
{
- std::vector<String> files;
- GetDroppedFiles(dropInfo, files);
- if (files.size() == 0)
- return;
-
GetParent()->SendMessage(WM_COMMAND, GetDlgCtrlID() +
(CBN_EDITUPDATE << 16), (LPARAM)m_hWnd);
SetWindowText(files[0].c_str());
// ComboBoxEx.h : header file
//
+#include <vector>
+#include "UnicodeString.h"
+
+class DropHandler;
+
/////////////////////////////////////////////////////////////////////////////
// CSuperComboBox window
protected:
CString m_strCurSel;
virtual BOOL OnAddTemplate();
+ virtual void PreSubclassWindow();
CString m_strAutoAdd;
BOOL m_bMustUninitOLE;
+ DropHandler *m_pDropHandler;
//{{AFX_MSG(CSuperComboBox)
afx_msg BOOL OnEditchange();
afx_msg BOOL OnSelchange();
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
- afx_msg void OnDropFiles(HDROP dropInfo);
+ afx_msg void OnDropFiles(const std::vector<String>& files);
afx_msg void OnGetDispInfo(NMHDR *pNotifyStruct, LRESULT *pResult);
+ afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
--- /dev/null
+#include <StdAfx.h>
+#include "DropHandler.h"
+#include <memory>
+#include <ShlObj.h>
+#include <comip.h>
+#include "paths.h"
+#include "Environment.h"
+#include "unicoder.h"
+#include "WaitStatusCursor.h"
+
+namespace
+{
+ struct HandleDeleter {
+ typedef HANDLE pointer;
+ void operator()(HANDLE h) { if (h && h != INVALID_HANDLE_VALUE) ::CloseHandle(h); }
+ };
+
+ typedef std::unique_ptr<HANDLE, HandleDeleter> unique_handle;
+ typedef _com_ptr_t<_com_IIID<IFileOperation, &__uuidof(IFileOperation)>> IFileOperationPtr;
+ typedef _com_ptr_t<_com_IIID<IShellItem, &__uuidof(IShellItem)>> IShellItemPtr;
+
+ bool CopyFileOrFolder(const String& src, const String& dst)
+ {
+ std::vector<TCHAR> srcpath(src.length() + 2, 0);
+ std::vector<TCHAR> dstpath(dst.length() + 2, 0);
+ memcpy(&srcpath[0], src.c_str(), src.length() * sizeof(TCHAR));
+ memcpy(&dstpath[0], dst.c_str(), dst.length() * sizeof(TCHAR));
+ SHFILEOPSTRUCT fileop = { 0, FO_COPY, &srcpath[0], &dstpath[0], FOF_NOCONFIRMATION, 0, 0, 0 };
+ return SHFileOperation(&fileop) == 0;
+ }
+
+ //
+ // OnDropFiles code from CDropEdit
+ // Copyright 1997 Chris Losinger
+ //
+ // shortcut expansion code modified from :
+ // CShortcut, 1996 Rob Warner
+ //
+
+ std::vector<String> GetDroppedFiles(HDROP dropInfo)
+ {
+ std::vector<String> files;
+ // Get the number of pathnames that have been dropped
+ UINT wNumFilesDropped = DragQueryFile(dropInfo, 0xFFFFFFFF, NULL, 0);
+ UINT fileCount = 0;
+
+ // get all file names. but we'll only need the first one.
+ for (WORD x = 0; x < wNumFilesDropped; x++)
+ {
+ // Get the number of bytes required by the file's full pathname
+ UINT wPathnameSize = DragQueryFile(dropInfo, x, NULL, 0);
+
+ // Allocate memory to contain full pathname & zero byte
+ wPathnameSize += 1;
+ std::unique_ptr<TCHAR[]> npszFile(new TCHAR[wPathnameSize]);
+
+ // Copy the pathname into the buffer
+ DragQueryFile(dropInfo, x, npszFile.get(), wPathnameSize);
+
+ files.push_back(npszFile.get());
+ }
+ return files;
+ }
+
+ std::vector<String> FilterFiles(const std::vector<String>& files_src)
+ {
+ std::vector<String> files(files_src);
+ TCHAR szTempPath[MAX_PATH];
+ TCHAR szTempPathShort[MAX_PATH];
+ GetTempPath(sizeof(szTempPath) / sizeof(szTempPath[0]), szTempPath);
+ GetShortPathName(szTempPath, szTempPathShort, sizeof(szTempPathShort) / sizeof(szTempPathShort[0]));
+
+ for (UINT i = 0; i < files.size(); i++)
+ {
+ if (paths_IsShortcut(files[i]))
+ {
+ // if this was a shortcut, we need to expand it to the target path
+ String expandedFile = ExpandShortcut(files[i]);
+
+ // if that worked, we should have a real file name
+ if (!expandedFile.empty())
+ files[i] = expandedFile;
+ }
+ else if (paths_IsDecendant(files[i], szTempPath) || paths_IsDecendant(files[i], szTempPathShort))
+ {
+ String tmpdir = env_GetTempChildPath();
+ CopyFileOrFolder(files[i], tmpdir);
+ files[i] = paths_ConcatPath(tmpdir, paths_FindFileName(files[i]));
+ }
+ }
+ return files;
+ }
+
+ HRESULT IStream_WriteToFile(IStream *pStream, const String& filename)
+ {
+ unique_handle hFile(CreateFile(filename.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL));
+ if (hFile.get() == INVALID_HANDLE_VALUE)
+ return E_FAIL;
+ for (;;)
+ {
+ char buf[65536];
+ DWORD dwWritten;
+ ULONG size = 0;
+ HRESULT hr = pStream->Read(buf, sizeof(buf), &size);
+ if (FAILED(hr))
+ return hr;
+ if (size == 0)
+ break;
+ WriteFile(hFile.get(), buf, size, &dwWritten, NULL);
+ }
+ return S_OK;
+ }
+
+ HRESULT HGLOBAL_WriteToFile(HGLOBAL hGlobal, const String& filename)
+ {
+ unique_handle hFile(CreateFile(filename.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL));
+ if (hFile.get() == INVALID_HANDLE_VALUE)
+ return E_FAIL;
+ char *p = static_cast<char *>(GlobalLock(hGlobal));
+ if (!p)
+ return E_FAIL;
+ SIZE_T size = GlobalSize(hGlobal);
+ while (size > 0)
+ {
+ DWORD dwWritten;
+ if (WriteFile(hFile.get(), p, (size > INT_MAX) ? INT_MAX : static_cast<DWORD>(size), &dwWritten, NULL) == FALSE)
+ {
+ GlobalUnlock(hGlobal);
+ return E_FAIL;
+ }
+ p += dwWritten;
+ size -= dwWritten;
+ }
+ GlobalUnlock(hGlobal);
+ return S_OK;
+ }
+
+ HRESULT SetFileWriteTime(const String& filename, const FILETIME& writetime)
+ {
+ unique_handle hFile(CreateFile(filename.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
+ if (hFile.get() == INVALID_HANDLE_VALUE)
+ return E_FAIL;
+ return SetFileTime(hFile.get(), NULL, NULL, &writetime) ? S_OK : E_FAIL;
+ }
+
+ HRESULT GetFileItemsFromIDataObject_CF_HDROP(IDataObject *pDataObj, std::vector<String>& files)
+ {
+ FORMATETC fmtetc_cf_hdrop = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ STGMEDIUM medium = { 0 };
+ HRESULT hr;
+ if ((hr = pDataObj->GetData(&fmtetc_cf_hdrop, &medium)) == S_OK)
+ {
+ HDROP hDrop = (HDROP)GlobalLock(medium.hGlobal);
+ if (hDrop)
+ {
+ files = FilterFiles(GetDroppedFiles(hDrop));
+ GlobalUnlock(medium.hGlobal);
+ }
+ ReleaseStgMedium(&medium);
+ }
+ return hr;
+ }
+
+#define HIDA_GetPIDLFolder(pida) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[0])
+#define HIDA_GetPIDLItem(pida, i) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[i+1])
+
+ HRESULT GetFileItemsFromIDataObject_ShellIDList(IDataObject *pDataObj, std::vector<String>& root_files)
+ {
+ String tmpdir;
+ FORMATETC fmtetc_filedescriptor = { RegisterClipboardFormat(CFSTR_SHELLIDLIST), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ STGMEDIUM medium = { 0 };
+ HRESULT hr;
+ if ((hr = pDataObj->GetData(&fmtetc_filedescriptor, &medium)) == S_OK)
+ {
+ CIDA *pcida = (CIDA *)GlobalLock(medium.hGlobal);
+ if (pcida)
+ {
+ LPCITEMIDLIST pidlParent = HIDA_GetPIDLFolder(pcida);
+ for (unsigned i = 0; i < pcida->cidl; ++i)
+ {
+ IShellItemPtr pShellItem;
+ if (SUCCEEDED(hr = SHCreateShellItem(pidlParent, NULL, HIDA_GetPIDLItem(pcida, i), &pShellItem)))
+ {
+ SFGAOF sfgaof = 0;
+ if (SUCCEEDED(hr = pShellItem->GetAttributes(SFGAO_FOLDER, &sfgaof)) && (sfgaof & SFGAO_FOLDER))
+ {
+ // Folder item
+ wchar_t *pPath = NULL;
+ if (SUCCEEDED(hr = pShellItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEEDITING, &pPath)))
+ {
+ root_files.push_back(ucr::toTString(pPath));
+ CoTaskMemFree(pPath);
+ }
+ }
+ else
+ {
+ // File item
+ IFileOperationPtr pFileOperation;
+ if (SUCCEEDED(hr = pFileOperation.CreateInstance(CLSID_FileOperation, NULL, CLSCTX_ALL)))
+ {
+ if (tmpdir.empty())
+ tmpdir = env_GetTempChildPath();
+ pFileOperation->SetOperationFlags(0);
+ PIDLIST_ABSOLUTE pidlDest;
+ if (SUCCEEDED(hr = SHParseDisplayName(ucr::toUTF16(tmpdir).c_str(), NULL, &pidlDest, 0, NULL)))
+ {
+ IShellItemPtr pShellItemDest;
+ SHCreateShellItem(NULL, NULL, pidlDest, &pShellItemDest);
+ pFileOperation->CopyItem(pShellItem, pShellItemDest, NULL, NULL);
+ if (SUCCEEDED(hr = pFileOperation->PerformOperations()))
+ {
+ wchar_t *pName;
+ if (SUCCEEDED(hr = pShellItem->GetDisplayName(SIGDN_PARENTRELATIVE, &pName)))
+ {
+ root_files.push_back(paths_ConcatPath(tmpdir, ucr::toTString(pName)));
+ CoTaskMemFree(pName);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ GlobalUnlock(medium.hGlobal);
+ }
+ ReleaseStgMedium(&medium);
+ }
+ return hr;
+ }
+
+ HRESULT ExtractFileItemFromIDataObject_FileContents(IDataObject *pDataObj, int lindex, const String& filepath)
+ {
+ FORMATETC fmtetc_filecontents = { RegisterClipboardFormat(CFSTR_FILECONTENTS), NULL, DVASPECT_CONTENT, lindex, TYMED_HGLOBAL | TYMED_ISTREAM };
+ STGMEDIUM medium = { 0 };
+ HRESULT hr;
+ if ((hr = pDataObj->GetData(&fmtetc_filecontents, &medium)) == S_OK)
+ {
+ hr = E_FAIL;
+ if (medium.tymed == TYMED_HGLOBAL)
+ hr = HGLOBAL_WriteToFile(medium.hGlobal, filepath);
+ else if (medium.tymed == TYMED_ISTREAM)
+ hr = IStream_WriteToFile(medium.pstm, filepath);
+ ReleaseStgMedium(&medium);
+ }
+ return hr;
+ }
+
+ HRESULT GetFileItemsFromIDataObject_FileDescriptor(IDataObject *pDataObj, std::vector<String>& root_files)
+ {
+ String tmpdir = env_GetTempChildPath();
+ FORMATETC fmtetc_filedescriptor = { RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ STGMEDIUM medium = { 0 };
+ HRESULT hr;
+ if ((hr = pDataObj->GetData(&fmtetc_filedescriptor, &medium)) == S_OK)
+ {
+ FILEGROUPDESCRIPTOR *file_group_descriptor = (FILEGROUPDESCRIPTOR *)GlobalLock(medium.hGlobal);
+ if (file_group_descriptor)
+ {
+ for (unsigned i = 0; i < file_group_descriptor->cItems; ++i)
+ {
+ String filename = file_group_descriptor->fgd[i].cFileName;
+ String filepath = paths_ConcatPath(tmpdir, filename);
+ if (file_group_descriptor->fgd[i].dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ paths_CreateIfNeeded(filepath);
+ else
+ {
+ ExtractFileItemFromIDataObject_FileContents(pDataObj, i, filepath);
+ if (file_group_descriptor->fgd[i].dwFlags & FD_WRITESTIME)
+ SetFileWriteTime(filepath, file_group_descriptor->fgd[i].ftLastWriteTime);
+ }
+ if (filename.find('\\') == String::npos)
+ root_files.push_back(filepath);
+ }
+ GlobalUnlock(medium.hGlobal);
+ }
+ ReleaseStgMedium(&medium);
+ }
+ return hr;
+ }
+
+}
+
+DropHandler::DropHandler(std::function<void(const std::vector<String>&)> callback)
+ : m_cRef(0), m_callback(callback)
+{
+}
+
+DropHandler::~DropHandler()
+{
+}
+
+HRESULT STDMETHODCALLTYPE DropHandler::QueryInterface(REFIID riid, void **ppvObject)
+{
+ if (!IsEqualIID(riid, IID_IUnknown) && !IsEqualIID(riid, IID_IDropTarget))
+ {
+ *ppvObject = NULL;
+ return E_NOINTERFACE;
+ }
+ *ppvObject = static_cast<IDropTarget *>(this);
+ AddRef();
+ return S_OK;
+}
+
+ULONG STDMETHODCALLTYPE DropHandler::AddRef(void)
+{
+ return InterlockedIncrement(&m_cRef);
+}
+
+ULONG STDMETHODCALLTYPE DropHandler::Release(void)
+{
+ if (InterlockedDecrement(&m_cRef) == 0) {
+ delete this;
+ return 0;
+ }
+ return m_cRef;
+}
+
+HRESULT STDMETHODCALLTYPE DropHandler::DragEnter(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
+{
+ FORMATETC fmtetc_cf_hdrop = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ FORMATETC fmtetc_shellidlist = { RegisterClipboardFormat(CFSTR_SHELLIDLIST), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ FORMATETC fmtetc_filedescriptor = { RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ if (pDataObj->QueryGetData(&fmtetc_cf_hdrop) == S_OK ||
+ pDataObj->QueryGetData(&fmtetc_shellidlist) == S_OK ||
+ pDataObj->QueryGetData(&fmtetc_filedescriptor) == S_OK)
+ {
+ *pdwEffect = DROPEFFECT_COPY;
+ return S_OK;
+ }
+ *pdwEffect = DROPEFFECT_NONE;
+ return DRAGDROP_S_CANCEL;
+}
+
+HRESULT STDMETHODCALLTYPE DropHandler::DragOver(DWORD, POINTL, DWORD *)
+{
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE DropHandler::DragLeave(void)
+{
+ return S_OK;
+}
+
+HRESULT DropHandler::Drop(IDataObject* pDataObj, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect)
+{
+ bool ok = false;
+ WaitStatusCursor waitstatus(IDS_STATUS_COPYFILES);
+ std::vector<String> files;
+ FORMATETC fmtetc_cf_hdrop = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ FORMATETC fmtetc_shellidlist = { RegisterClipboardFormat(CFSTR_SHELLIDLIST), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ FORMATETC fmtetc_filedescriptor = { RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR), NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ if (pDataObj->QueryGetData(&fmtetc_cf_hdrop) == S_OK &&
+ GetFileItemsFromIDataObject_CF_HDROP(pDataObj, files) == S_OK && files.size() > 0)
+ ok = true;
+ else if (pDataObj->QueryGetData(&fmtetc_shellidlist) == S_OK &&
+ GetFileItemsFromIDataObject_ShellIDList(pDataObj, files) == S_OK && files.size() > 0)
+ ok = true;
+ else if (pDataObj->QueryGetData(&fmtetc_filedescriptor) == S_OK &&
+ GetFileItemsFromIDataObject_FileDescriptor(pDataObj, files) == S_OK && files.size() > 0)
+ ok = true;
+ if (files.size() > 3)
+ files.resize(3);
+ if (!files.empty())
+ m_callback(files);
+ return S_OK;
+}
--- /dev/null
+#pragma once\r
+\r
+#include <windows.h>\r
+#include <functional>\r
+#include <vector>\r
+#include "UnicodeString.h"\r
+\r
+class DropHandler : public IDropTarget\r
+{\r
+public:\r
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);\r
+ ULONG STDMETHODCALLTYPE AddRef();\r
+ ULONG STDMETHODCALLTYPE Release();\r
+ \r
+ HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);\r
+ HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);\r
+ HRESULT STDMETHODCALLTYPE DragLeave(void);\r
+ HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);\r
+\r
+ DropHandler(std::function<void(const std::vector<String>&)> callback);\r
+ ~DropHandler();\r
+\r
+private:\r
+ LONG m_cRef;\r
+ std::function<void(const std::vector<String>&)> m_callback;\r
+};\r
#include "OptionsFont.h"
#include "TFile.h"
#include "JumpList.h"
-#include "DragDrop.h"
+#include "DropHandler.h"
#include "LanguageSelect.h"
using std::vector;
ON_COMMAND(ID_VIEW_WHITESPACE, OnViewWhitespace)
ON_UPDATE_COMMAND_UI(ID_VIEW_WHITESPACE, OnUpdateViewWhitespace)
ON_COMMAND(ID_TOOLS_GENERATEPATCH, OnToolsGeneratePatch)
- ON_WM_DROPFILES()
+ ON_WM_DESTROY()
ON_WM_SETCURSOR()
ON_COMMAND_RANGE(ID_UNPACK_MANUAL, ID_UNPACK_AUTO, OnPluginUnpackMode)
ON_UPDATE_COMMAND_UI_RANGE(ID_UNPACK_MANUAL, ID_UNPACK_AUTO, OnUpdatePluginUnpackMode)
CMainFrame::CMainFrame()
: m_bFlashing(FALSE)
, m_bFirstTime(TRUE)
+, m_pDropHandler(NULL)
{
ZeroMemory(&m_pMenus[0], sizeof(m_pMenus));
}
myStatusDisplay.SetFrame(this);
CustomStatusCursor::SetStatusDisplay(&myStatusDisplay);
+ m_pDropHandler = new DropHandler(std::bind(&CMainFrame::OnDropFiles, this, std::placeholders::_1));
+ RegisterDragDrop(m_hWnd, m_pDropHandler);
+
return 0;
}
+void CMainFrame::OnDestroy(void)
+{
+ if (m_pDropHandler)
+ RevokeDragDrop(m_hWnd);
+}
+
static HMENU GetSubmenu(HMENU mainMenu, UINT nIDFirstMenuItem, bool bFirstSubmenu)
{
int i;
}
}
-void CMainFrame::OnDropFiles(HDROP dropInfo)
+void CMainFrame::OnDropFiles(const std::vector<String>& dropped_files)
{
- std::vector<String> dropped_files;
- GetDroppedFiles(dropInfo, dropped_files);
PathContext files(dropped_files);
const size_t fileCount = files.GetSize();
class LineFiltersList;
class TempFile;
struct FileLocation;
+class DropHandler;
typedef std::shared_ptr<TempFile> TempFilePtr;
std::unique_ptr<BCMenu> m_pMenus[MENU_COUNT]; /**< Menus for different views */
std::vector<TempFilePtr> m_tempFiles; /**< List of possibly needed temp files. */
+ DropHandler *m_pDropHandler;
// Generated message map functions
protected:
afx_msg void OnViewWhitespace();
afx_msg void OnUpdateViewWhitespace(CCmdUI* pCmdUI);
afx_msg void OnToolsGeneratePatch();
- afx_msg void OnDropFiles(HDROP dropInfo);
+ afx_msg void OnDropFiles(const std::vector<String>& files);
afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
afx_msg void OnUpdatePluginUnpackMode(CCmdUI* pCmdUI);
afx_msg void OnPluginUnpackMode(UINT nID);
afx_msg void OnUpdateCompareMethod(CCmdUI* pCmdUI);
afx_msg void OnMRUs(UINT nID);
afx_msg void OnUpdateNoMRUs(CCmdUI* pCmdUI);
+ afx_msg void OnDestroy();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
return FALSE;
}
m_pMainWnd = pMainFrame;
- // Enable drag&drop files
- pMainFrame->ModifyStyleEx(NULL, WS_EX_ACCEPTFILES);
// Init menus -- hMenuDefault is for MainFrame
pMainFrame->m_hMenuDefault = pMainFrame->NewDefaultMenu();
IDD_OPEN DIALOGEX 0, 0, 460, 260
STYLE DS_CENTER | DS_SETFONT | DS_FIXEDSYS | WS_CHILD
-EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Select Files or Folders"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
RTEXT "&1:",IDC_STATIC,13,84,65,8
CONTROL "",IDC_PATH0_COMBO,"ComboBoxEx32",CBS_DROPDOWN |
CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP,
- 81,82,367,94,WS_EX_ACCEPTFILES
+ 81,82,367,94
PUSHBUTTON "",IDC_SWAP01_BUTTON,384,98,15,14
PUSHBUTTON "&Browse...",IDC_PATH0_BUTTON,402,98,50,14
RTEXT "&2:",IDC_STATIC,13,116,65,8
CONTROL "",IDC_PATH1_COMBO,"ComboBoxEx32",CBS_DROPDOWN |
CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP
- ,81,114,367,95,WS_EX_ACCEPTFILES
+ ,81,114,367,95
PUSHBUTTON "",IDC_SWAP12_BUTTON,384,130,15,14
PUSHBUTTON "B&rowse...",IDC_PATH1_BUTTON,402,130,50,14
RTEXT "&3(Optional):",IDC_STATIC,13,148,65,8
CONTROL "",IDC_PATH2_COMBO,"ComboBoxEx32",CBS_DROPDOWN |
CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP,
- 81,146,367,95,WS_EX_ACCEPTFILES
+ 81,146,367,95
PUSHBUTTON "",IDC_SWAP02_BUTTON,384,162,15,14
PUSHBUTTON "Br&owse...",IDC_PATH2_BUTTON,402,162,50,14
RTEXT "Fi<er:",IDC_STATIC,13,178,65,8
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='UnicodeRelease|x64'">NotUsing</PrecompiledHeader>\r
</ClCompile>\r
<ClCompile Include="Common\ColorButton.cpp" />\r
- <ClCompile Include="Common\DragDrop.cpp">\r
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>\r
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='UnicodeDebug|Win32'">NotUsing</PrecompiledHeader>\r
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug Unicode + Code Analysis|Win32'">NotUsing</PrecompiledHeader>\r
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='UnicodeRelease|Win32'">NotUsing</PrecompiledHeader>\r
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>\r
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>\r
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='UnicodeDebug|x64'">NotUsing</PrecompiledHeader>\r
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug Unicode + Code Analysis|x64'">NotUsing</PrecompiledHeader>\r
- <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='UnicodeRelease|x64'">NotUsing</PrecompiledHeader>\r
- </ClCompile>\r
<ClCompile Include="Common\ExConverter.cpp">\r
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>\r
</ClCompile>\r
<ClCompile Include="Common\CSubclass.cpp">\r
</ClCompile>\r
+ <ClCompile Include="DropHandler.cpp">\r
+ </ClCompile>\r
<ClCompile Include="ImgMergeFrm.cpp" />\r
<ClCompile Include="Merge7zFormatMergePluginImpl.cpp">\r
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
<ClInclude Include="codepage.h" />\r
<ClInclude Include="codepage_detect.h" />\r
<ClInclude Include="Common\ColorButton.h" />\r
- <ClInclude Include="Common\DragDrop.h" />\r
<ClInclude Include="Common\ExConverter.h" />\r
<ClInclude Include="CompareEngines\BinaryCompare.h" />\r
<ClInclude Include="CompareOptions.h" />\r
<ClInclude Include="Common\coretypes.h" />\r
<ClInclude Include="Common\CSubclass.h" />\r
<ClInclude Include="HexMergeView.h" />\r
+ <ClInclude Include="DropHandler.h" />\r
<ClInclude Include="IMergeDoc.h" />\r
<ClInclude Include="ImgMergeFrm.h" />\r
<ClInclude Include="Merge7zFormatMergePluginImpl.h" />\r
<ClCompile Include="JumpList.cpp">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
- <ClCompile Include="Common\DragDrop.cpp">\r
- <Filter>Source Files</Filter>\r
- </ClCompile>\r
<ClCompile Include="Common\ClipBoard.cpp">\r
<Filter>Source Files</Filter>\r
</ClCompile>\r
<ClCompile Include="Common\ColorButton.cpp">\r
<Filter>MFCGui\Common</Filter>\r
</ClCompile>\r
+ <ClCompile Include="DropHandler.cpp">\r
+ <Filter>MFCGui\Source Files</Filter>\r
+ </ClCompile>\r
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="charsets.h">\r
<ClInclude Include="JumpList.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
- <ClInclude Include="Common\DragDrop.h">\r
- <Filter>Header Files</Filter>\r
- </ClInclude>\r
<ClInclude Include="Common\ClipBoard.h">\r
<Filter>Header Files</Filter>\r
</ClInclude>\r
<ClInclude Include="Common\Picture.h">\r
<Filter>MFCGui\Common</Filter>\r
</ClInclude>\r
+ <ClInclude Include="DropHandler.h">\r
+ <Filter>MFCGui\Header Files</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<None Include="res\binarydiff.ico">\r
#include "7zCommon.h"
#include "Constants.h"
#include "Picture.h"
-#include "DragDrop.h"
+#include "DropHandler.h"
#include "FileFilterHelper.h"
#include "Plugins.h"
ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
ON_COMMAND(ID_EDIT_CUT, OnEditCut)
ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
- ON_WM_DROPFILES()
ON_MESSAGE(WM_USER + 1, OnUpdateStatus)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
: CFormView(COpenView::IDD)
, m_pUpdateButtonStatusThread(NULL)
, m_bRecurse(FALSE)
+ , m_pDropHandler(NULL)
{
m_bAutoCompleteReady[0] = false;
m_bAutoCompleteReady[1] = false;
UpdateData(FALSE);
SetStatus(IDS_OPEN_FILESDIRS);
SetUnpackerStatus(IDS_OPEN_UNPACKERDISABLED);
+
+ m_pDropHandler = new DropHandler(std::bind(&COpenView::OnDropFiles, this, std::placeholders::_1));
+ RegisterDragDrop(m_hWnd, m_pDropHandler);
}
// COpenView diagnostics
void COpenView::OnDestroy()
{
+ if (m_pDropHandler)
+ RevokeDragDrop(m_hWnd);
+
m_constraint.Persist(true, false);
CFormView::OnDestroy();
* - overwrite both paths, empty or not
* @param [in] dropInfo Dropped data, including paths.
*/
-void COpenView::OnDropFiles(HDROP dropInfo)
+void COpenView::OnDropFiles(const std::vector<String>& files)
{
- std::vector<String> files;
- GetDroppedFiles(dropInfo, files);
const size_t fileCount = files.size();
// Add dropped paths to the dialog
class ProjectFile;
class COpenDoc;
+class DropHandler;
/**
* @brief The Open-View class.
prdlg::CMoveConstraint m_constraint;
CFont m_fontSwapButton;
bool m_bAutoCompleteReady[3];
+ DropHandler *m_pDropHandler;
// Overrides
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
afx_msg void OnEditPaste();
afx_msg void OnEditUndo();
afx_msg void OnHelp();
- afx_msg void OnDropFiles(HDROP dropInfo);
+ afx_msg void OnDropFiles(const std::vector<String>& files);
afx_msg LRESULT OnUpdateStatus(WPARAM wParam, LPARAM lParam);
afx_msg void OnPaint();
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
{
return (path.find(_T("://")) != String::npos || path.find(_T("::{")) != String::npos);
}
+
+bool paths_IsDecendant(const String& path, const String& ancestor)
+{
+ return path.length() > ancestor.length() &&
+ string_compare_nocase(String(path.c_str(), path.c_str() + ancestor.length()), ancestor) == 0;
+}
void paths_SplitViewName(const TCHAR *s, String * path, String * name, String * ext);
String paths_GetPathOnly(const String& fullpath);
bool paths_IsURLorCLSID(const String& path);
+bool paths_IsDecendant(const String& path, const String& ancestor);