diff --git a/Src/ClipboardHistory.cpp b/Src/ClipboardHistory.cpp index e554a2d8066..092bb511cdf 100644 --- a/Src/ClipboardHistory.cpp +++ b/Src/ClipboardHistory.cpp @@ -50,7 +50,7 @@ namespace ClipboardHistory String GetClipboardText() { String text; - GetFromClipboard(text, nullptr); + GetFromClipboard(text); return text; } diff --git a/Src/Common/ClipBoard.cpp b/Src/Common/ClipBoard.cpp index c4e56c478ee..a8580133bf0 100644 --- a/Src/Common/ClipBoard.cpp +++ b/Src/Common/ClipBoard.cpp @@ -6,6 +6,9 @@ #include "pch.h" #include "ClipBoard.h" +#include + +inline CLIPFORMAT GetClipTcharTextFormat() { return (sizeof(tchar_t) == 1 ? CF_TEXT : CF_UNICODETEXT); } /** * @brief Copies string to clipboard. @@ -13,7 +16,8 @@ * @param [in] currentWindowHandle Handle to current window. * @return `true` if text copying succeeds, `false` otherwise. */ -bool PutToClipboard(const String & text, HWND currentWindowHandle) +template<> +bool PutToClipboard(const String & text, HWND currentWindowHandle) { if (text.empty()) return false; @@ -45,10 +49,10 @@ bool PutToClipboard(const String & text, HWND currentWindowHandle) * @param [in] currentWindowHandle Handle to current window. * @return `true` if retrieving the clipboard text succeeds, `false` otherwise. */ -bool GetFromClipboard(String & text, HWND currentWindowHandle) +bool GetFromClipboard(String & text) { bool bSuccess = false; - if (OpenClipboard(currentWindowHandle)) + if (OpenClipboard(nullptr)) { CLIPFORMAT fmt = GetClipTcharTextFormat(); HGLOBAL hData = GetClipboardData(fmt); @@ -66,3 +70,60 @@ bool GetFromClipboard(String & text, HWND currentWindowHandle) } return bSuccess; } + +template<> +void PutFilesToClipboardInternal(const String& strPaths, const String& strPathsSepSpc, HWND currentWindowHandle) +{ + // CF_HDROP + HGLOBAL hDrop = GlobalAlloc(GHND, sizeof(DROPFILES) + sizeof(tchar_t) * strPaths.length()); + if (hDrop == nullptr) + return; + if (tchar_t* pDrop = static_cast(GlobalLock(hDrop))) + { + DROPFILES df = { 0 }; + df.pFiles = sizeof(DROPFILES); + df.fWide = (sizeof(tchar_t) > 1); + memcpy(pDrop, &df, sizeof(DROPFILES)); + memcpy((BYTE*)pDrop + sizeof(DROPFILES), (const tchar_t*)strPaths.c_str(), sizeof(tchar_t) * strPaths.length()); + GlobalUnlock(hDrop); + } + + // CF_DROPEFFECT + HGLOBAL hDropEffect = GlobalAlloc(GHND, sizeof(DWORD)); + if (hDropEffect == nullptr) + { + GlobalFree(hDrop); + return; + } + if (DWORD* p = static_cast(GlobalLock(hDropEffect))) + { + *p = DROPEFFECT_COPY; + GlobalUnlock(hDropEffect); + } + + // CF_UNICODETEXT + HGLOBAL hPathnames = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(tchar_t) * (strPathsSepSpc.length() + 1)); + if (hPathnames == nullptr) + { + GlobalFree(hDrop); + GlobalFree(hDropEffect); + return; + } + if (void* pPathnames = GlobalLock(hPathnames)) + { + memcpy((BYTE*)pPathnames, (const tchar_t*)strPathsSepSpc.c_str(), sizeof(tchar_t) * strPathsSepSpc.length()); + ((tchar_t*)pPathnames)[strPathsSepSpc.length()] = 0; + GlobalUnlock(hPathnames); + } + + UINT CF_DROPEFFECT = RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT); + if (::OpenClipboard(currentWindowHandle)) + { + EmptyClipboard(); + SetClipboardData(CF_HDROP, hDrop); + SetClipboardData(CF_DROPEFFECT, hDropEffect); + SetClipboardData(GetClipTcharTextFormat(), hPathnames); + CloseClipboard(); + } +} + diff --git a/Src/Common/ClipBoard.h b/Src/Common/ClipBoard.h index 2d50f7b5207..43e1d983287 100644 --- a/Src/Common/ClipBoard.h +++ b/Src/Common/ClipBoard.h @@ -5,20 +5,21 @@ */ #pragma once -#include #include "UnicodeString.h" -inline CLIPFORMAT GetClipTcharTextFormat() { return (sizeof(tchar_t) == 1 ? CF_TEXT : CF_UNICODETEXT); } +template +bool PutToClipboard(const String & text, WindowHandle currentWindowHandle); +bool GetFromClipboard(String & text); +template +void PutFilesToClipboardInternal(const String& strPaths, const String& strPathsSepSpc, WindowHandle currentWindowHandle); -bool PutToClipboard(const String & text, HWND currentWindowHandle); -bool GetFromClipboard(String & text, HWND currentWindowHandle); - -template -void PutFilesToClipboard(const Container& list, HWND currentWindowHandle) +template +void PutFilesToClipboard(const Container& list, WindowHandle currentWindowHandle) { + constexpr size_t MaxPathFull = 32767; String strPaths, strPathsSepSpc; - strPaths.reserve(list.size() * MAX_PATH_FULL); - strPathsSepSpc.reserve(list.size() * MAX_PATH_FULL); + strPaths.reserve(list.size() * MaxPathFull); + strPathsSepSpc.reserve(list.size() * MaxPathFull); for (Container::const_iterator it = list.begin(); it != list.end(); ++it) { @@ -35,55 +36,5 @@ void PutFilesToClipboard(const Container& list, HWND currentWindowHandle) strPaths += _T('\0'); strPathsSepSpc = strutils::trim_ws_end(strPathsSepSpc); - // CF_HDROP - HGLOBAL hDrop = GlobalAlloc(GHND, sizeof(DROPFILES) + sizeof(tchar_t) * strPaths.length()); - if (hDrop == nullptr) - return; - if (tchar_t *pDrop = static_cast(GlobalLock(hDrop))) - { - DROPFILES df = {0}; - df.pFiles = sizeof(DROPFILES); - df.fWide = (sizeof(tchar_t) > 1); - memcpy(pDrop, &df, sizeof(DROPFILES)); - memcpy((BYTE *)pDrop + sizeof(DROPFILES), (const tchar_t*)strPaths.c_str(), sizeof(tchar_t) * strPaths.length()); - GlobalUnlock(hDrop); - } - - // CF_DROPEFFECT - HGLOBAL hDropEffect = GlobalAlloc(GHND, sizeof(DWORD)); - if (hDropEffect == nullptr) - { - GlobalFree(hDrop); - return; - } - if (DWORD *p = static_cast(GlobalLock(hDropEffect))) - { - *p = DROPEFFECT_COPY; - GlobalUnlock(hDropEffect); - } - - // CF_UNICODETEXT - HGLOBAL hPathnames = GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, sizeof(tchar_t) * (strPathsSepSpc.length() + 1)); - if (hPathnames == nullptr) - { - GlobalFree(hDrop); - GlobalFree(hDropEffect); - return; - } - if (void *pPathnames = GlobalLock(hPathnames)) - { - memcpy((BYTE *)pPathnames, (const tchar_t*)strPathsSepSpc.c_str(), sizeof(tchar_t) * strPathsSepSpc.length()); - ((tchar_t *)pPathnames)[strPathsSepSpc.length()] = 0; - GlobalUnlock(hPathnames); - } - - UINT CF_DROPEFFECT = RegisterClipboardFormat(CFSTR_PREFERREDDROPEFFECT); - if (::OpenClipboard(AfxGetMainWnd()->GetSafeHwnd())) - { - EmptyClipboard(); - SetClipboardData(CF_HDROP, hDrop); - SetClipboardData(CF_DROPEFFECT, hDropEffect); - SetClipboardData(GetClipTcharTextFormat(), hPathnames); - CloseClipboard(); - } + PutFilesToClipboardInternal(strPaths, strPathsSepSpc, currentWindowHandle); }