URL(File) Drag&Drop

|
2013. 09. 06 추가.
MFC에서 창 전체로 드래그하는 방법 추가 ------------------------

간단합니다.
다이얼로그 리소스 에디터에서 다이얼로그를 선택하고,
속성창에서 메세지 뷰 선택 (번개모양 옆)
거기서 WM_DROPFILES 메세지 함수를 만들면 창으로 드래그&드롭시 해당 함수가 실행됩니다.

여기에 한가지만 더 해주면 되는데, INITDIALOG 등에서 DragAcceptFiles(TRUE); 한줄만 추가해주면 끝.

HDROP 핸들로부터 파일명을 받아오는것은 QueryDragFile() 함수를 사용하면 된다.
QueryDragPoint()함수도 있는것으로 보아 원래 클릭된 좌표도 받아올 수 있는듯.

덧.
VC++ 6 IDE에서는 클래스위자드에서 해당 메세지가 보이지 않는 듯. 수동으로 해주어야 하는 작업들을 보면,

afx_msg void OnDropFiles(HDROP hDrop); //이벤트처리기 추가
ON_WM_DROPFILES() //메세지 맵 추가

그리고 OnDropFiles()를 구현해주면 된다.


OLE를 통해 사용하고자 한다면 아래 포스팅 참고.
------------




COleDropTarget을 사용해야 한다.
InitInstance()와 ExitInstance()에서
CoInitinilize(); AfxOleInit(); 와 Uninitilize(); 호출...

먼저, 드롭 이벤트시 행동을 재정의하기 위해 COleDropTarget 클래스를 상속받는 클래스를 하나 생성한다.

class CDropTarget : COleDropTarget ..............

그리고 드롭 이벤트를 받을 객체를 상속받아 MFC클래스를 생성한다.

class CDropList : CListBox ...................

객체의 create시, ole에 등록을 한다
COleDropTarget::Register(...);

COleDropTarget내의 메소드들을 재정의한다
재정의된 메소드들은 다음과 같다


DROPEFFECT CDropTarget::OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point ) {
        if (!pDataObject->IsDataAvailable(CF_TEXT))
        {
                return DROPEFFECT_NONE;
        
        }

    // if the control key is held down, return a drop effect COPY 
    if((dwKeyState&MK_CONTROL) == MK_CONTROL)
        return DROPEFFECT_COPY;
    // Otherwise return a drop effect of MOVE
    else
        return DROPEFFECT_MOVE;    

}

DROPEFFECT CDropTarget::OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point ) {
        if (!pDataObject->IsDataAvailable(CF_TEXT))
                return DROPEFFECT_NONE;

    if((dwKeyState&MK_CONTROL) == MK_CONTROL)
        return DROPEFFECT_NONE;  
    else
        return DROPEFFECT_MOVE;  // move source

}

void CDropTarget::OnDragLeave(CWnd* pWnd) {
    // Call base class implementation
    COleDropTarget::OnDragLeave(pWnd);
}
   
BOOL CDropTarget::OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point ) {
    HGLOBAL  hGlobal;
    LPCSTR   pData;                     

        if (pDataObject->IsDataAvailable(CF_TEXT))
        {                
                STGMEDIUM Stg;
                BOOL bValue = pDataObject->GetData(CF_TEXT, &Stg);                

                TCHAR *strText = (TCHAR*)GlobalLock(Stg.hGlobal);
                
                CString strUrl;
                strUrl.Format("%s",strText);

//                ((CGetList *)m_pParent)->AddUrl(strUrl);
                ((CDropList *)m_parent)->Add(strUrl);

                GlobalUnlock(Stg.hGlobal);
                GlobalFree(Stg.hGlobal);                

        }

    if((dropEffect&DROPEFFECT_MOVE) != DROPEFFECT_MOVE)
        return FALSE;

    // Get text data from COleDataObject
    hGlobal=pDataObject->GetGlobalData(CF_TEXT);

    // Get pointer to data
    pData=(LPCSTR)GlobalLock(hGlobal);    
    ASSERT(pData!=NULL); 

    // Unlock memory - Send dropped text into the "bit-bucket"
    GlobalUnlock(hGlobal);

    return TRUE;

}
CWnd *CDropTarget::SetParent(CWnd *pWndNewParent) {
        m_parent = pWndNewParent;
        return NULL;
}






-----------------------------------------
추후 추가 포스트
-------------------------------
 

예전에 포스팅 했지만 너무 무성의하게 해놓은 탓에..-_-
정리겸 재포스팅합니다...


파일 드롭은 간단히 속성을 변경하는걸로 받을수 있지만 파일 드롭을 설정 해놓아도 URL드롭은 안됩니다...

이를 사용하기 위해선 OLE를 사용해야 하는데....


먼저 InitInstance부분에서

CoInitialize(NULL);

AfxOleInit();

이 두줄을 넣어 OLE를 초기화합니다.


초기화를 했다면 그 반대도 해 주어야 겠죠...?

ExitInstance()등의 부분에

CoUninitialize();

를 호출합니다.



초기화를 하고, OLE에 등록을 해야 하는데,

먼저 COleDropTarget클래스를 상속받는 클래스를 하나 선언하여 정의합니다.


그리고 선언한 클래스를 하나 생성하여,

(저의 경우엔 class CDropTarget : public COleDropTarget 으로 했습니다.)

.Register()를 호출합니다.


인자로는 *CWnd형이 들어가는데,

창 전체로 드롭을 받으려면 현재 다이얼로그의 객체인 this만 넘겨주면 됩니다.


초기화는 되었습니다.

이제 드롭이 되었을때의 콜백함수를 정의해주면 되는데,


그 몇가지 원형은,

DROPEFFECT COleDropTarget::OnDragEnter(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point )

DROPEFFECT COleDropTarget::OnDragOver(CWnd* pWnd, COleDataObject* pDataObject, DWORD dwKeyState, CPoint point )

void COleDropTarget::OnDragLeave(CWnd* pWnd)

BOOL COleDropTarget::OnDrop(CWnd* pWnd, COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point )

입니다.


어떤 콜백인지는 함수명 보시면 알수 있고,

리턴형이 DROPEFFECT인것은, 리턴을 DROPEFFECT_MOVE를 리턴해주어야 커서 모양이 바뀝니다.


그리고,

한가지 더 말씀드리자면 상속받은 클래스 내에 윈도 핸들등의 본체 다이얼로그 접근용 멤버변수를 두어 하면 됩니다.

And