New-style Windows cursors when dragging object from outside
authorCyril Oblikov <munknex@gmail.com>
Tue, 23 Oct 2012 15:00:58 +0000 (18:00 +0300)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Fri, 26 Oct 2012 09:00:04 +0000 (11:00 +0200)
New-style drag&drop cursors are used now on Windows when user drags
object to application from outside (e.g. image from Explorer). This is
achieved by using IDropTargetHelper.

Change-Id: I67e1db73cf433e235fce891eef0093cd4e605904
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
src/plugins/platforms/windows/qwindowsdrag.cpp
src/plugins/platforms/windows/qwindowsdrag.h

index f74b214..ad2ff22 100644 (file)
@@ -595,6 +595,9 @@ QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
 QWindowsOleDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState,
                                  POINTL pt, LPDWORD pdwEffect)
 {
+    if (IDropTargetHelper* dh = QWindowsDrag::instance()->dropHelper())
+        dh->DragEnter(reinterpret_cast<HWND>(m_window->winId()), pDataObj, reinterpret_cast<POINT*>(&pt), *pdwEffect);
+
     if (QWindowsContext::verboseOLE)
         qDebug("%s widget=%p key=%lu, pt=%ld,%ld", __FUNCTION__, m_window, grfKeyState, pt.x, pt.y);
 
@@ -608,6 +611,9 @@ QWindowsOleDropTarget::DragEnter(LPDATAOBJECT pDataObj, DWORD grfKeyState,
 QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
 QWindowsOleDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
 {
+    if (IDropTargetHelper* dh = QWindowsDrag::instance()->dropHelper())
+        dh->DragOver(reinterpret_cast<POINT*>(&pt), *pdwEffect);
+
     QWindow *dragOverWindow = findDragOverWindow(pt);
     if (QWindowsContext::verboseOLE)
         qDebug("%s widget=%p key=%lu, pt=%ld,%ld", __FUNCTION__, dragOverWindow, grfKeyState, pt.x, pt.y);
@@ -628,6 +634,9 @@ QWindowsOleDropTarget::DragOver(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect)
 QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
 QWindowsOleDropTarget::DragLeave()
 {
+    if (IDropTargetHelper* dh = QWindowsDrag::instance()->dropHelper())
+        dh->DragLeave();
+
     if (QWindowsContext::verboseOLE)
         qDebug().nospace() <<__FUNCTION__ << ' ' << m_window;
 
@@ -640,9 +649,12 @@ QWindowsOleDropTarget::DragLeave()
 #define KEY_STATE_BUTTON_MASK (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)
 
 QT_ENSURE_STACK_ALIGNED_FOR_SSE STDMETHODIMP
-QWindowsOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState,
+QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
                             POINTL pt, LPDWORD pdwEffect)
 {
+    if (IDropTargetHelper* dh = QWindowsDrag::instance()->dropHelper())
+        dh->Drop(pDataObj, reinterpret_cast<POINT*>(&pt), *pdwEffect);
+
     QWindow *dropWindow = findDragOverWindow(pt);
 
     if (QWindowsContext::verboseOLE)
@@ -700,6 +712,10 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState,
     return NOERROR;
 }
 
+#if defined(Q_CC_MINGW) && !defined(_WIN32_IE)
+# define _WIN32_IE 0x0501
+#endif
+
 /*!
     \class QWindowsDrag
     \brief Windows drag implementation.
@@ -707,12 +723,15 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT /*pDataObj*/, DWORD grfKeyState,
     \ingroup qt-lighthouse-win
 */
 
-QWindowsDrag::QWindowsDrag() : m_dropDataObject(0)
+QWindowsDrag::QWindowsDrag() :
+    m_dropDataObject(0), m_cachedDropTargetHelper(0)
 {
 }
 
 QWindowsDrag::~QWindowsDrag()
 {
+    if (m_cachedDropTargetHelper)
+        m_cachedDropTargetHelper->Release();
 }
 
 /*!
@@ -726,6 +745,18 @@ QMimeData *QWindowsDrag::dropData()
     return &m_dropData;
 }
 
+/*!
+    \brief May be used to handle extended cursors functionality for drags from outside the app.
+*/
+IDropTargetHelper* QWindowsDrag::dropHelper() {
+    if (!m_cachedDropTargetHelper) {
+        CoCreateInstance(CLSID_DragDropHelper, 0, CLSCTX_INPROC_SERVER,
+                         IID_IDropTargetHelper,
+                         reinterpret_cast<void**>(&m_cachedDropTargetHelper));
+    }
+    return m_cachedDropTargetHelper;
+}
+
 QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const
 {
     switch (action) {
index ab06545..d3bfd36 100644 (file)
@@ -47,6 +47,8 @@
 #include <qpa/qplatformdrag.h>
 #include <QtGui/QPixmap>
 
+struct IDropTargetHelper;
+
 QT_BEGIN_NAMESPACE
 class QWindowsDropMimeData : public QWindowsInternalMimeData {
 public:
@@ -100,12 +102,16 @@ public:
     void releaseDropDataObject();
     QMimeData *dropData();
 
+    IDropTargetHelper* dropHelper();
+
     QPixmap defaultCursor(Qt::DropAction action) const;
 
 private:
     QWindowsDropMimeData m_dropData;
     IDataObject *m_dropDataObject;
 
+    IDropTargetHelper* m_cachedDropTargetHelper;
+
     mutable QPixmap m_copyDragCursor;
     mutable QPixmap m_moveDragCursor;
     mutable QPixmap m_linkDragCursor;