HRESULT WinCE_DoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource, DWORD dwOKEffects, LPDWORD pdwEffect) { MSG msg; POINT dest = {0,0}; POINT lastDraw = {-1,-1}; DWORD effect = DROPEFFECT_NONE; DWORD lastEffect = -1; IDropTarget * currentTarget = NULL; IWebViewPrivate * webView = NULL; IDataObject * dataObject = pDataObj; IDropSource * dropSource = pDropSource; HRESULT feedbackHR = DRAGDROP_S_USEDEFAULTCURSORS; HCURSOR startCursor = ::GetCursor(); HCURSOR noCursor = LoadCursor(NULL, IDC_NO); // If there is a change in the keyboard or mouse button state, DoDragDrop calls // IDropSource::QueryContinueDrag and determines whether to continue the drag, to // drop the data, or to cancel the operation based on the return value. BOOL escapePressed = FALSE; DWORD keyState = MK_LBUTTON; if (GetKeyState(VK_CONTROL) & HIGH_BIT_MASK_SHORT) keyState |= MK_CONTROL; if (GetKeyState(VK_SHIFT) & HIGH_BIT_MASK_SHORT) keyState |= MK_SHIFT; HRESULT result = dropSource->QueryContinueDrag(escapePressed, keyState); bool dragActive = (result == S_OK); POINTL screenPoint; while (dragActive && GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); // Filter all mouse and key events during the drag and drop: if (msg.message == WM_LBUTTONUP || msg.message == WM_LBUTTONDOWN || msg.message == WM_RBUTTONUP || msg.message == WM_RBUTTONDOWN || msg.message == WM_MOUSEMOVE || msg.message == WM_KEYDOWN || msg.message == WM_KEYUP || msg.message == WM_CHAR || msg.message == WM_SYSKEYDOWN || msg.message == WM_SYSKEYUP || msg.message == WM_SYSCHAR) { if (msg.message == WM_MOUSEMOVE) { PERFORMANCE_START(WTF::PerformanceTrace::InputEvent,"DragDropManager: Mouse Move"); } else if (msg.message == WM_LBUTTONUP) { PERFORMANCE_START(WTF::PerformanceTrace::InputEvent,"DragDropManager: Mouse Up"); } else { PERFORMANCE_START(WTF::PerformanceTrace::InputEvent,"DragDropManager: Other Input"); } bool stateChanged = false; if (msg.message == WM_MOUSEMOVE || msg.message == WM_LBUTTONUP) { POINT pt = {GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam)}; ::ClientToScreen(msg.hwnd, &pt); screenPoint.x = pt.x; screenPoint.y = pt.y; dest.x = pt.x - currentDragImage.ptOffset.x; dest.y = pt.y - currentDragImage.ptOffset.y; if (msg.message == WM_MOUSEMOVE) { // Which window is my mouse over? HWND mouseWnd = WindowFromPoint(dest); IDropTarget * newTarget = NULL; if (mouseWnd != NULL && dragMap) { DragWindowMap::iterator it = dragMap->find(mouseWnd); if (it != dragMap->end()) newTarget = it->second; } if (currentTarget && currentTarget != newTarget) { currentTarget->DragLeave(); feedbackHR = dropSource->GiveFeedback(DROPEFFECT_NONE); } if (newTarget) { effect = DROPEFFECT_NONE; //is this the correct way to set effect? if (pdwEffect) effect = *pdwEffect; if (currentTarget != newTarget) { newTarget->DragEnter(dataObject, keyState, screenPoint, &effect); feedbackHR = dropSource->GiveFeedback(effect); // Find out if the target is a webview now. if (webView) webView->Release(); newTarget->QueryInterface(IID_IWebViewPrivate, (void**) &webView); } else if (currentTarget) { currentTarget->DragOver(keyState, screenPoint, &effect); feedbackHR = dropSource->GiveFeedback(effect); } } if (webView) { dragImageVisible = true; dragAreaInvalid = true; } if (feedbackHR == DRAGDROP_S_USEDEFAULTCURSORS && effect != lastEffect) { switch (effect) { case DROPEFFECT_NONE: ::SetCursor(noCursor); break; /* MS doesn't give us these cursors!!! case DROPEFFECT_COPY: break; case DROPEFFECT_MOVE: break; case DROPEFFECT_LINK: break; */ default: ::SetCursor(startCursor); break; } lastEffect = effect; } currentTarget = newTarget; } else if (msg.message == WM_LBUTTONUP) { keyState = 0; stateChanged = true; } } else if (msg.message == WM_KEYDOWN) { if (msg.wParam == VK_ESCAPE) { escapePressed = TRUE; stateChanged = true; } } else if (msg.message == WM_KEYUP) { if (msg.wParam == VK_ESCAPE) { escapePressed = FALSE; stateChanged = true; } } if (stateChanged) { result = dropSource->QueryContinueDrag(escapePressed, keyState); if (result != S_OK) { dragImageVisible = false; dragAreaInvalid = true; if (currentTarget && effect && result == DRAGDROP_S_DROP) { effect = DROPEFFECT_NONE; //FIXME: should we reset effect or not? result = currentTarget->Drop(dataObject, keyState, screenPoint, &effect); if (SUCCEEDED(result)) { result = DRAGDROP_S_DROP; if (pdwEffect) *pdwEffect = effect; } } else { result = DRAGDROP_S_CANCEL; } dragActive = false; } } PERFORMANCE_END(WTF::PerformanceTrace::InputEvent); } else { DispatchMessage(&msg); } if (dragAreaInvalid && webView && dragImageCairo) { PERFORMANCE_START(WTF::PerformanceTrace::Paint, "DragDropManager::Paint"); HDC screenDC = ::GetDC(NULL); cairo_surface_t * screenSurface = cairo_win32_surface_create(screenDC); cairo_t *crScreen = cairo_create(screenSurface); HWND wnd; webView->viewWindow((OLE_HANDLE*) &wnd); RECT dirty; if (invalidDragRect.left != -1) { dirty = invalidDragRect; } else { POINT p = {0, 0}; ::ClientToScreen(wnd, &p); ::GetClientRect(wnd, &dirty); dirty.left += p.x; dirty.top += p.y; dirty.right += p.x; dirty.bottom += p.y; } if (dragImageVisible) { POINT * prevDraw = NULL; if (lastDraw.x != -1 && (lastDraw.x != dest.x || lastDraw.y != dest.y)) prevDraw = &lastDraw; drawDragImage(crScreen, dest, prevDraw, webView, wnd, true, &dirty); lastDraw = dest; invalidDragRect.left = -1; } else { // erase the drag image wherever we last put it: drawDragImage(crScreen, lastDraw, NULL, webView, wnd, false, &dirty); } cairo_destroy(crScreen); cairo_surface_destroy(screenSurface); ::ReleaseDC(NULL, screenDC); dragAreaInvalid = false; PERFORMANCE_END(WTF::PerformanceTrace::Paint); } } if (currentTarget && result != DRAGDROP_S_DROP) { currentTarget->DragLeave(); } ::SetCursor(startCursor); if (webView) webView->Release(); if (dragImageCairo) { cairo_surface_destroy(dragImageCairo); dragImageCairo = NULL; } return result; }
void _ecore_win32_dnd_drop_source_free(void *drop_source) { if (!drop_source) return; IDropSource *object = (IDropSource *)drop_source; object->Release(); }
// @pymethod |PyIDropSource|GiveFeedback|Description of GiveFeedback. PyObject *PyIDropSource::GiveFeedback(PyObject *self, PyObject *args) { IDropSource *pIDS = GetI(self); if ( pIDS == NULL ) return NULL; // @pyparm int|dwEffect||Description for dwEffect DWORD dwEffect; if ( !PyArg_ParseTuple(args, "l:GiveFeedback", &dwEffect) ) return NULL; HRESULT hr; PY_INTERFACE_PRECALL; hr = pIDS->GiveFeedback( dwEffect ); PY_INTERFACE_POSTCALL; if ( FAILED(hr) ) return PyCom_BuildPyException(hr, pIDS, IID_IDropSource ); Py_INCREF(Py_None); return Py_None; }
// @pymethod |PyIDropSource|QueryContinueDrag|Description of QueryContinueDrag. PyObject *PyIDropSource::QueryContinueDrag(PyObject *self, PyObject *args) { IDropSource *pIDS = GetI(self); if ( pIDS == NULL ) return NULL; // @pyparm int|fEscapePressed||Description for fEscapePressed // @pyparm int|grfKeyState||Description for grfKeyState BOOL fEscapePressed; DWORD grfKeyState; if ( !PyArg_ParseTuple(args, "il:QueryContinueDrag", &fEscapePressed, &grfKeyState) ) return NULL; HRESULT hr; PY_INTERFACE_PRECALL; hr = pIDS->QueryContinueDrag( fEscapePressed, grfKeyState ); PY_INTERFACE_POSTCALL; if ( FAILED(hr) ) return PyCom_BuildPyException(hr, pIDS, IID_IDropSource ); Py_INCREF(Py_None); return Py_None; }
void Explorerplusplus::OnAddressBarBeginDrag(void) { IDragSourceHelper *pDragSourceHelper = NULL; IDropSource *pDropSource = NULL; HRESULT hr; hr = CoCreateInstance(CLSID_DragDropHelper,NULL,CLSCTX_ALL, IID_IDragSourceHelper,(LPVOID *)&pDragSourceHelper); if(SUCCEEDED(hr)) { hr = CreateDropSource(&pDropSource,DRAG_TYPE_LEFTCLICK); if(SUCCEEDED(hr)) { LPITEMIDLIST pidlDirectory = m_pActiveShellBrowser->QueryCurrentDirectoryIdl(); FORMATETC ftc[2]; STGMEDIUM stg[2]; SetFORMATETC(&ftc[0],(CLIPFORMAT)RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR), NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL); HGLOBAL hglb = GlobalAlloc(GMEM_MOVEABLE,1000); FILEGROUPDESCRIPTOR *pfgd = static_cast<FILEGROUPDESCRIPTOR *>(GlobalLock(hglb)); pfgd->cItems = 1; FILEDESCRIPTOR *pfd = (FILEDESCRIPTOR *)((LPBYTE)pfgd + sizeof(UINT)); /* File information (name, size, date created, etc). */ pfd[0].dwFlags = FD_ATTRIBUTES|FD_FILESIZE; pfd[0].dwFileAttributes = FILE_ATTRIBUTE_NORMAL; pfd[0].nFileSizeLow = 16384; pfd[0].nFileSizeHigh = 0; /* The name of the file will be the folder name, followed by .lnk. */ TCHAR szDisplayName[MAX_PATH]; GetDisplayName(pidlDirectory,szDisplayName,SHGDN_INFOLDER); StringCchCat(szDisplayName,SIZEOF_ARRAY(szDisplayName),_T(".lnk")); StringCchCopy(pfd[0].cFileName,SIZEOF_ARRAY(pfd[0].cFileName),szDisplayName); GlobalUnlock(hglb); stg[0].pUnkForRelease = 0; stg[0].hGlobal = hglb; stg[0].tymed = TYMED_HGLOBAL; /* File contents. */ SetFORMATETC(&ftc[1],(CLIPFORMAT)RegisterClipboardFormat(CFSTR_FILECONTENTS), NULL,DVASPECT_CONTENT,-1,TYMED_HGLOBAL); hglb = GlobalAlloc(GMEM_MOVEABLE,16384); IShellLink *pShellLink = NULL; IPersistStream *pPersistStream = NULL; HRESULT hr; hr = CoCreateInstance(CLSID_ShellLink,NULL,CLSCTX_INPROC_SERVER, IID_IShellLink,(LPVOID*)&pShellLink); if(SUCCEEDED(hr)) { TCHAR szPath[MAX_PATH]; GetDisplayName(pidlDirectory,szPath,SHGDN_FORPARSING); pShellLink->SetPath(szPath); hr = pShellLink->QueryInterface(IID_IPersistStream,(LPVOID*)&pPersistStream); if(SUCCEEDED(hr)) { IStream *pStream = NULL; CreateStreamOnHGlobal(hglb,FALSE,&pStream); hr = pPersistStream->Save(pStream,TRUE); } } GlobalUnlock(hglb); stg[1].pUnkForRelease = 0; stg[1].hGlobal = hglb; stg[1].tymed = TYMED_HGLOBAL; IDataObject *pDataObject = NULL; POINT pt = {0,0}; hr = CreateDataObject(ftc,stg,&pDataObject,2); pDragSourceHelper->InitializeFromWindow(m_hAddressBar,&pt,pDataObject); DWORD dwEffect; DoDragDrop(pDataObject,pDropSource,DROPEFFECT_LINK,&dwEffect); CoTaskMemFree(pidlDirectory); pDataObject->Release(); pDropSource->Release(); } pDragSourceHelper->Release(); } }
// The user started to move a link in the trace ctl int POTraceCtl::OnLinkDragBegin(const String& strUrl) { int nDragResult = dragNone; /////////////////////////////////////////////////////////// // Allocate resource for the data to share between PngOptimizer and the target application // Here it will be some bytes to store a file path HGLOBAL hgDrop = CreateDropFilesW(strUrl); ///////////////////////////////////////////////////////// FORMATETC etc; etc.cfFormat = CF_HDROP; // CLIPFORMAT etc.ptd = NULL; // DVTARGETDEVICE* etc.dwAspect = DVASPECT_CONTENT; // DWORD etc.lindex = -1; // LONG etc.tymed = TYMED_HGLOBAL; // DWORD STGMEDIUM med; med.tymed = TYMED_HGLOBAL; med.hGlobal = hgDrop; med.pUnkForRelease = NULL; IDataObject* pDataObject = new PlopDataObject; if( pDataObject ) { pDataObject->SetData(&etc, &med, TRUE); IDropSource* pDropSource = new PlopDropSource; if( pDropSource ) { // Forbid drag-and-drop on ourself ::DragAcceptFiles( ::GetParent(m_handle), FALSE); // DoDragDrop will manage the rest of the action and will return when a drag-and-drop action is done DWORD nEffect = 0; HRESULT hr = ::DoDragDrop(pDataObject, pDropSource, DROPEFFECT_MOVE | DROPEFFECT_COPY | DROPEFFECT_LINK, &nEffect); // Unless an optimization is in progress, enable again drag-and-drop on ourself if( !m_pApp->IsJobRunning() ) { ::DragAcceptFiles( ::GetParent(m_handle), TRUE); } if( hr == DRAGDROP_S_DROP ) { // Testing proved that we cannot rely on the return code given by Windows to know the exact // operation that occurred during DoDragDrop. It depends on the target application, // it depends on the Windows version and maybe the position of the stars in the sky // So we check ourselves if DoDragDrop performed a copy or a move by testing if our file is still here if( !File::Exists(strUrl) ) { // The source file does not exist anymore, then it was a move operation nDragResult = dragMove; } else { nDragResult = dragCopy; } } pDropSource->Release(); } pDataObject->Release(); } GlobalFree(hgDrop); return nDragResult; }