在ActiveX中实现Drag&Drop的方法 @ 4/3/2007

技术类
Q:
如何将本地文件拖放入在网页上的ActiveX中?

A:
在ATL实现的ActiveX中,继承IDropTarget接口。

在MFC实现的ActiveX中的方法,实现一个窗口CWnd子类,在ActiveX Control创建的时候创建在ActiveX界面上面。然后用这个窗口响应Drag&Drop消息。

int CTestCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct) {
    if (COleControl::OnCreate(lpCreateStruct) == -1) return -1;

    m_wndTest = new CTestWnd();
    CRect rcClient(lpCreateStruct->x, lpCreateStruct->y,
        lpCreateStruct->x + lpCreateStruct->cx,
        lpCreateStruct->y + lpCreateStruct->cy);
    if(m_wndTest->Create(rcClient, this) == -1) return -1;

    return 0;
}

其实可以在CTestCtrl中直接Regist,创建CWnd窗口的好处是可以简单的响应很多消息。

处理FileDrop的一种方法,注册响应WM_DROPFILES消息:
int CTestWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
    if (CWnd::OnCreate(lpCreateStruct) == -1) return -1;
    ModifyStyleEx(0, WS_EX_ACCEPTFILES);
    ...
}
然后在窗口中实现WM_DROPFILES消息的处理函数afx_msg void OnDropFiles(HDROP hDropInfo);处理方法参考msdn或者后面的OnDrop函数代码。

另一种方法,写一个COleDropTarget的子类。
class CTestTgt : public COleDropTarget {
// 注,此处可以写成Template,只是懒得写一个接口了。
public:
    CTestTgt():m_wndForward(NULL){};
    BOOL Register(CTestWnd *const forward){
        // 注,此处可以做一个队列,挨个通知
        if(m_wndForward != NULL) return FALSE;
        m_wndForward = forward;
        return COleDropTarget::Register(forward);
    }
    virtual DROPEFFECT OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) {
        if(m_wndForward == NULL) return DROPEFFECT_NONE;
        return m_wndForward->OnDragEnter(pDataObject);
    }
    virtual DROPEFFECT OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) {
        if(m_wndForward == NULL) return DROPEFFECT_NONE;
        return m_wndForward->OnDragOver(pDataObject);
    }
    virtual BOOL OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point) {
        if(m_wndForward == NULL) return DROPEFFECT_NONE;
        return m_wndForward->OnDrop(pDataObject);
    }
    virtual void OnDragLeave(CWnd* pWnd) {
        return m_wndForward->OnDragLeave(pDataObject);
    }
protected:
    CTestWnd* m_wndForward;
};


在CTestWnd::OnCreate方法中:
int CTestWnd::OnCreate(LPCREATESTRUCT lpCreateStruct) {
    if (CWnd::OnCreate(lpCreateStruct) == -1) return -1;
    m_drpTarget.Register(this);
        ...
}

CTestWnd实现:
DROPEFFECT CTestWnd::OnDragEnter(COleDataObject* pDataObject) {
    DROPEFFECT de = DROPEFFECT_NONE;
    m_bDragOver = TRUE;
    if(!pDataObject->IsDataAvailable(CF_HDROP) || m_bDragOver) {
        return de;
    }
/*
    if ((dwKeyState & (MK_CONTROL|MK_SHIFT) ) == (MK_CONTROL|MK_SHIFT)) {
        // Ctrl和Shift同时按下表示对象以链接方式进入
    de = DROPEFFECT_LINK;
    } else if ((dwKeyState & MK_CONTROL) == MK_CONTROL) {
        // Ctrl按下表示对象以复制方式进入
        de = DROPEFFECT_COPY;
    } else if ((dwKeyState & MK_ALT) == MK_ALT) {
        // Alt 按下表示对象以移动方式进入
        de = DROPEFFECT_MOVE;
    } else {
        //缺省为以移动方式进入
        de = DROPEFFECT_MOVE;
    }
*/
    return DROPEFFECT_COPY;
}

DROPEFFECT CTestWnd::OnDragOver(COleDataObject* pDataObject) {
    return m_bDragOver?DROPEFFECT_COPY:DROPEFFECT_NONE;
}

void CTestWnd::OnDragLeave() {
    if(m_bDragOver) m_bDragOver = FALSE;
}

BOOL CTestWnd::OnDrop(COleDataObject* pDataObject) {
    OnDragLeave();

    FORMATETC fmtetc = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    STGMEDIUM stgmed;
   
    TCHAR szFileName[_MAX_PATH + 1];
    if(!pDataObject->GetData(CF_HDROP, &stgmed, &fmtetc)) {   
        return TRUE;
    }

    HDROP hdrop = (HDROP)GlobalLock(stgmed.hGlobal);
    if(NULL == hdrop) {
        ReleaseStgMedium(&stgmed);
        return TRUE;
    }

    BOOL bAddedFiles = FALSE;
    UINT nFiles = DragQueryFile(hdrop, (UINT)-1, NULL, 0);
    for(UINT nNames = 0; nNames < nFiles; nNames++) {
        ZeroMemory(szFileName, _MAX_PATH + 1);
        DragQueryFile(hdrop, nNames, (LPTSTR)szFileName, _MAX_PATH + 1);
        MessageBox(szFileName);
    }
    GlobalUnlock(hdrop);
    ReleaseStgMedium(&stgmed);

    return TRUE;
}
发布于 4/3/2007 21:12:55 | 评论:0

看帖要回帖...

categories
archives
links
statistics
  • 网志数:1170
  • 评论数:2013