Browse Source

Fixed a scaling problem with file drag+drop on Windows

tags/2021-05-28
jules 8 years ago
parent
commit
84a4dc0faa
2 changed files with 75 additions and 102 deletions
  1. +21
    -32
      modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp
  2. +54
    -70
      modules/juce_gui_basics/native/juce_win32_Windowing.cpp

+ 21
- 32
modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp View File

@@ -27,12 +27,11 @@
namespace DragAndDropHelpers
{
//==============================================================================
class JuceDropSource : public ComBaseClassHelper <IDropSource>
struct JuceDropSource : public ComBaseClassHelper<IDropSource>
{
public:
JuceDropSource() {}
JUCE_COMRESULT QueryContinueDrag (BOOL escapePressed, DWORD keys)
JUCE_COMRESULT QueryContinueDrag (BOOL escapePressed, DWORD keys) override
{
if (escapePressed)
return DRAGDROP_S_CANCEL;
@@ -43,35 +42,29 @@ namespace DragAndDropHelpers
return S_OK;
}
JUCE_COMRESULT GiveFeedback (DWORD)
JUCE_COMRESULT GiveFeedback (DWORD) override
{
return DRAGDROP_S_USEDEFAULTCURSORS;
}
};
//==============================================================================
class JuceEnumFormatEtc : public ComBaseClassHelper <IEnumFORMATETC>
struct JuceEnumFormatEtc : public ComBaseClassHelper<IEnumFORMATETC>
{
public:
JuceEnumFormatEtc (const FORMATETC* const format_)
: format (format_),
index (0)
{
}
JuceEnumFormatEtc (const FORMATETC* f) : format (f) {}
JUCE_COMRESULT Clone (IEnumFORMATETC** result)
JUCE_COMRESULT Clone (IEnumFORMATETC** result) override
{
if (result == 0)
return E_POINTER;
JuceEnumFormatEtc* const newOne = new JuceEnumFormatEtc (format);
auto newOne = new JuceEnumFormatEtc (format);
newOne->index = index;
*result = newOne;
return S_OK;
}
JUCE_COMRESULT Next (ULONG celt, LPFORMATETC lpFormatEtc, ULONG* pceltFetched)
JUCE_COMRESULT Next (ULONG celt, LPFORMATETC lpFormatEtc, ULONG* pceltFetched) override
{
if (pceltFetched != nullptr)
*pceltFetched = 0;
@@ -92,7 +85,7 @@ namespace DragAndDropHelpers
return S_FALSE;
}
JUCE_COMRESULT Skip (ULONG celt)
JUCE_COMRESULT Skip (ULONG celt) override
{
if (index + (int) celt >= 1)
return S_FALSE;
@@ -101,7 +94,7 @@ namespace DragAndDropHelpers
return S_OK;
}
JUCE_COMRESULT Reset()
JUCE_COMRESULT Reset() override
{
index = 0;
return S_OK;
@@ -109,7 +102,7 @@ namespace DragAndDropHelpers
private:
const FORMATETC* const format;
int index;
int index = 0;
static void copyFormatEtc (FORMATETC& dest, const FORMATETC& source)
{
@@ -129,12 +122,8 @@ namespace DragAndDropHelpers
class JuceDataObject : public ComBaseClassHelper <IDataObject>
{
public:
JuceDataObject (JuceDropSource* const dropSource_,
const FORMATETC* const format_,
const STGMEDIUM* const medium_)
: dropSource (dropSource_),
format (format_),
medium (medium_)
JuceDataObject (JuceDropSource* s, const FORMATETC* f, const STGMEDIUM* m)
: dropSource (s), format (f), medium (m)
{
}
@@ -154,7 +143,7 @@ namespace DragAndDropHelpers
if (format->tymed == TYMED_HGLOBAL)
{
const SIZE_T len = GlobalSize (medium->hGlobal);
auto len = GlobalSize (medium->hGlobal);
void* const src = GlobalLock (medium->hGlobal);
void* const dst = GlobalAlloc (GMEM_FIXED, len);
@@ -229,15 +218,15 @@ namespace DragAndDropHelpers
if (hDrop != 0)
{
LPDROPFILES pDropFiles = (LPDROPFILES) GlobalLock (hDrop);
auto pDropFiles = (LPDROPFILES) GlobalLock (hDrop);
pDropFiles->pFiles = sizeof (DROPFILES);
pDropFiles->fWide = true;
WCHAR* fname = reinterpret_cast<WCHAR*> (addBytesToPointer (pDropFiles, sizeof (DROPFILES)));
auto* fname = reinterpret_cast<WCHAR*> (addBytesToPointer (pDropFiles, sizeof (DROPFILES)));
for (int i = 0; i < fileNames.size(); ++i)
{
const size_t bytesWritten = fileNames[i].copyToUTF16 (fname, 2048);
auto bytesWritten = fileNames[i].copyToUTF16 (fname, 2048);
fname = reinterpret_cast<WCHAR*> (addBytesToPointer (fname, bytesWritten));
}
@@ -251,11 +240,11 @@ namespace DragAndDropHelpers
bool performDragDrop (FORMATETC* const format, STGMEDIUM* const medium, const DWORD whatToDo)
{
JuceDropSource* const source = new JuceDropSource();
JuceDataObject* const data = new JuceDataObject (source, format, medium);
auto source = new JuceDropSource();
auto data = new JuceDataObject (source, format, medium);
DWORD effect;
const HRESULT res = DoDragDrop (data, source, whatToDo, &effect);
auto res = DoDragDrop (data, source, whatToDo, &effect);
data->Release();
source->Release();
@@ -281,7 +270,7 @@ bool DragAndDropContainer::performExternalDragDropOfText (const String& text)
FORMATETC format = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM medium = { TYMED_HGLOBAL, { 0 }, 0 };
const size_t numBytes = CharPointer_UTF16::getBytesRequiredFor (text.getCharPointer());
auto numBytes = CharPointer_UTF16::getBytesRequiredFor (text.getCharPointer());
medium.hGlobal = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, numBytes + 2);
WCHAR* const data = static_cast<WCHAR*> (GlobalLock (medium.hGlobal));


+ 54
- 70
modules/juce_gui_basics/native/juce_win32_Windowing.cpp View File

@@ -975,7 +975,7 @@ public:
if (dropTarget != nullptr)
{
dropTarget->clear();
dropTarget->peerIsDeleted = true;
dropTarget->Release();
dropTarget = nullptr;
}
@@ -1356,102 +1356,86 @@ public:
static ModifierKeys modifiersAtLastCallback;
//==============================================================================
class JuceDropTarget : public ComBaseClassHelper<IDropTarget>
struct FileDropTarget : public ComBaseClassHelper<IDropTarget>
{
public:
JuceDropTarget (HWNDComponentPeer& p) : ownerInfo (new OwnerInfo (p)) {}
void clear()
{
ownerInfo = nullptr;
}
FileDropTarget (HWNDComponentPeer& p) : peer (p) {}
JUCE_COMRESULT DragEnter (IDataObject* pDataObject, DWORD grfKeyState, POINTL mousePos, DWORD* pdwEffect)
JUCE_COMRESULT DragEnter (IDataObject* pDataObject, DWORD grfKeyState, POINTL mousePos, DWORD* pdwEffect) override
{
HRESULT hr = updateFileList (pDataObject);
auto hr = updateFileList (pDataObject);
if (FAILED (hr))
return hr;
return DragOver (grfKeyState, mousePos, pdwEffect);
}
JUCE_COMRESULT DragLeave()
JUCE_COMRESULT DragLeave() override
{
if (ownerInfo == nullptr)
if (peerIsDeleted)
return S_FALSE;
ownerInfo->owner.handleDragExit (ownerInfo->dragInfo);
peer.handleDragExit (dragInfo);
return S_OK;
}
JUCE_COMRESULT DragOver (DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect)
JUCE_COMRESULT DragOver (DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect) override
{
if (ownerInfo == nullptr)
if (peerIsDeleted)
return S_FALSE;
ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos).roundToInt();
const bool wasWanted = ownerInfo->owner.handleDragMove (ownerInfo->dragInfo);
*pdwEffect = wasWanted ? (DWORD) DROPEFFECT_COPY : (DWORD) DROPEFFECT_NONE;
dragInfo.position = getMousePos (mousePos).roundToInt();
*pdwEffect = peer.handleDragMove (dragInfo) ? (DWORD) DROPEFFECT_COPY
: (DWORD) DROPEFFECT_NONE;
return S_OK;
}
JUCE_COMRESULT Drop (IDataObject* pDataObject, DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect)
JUCE_COMRESULT Drop (IDataObject* pDataObject, DWORD /*grfKeyState*/, POINTL mousePos, DWORD* pdwEffect) override
{
HRESULT hr = updateFileList (pDataObject);
if (SUCCEEDED (hr))
{
ownerInfo->dragInfo.position = ownerInfo->getMousePos (mousePos).roundToInt();
const bool wasWanted = ownerInfo->owner.handleDragDrop (ownerInfo->dragInfo);
*pdwEffect = wasWanted ? (DWORD) DROPEFFECT_COPY : (DWORD) DROPEFFECT_NONE;
hr = S_OK;
}
if (FAILED (hr))
return hr;
return hr;
dragInfo.position = getMousePos (mousePos).roundToInt();
*pdwEffect = peer.handleDragDrop (dragInfo) ? (DWORD) DROPEFFECT_COPY
: (DWORD) DROPEFFECT_NONE;
return S_OK;
}
HWNDComponentPeer& peer;
ComponentPeer::DragInfo dragInfo;
bool peerIsDeleted = false;
private:
struct OwnerInfo
Point<float> getMousePos (POINTL mousePos) const
{
OwnerInfo (HWNDComponentPeer& p) : owner (p) {}
auto& comp = peer.getComponent();
return comp.getLocalPoint (nullptr, ScalingHelpers::unscaledScreenPosToScaled (comp.getDesktopScaleFactor(),
Point<float> (static_cast<float> (mousePos.x),
static_cast<float> (mousePos.y))));
}
Point<float> getMousePos (const POINTL& mousePos) const
{
return owner.globalToLocal (ScalingHelpers::unscaledScreenPosToScaled (owner.getComponent().getDesktopScaleFactor(),
Point<float> (static_cast<float> (mousePos.x),
static_cast<float> (mousePos.y))));
}
template <typename CharType>
void parseFileList (const CharType* names, const SIZE_T totalLen)
{
unsigned int i = 0;
template <typename CharType>
void parseFileList (const CharType* names, const SIZE_T totalLen)
for (;;)
{
unsigned int i = 0;
for (;;)
{
unsigned int len = 0;
while (i + len < totalLen && names [i + len] != 0)
++len;
unsigned int len = 0;
while (i + len < totalLen && names [i + len] != 0)
++len;
if (len == 0)
break;
if (len == 0)
break;
dragInfo.files.add (String (names + i, len));
i += len + 1;
}
dragInfo.files.add (String (names + i, len));
i += len + 1;
}
HWNDComponentPeer& owner;
ComponentPeer::DragInfo dragInfo;
JUCE_DECLARE_NON_COPYABLE (OwnerInfo)
};
ScopedPointer<OwnerInfo> ownerInfo;
}
struct DroppedData
{
DroppedData (IDataObject* const dataObject, const CLIPFORMAT type)
: data (nullptr)
DroppedData (IDataObject* dataObject, CLIPFORMAT type)
{
FORMATETC format = { type, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM resetMedium = { TYMED_HGLOBAL, { 0 }, 0 };
@@ -1472,16 +1456,16 @@ public:
HRESULT error;
STGMEDIUM medium;
void* data;
void* data = {};
SIZE_T dataSize;
};
HRESULT updateFileList (IDataObject* const dataObject)
{
if (ownerInfo == nullptr)
if (peerIsDeleted)
return S_FALSE;
ownerInfo->dragInfo.clear();
dragInfo.clear();
{
DroppedData fileData (dataObject, CF_HDROP);
@@ -1492,9 +1476,9 @@ public:
const void* const names = addBytesToPointer (dropFiles, sizeof (DROPFILES));
if (dropFiles->fWide)
ownerInfo->parseFileList (static_cast<const WCHAR*> (names), fileData.dataSize);
parseFileList (static_cast<const WCHAR*> (names), fileData.dataSize);
else
ownerInfo->parseFileList (static_cast<const char*> (names), fileData.dataSize);
parseFileList (static_cast<const char*> (names), fileData.dataSize);
return S_OK;
}
@@ -1504,15 +1488,15 @@ public:
if (SUCCEEDED (textData.error))
{
ownerInfo->dragInfo.text = String (CharPointer_UTF16 ((const WCHAR*) textData.data),
CharPointer_UTF16 ((const WCHAR*) addBytesToPointer (textData.data, textData.dataSize)));
dragInfo.text = String (CharPointer_UTF16 ((const WCHAR*) textData.data),
CharPointer_UTF16 ((const WCHAR*) addBytesToPointer (textData.data, textData.dataSize)));
return S_OK;
}
return textData.error;
}
JUCE_DECLARE_NON_COPYABLE (JuceDropTarget)
JUCE_DECLARE_NON_COPYABLE (FileDropTarget)
};
static bool offerKeyMessageToJUCEWindow (MSG& m)
@@ -1539,7 +1523,7 @@ private:
hasCreatedCaret = false, constrainerIsResizing = false;
BorderSize<int> windowBorder;
HICON currentWindowIcon = 0;
JuceDropTarget* dropTarget = nullptr;
FileDropTarget* dropTarget = nullptr;
uint8 updateLayeredWindowAlpha = 255;
UWPUIViewSettings uwpViewSettings;
MultiTouchMapper<DWORD> currentTouches;
@@ -1771,7 +1755,7 @@ private:
if (peer == nullptr)
peer = this;
dropTarget = new JuceDropTarget (*peer);
dropTarget = new FileDropTarget (*peer);
}
RegisterDragDrop (hwnd, dropTarget);


Loading…
Cancel
Save