Skip to content

Commit

Permalink
Move Windows dependent code from ClipBoard.h to Clipboard.cpp
Browse files Browse the repository at this point in the history
  • Loading branch information
sdottaka committed Mar 17, 2023
1 parent 00f0c57 commit 6e48a97
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 64 deletions.
2 changes: 1 addition & 1 deletion Src/ClipboardHistory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ namespace ClipboardHistory
String GetClipboardText()
{
String text;
GetFromClipboard(text, nullptr);
GetFromClipboard(text);
return text;
}

Expand Down
67 changes: 64 additions & 3 deletions Src/Common/ClipBoard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@

#include "pch.h"
#include "ClipBoard.h"
#include <ShlObj.h>

inline CLIPFORMAT GetClipTcharTextFormat() { return (sizeof(tchar_t) == 1 ? CF_TEXT : CF_UNICODETEXT); }

/**
* @brief Copies string to clipboard.
* @param [in] text Text to copy to clipboard.
* @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<HWND>(const String & text, HWND currentWindowHandle)
{
if (text.empty())
return false;
Expand Down Expand Up @@ -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);
Expand All @@ -66,3 +70,60 @@ bool GetFromClipboard(String & text, HWND currentWindowHandle)
}
return bSuccess;
}

template<>
void PutFilesToClipboardInternal<HWND>(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<tchar_t*>(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<DWORD*>(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();
}
}

71 changes: 11 additions & 60 deletions Src/Common/ClipBoard.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,21 @@
*/
#pragma once

#include <windows.h>
#include "UnicodeString.h"

inline CLIPFORMAT GetClipTcharTextFormat() { return (sizeof(tchar_t) == 1 ? CF_TEXT : CF_UNICODETEXT); }
template<typename WindowHandle>
bool PutToClipboard(const String & text, WindowHandle currentWindowHandle);
bool GetFromClipboard(String & text);
template<typename WindowHandle>
void PutFilesToClipboardInternal(const String& strPaths, const String& strPathsSepSpc, WindowHandle currentWindowHandle);

bool PutToClipboard(const String & text, HWND currentWindowHandle);
bool GetFromClipboard(String & text, HWND currentWindowHandle);

template<class Container>
void PutFilesToClipboard(const Container& list, HWND currentWindowHandle)
template<class Container, typename WindowHandle>
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)
{
Expand All @@ -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<tchar_t *>(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<DWORD *>(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);
}

0 comments on commit 6e48a97

Please sign in to comment.