Example #1
1
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 CDropHandler::HandleRightClickDrop(void)
{
	IShellFolder *pDesktop = NULL;
	IShellFolder *pShellFolder = NULL;
	IDropTarget *pDrop = NULL;
	LPITEMIDLIST pidlDirectory = NULL;
	DWORD dwe;
	HRESULT hr;

	hr = GetIdlFromParsingName(m_szDestDirectory,&pidlDirectory);

	if(SUCCEEDED(hr))
	{
		hr = SHGetDesktopFolder(&pDesktop);

		if(SUCCEEDED(hr))
		{
			hr = pDesktop->BindToObject(pidlDirectory,0,IID_IShellFolder,(void **)&pShellFolder);

			if(SUCCEEDED(hr))
			{
				dwe = *m_pdwEffect;

				hr = pShellFolder->CreateViewObject(m_hwndDrop,IID_IDropTarget,(void **)&pDrop);

				if(SUCCEEDED(hr))
				{
					pDrop->DragEnter(m_pDataObject,MK_RBUTTON,m_ptl,&dwe);

					dwe = *m_pdwEffect;
					pDrop->Drop(m_pDataObject,m_grfKeyState,m_ptl,&dwe);

					pDrop->DragLeave();

					pDrop->Release();
				}

				pShellFolder->Release();
			}

			pDesktop->Release();
		}

		CoTaskMemFree(pidlDirectory);
	}
}
// @pymethod |PyIDropTarget|DragLeave|Called as the object is dragged back out of the window
PyObject *PyIDropTarget::DragLeave(PyObject *self, PyObject *args)
{
	IDropTarget *pIDT = GetI(self);
	if ( pIDT == NULL )
		return NULL;
	if ( !PyArg_ParseTuple(args, ":DragLeave") )
		return NULL;
	HRESULT hr;
	PY_INTERFACE_PRECALL;
	hr = pIDT->DragLeave( );

	PY_INTERFACE_POSTCALL;

	if ( FAILED(hr) )
		return PyCom_BuildPyException(hr, pIDT, IID_IDropTarget );
	Py_INCREF(Py_None);
	return Py_None;

}