class TDropSource : public IDropSource
{
public :
TDropSource () : FRefCount (0) {
}
HRESULT __stdcall QueryInterface (REFIID riid, void ** ppv)
{
IUnknown * punk = NULL;
if (riid == IID_IUnknown) {
punk = static_cast (this);
} else if (riid == IID_IDropSource) {
punk = static_cast (this);
}
* ppv = punk;
if (punk) {
punk->AddRef ();
return S_OK;
} else {
return E_NOINTERFACE;
}
}
ULONG __stdcall AddRef ()
{
InterlockedIncrement (&FRefCount);
return (ULONG) FRefCount;
}
ULONG __stdcall Release ()
{
ULONG ret = (ULONG) InterlockedDecrement (&FRefCount);
if (ret == 0) {
delete this;
}
return ret;
}
/**
* 드래그 앤 드롭 처리를 계속하거나 종료를 돌려줍니다.
*/
HRESULT __stdcall QueryContinueDrag (BOOL fEsc, DWORD grfKeyState)
{
// ESC가 밀렸는지 두 버튼을 누를 경우 중지
if (fEsc ||
(MK_LBUTTON | MK_RBUTTON) == (grfKeyState & (MK_LBUTTON | MK_RBUTTON))) {
return DRAGDROP_S_CANCEL;
}
// 마우스 왼쪽 버튼을 놓으면 경우 드롭 처리에
if ((grfKeyState & (MK_LBUTTON | MK_RBUTTON)) == 0) {
return DRAGDROP_S_DROP;
}
// 그렇지는 D & D 계속
return S_OK;
}
/**
* 마우스 커서의 모양을 설정하고 사용자에게 피드백을 제공합니다.
*/
HRESULT __stdcall GiveFeedback (DWORD dwEffect)
{
// 기본 커서를 사용
return DRAGDROP_S_USEDEFAULTCURSORS;
}
private :
LONG FRefCount;
};
// ------------------------------------------------ ---------------------------
/**
* 파일 이름에서 IDataObject 인터페이스를 가져
* @ param FileName 파일 이름
* @ return 실패했을 때는 NULL
*/
IDataObject * GetFilePathDataObject (const UnicodeString &FileName)
{
// 파일 이름을 폴더를 파일 이름에 나누어 둘
UnicodeString dir = ExtractFileDir (FileName);
UnicodeString file = ExtractFileName (FileName);
// 데스크탑 IShellFolder 인터페이스를 가져
IShellFolder * desktop = NULL;
if (FAILED (SHGetDesktopFolder (&desktop))) {return NULL;}
// 대상 파일의 상위 폴더의 항목 식별자를 얻을
ITEMIDLIST* dirIDList;
DWORD eaten = 0, attributes = 0;
if (FAILED(desktop->ParseDisplayName(NULL, NULL, dir.c_str(), &eaten, &dirIDList, &attributes))) {
desktop->Release();
return NULL;
}
// 상위 폴더의 IShellFolder 인터페이스를 가져
IShellFolder* targetFolder;
if (FAILED (desktop->BindToObject (dirIDList, NULL, IID_IShellFolder,
(void **) &targetFolder))) {
desktop->Release();
return NULL;
}
// 대상 파일의 항목 식별자를 얻을
LPITEMIDLIST filePidl;
if (FAILED(targetFolder->ParseDisplayName(NULL, NULL, file.c_str(), &eaten,
&filePidl, &attributes))) {
targetFolder->Release();
desktop->Release();
return NULL;
}
// 대상 파일의 항목 식별자에서 IDataObject 인터페이스를 얻을
IDataObject* dataObject = NULL;
targetFolder->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST*)&filePidl,
IID_IDataObject, NULL, (void**)&dataObject);
targetFolder->Release();
desktop->Release();
return dataObject;
}
//////---------------------폼에서 드래그 시작시----------------------------------
void __fastcall TMainF::StartDrag(TObject *Sender, TDragObject *&DragObject)
{
Perform (WM_LBUTTONUP, 0, 0);
// OLE 드래그 앤 드롭 시작
IDataObject * dataObject = GetFilePathDataObject (L"C:\\Test.mp4"); //Drag&Drop으로 넘길 Test.mp4파일을 IDataObject화
if (dataObject == NULL) {
return;
}
DWORD dropEffect;
TDropSource* dropSource = new TDropSource ();
dropSource->AddRef();
DoDragDrop(dataObject, dropSource, DROPEFFECT_COPY, &dropEffect);
dataObject->Release();
dropSource->Release();
}
//---------------------------------------------------------------------------
현재 제 프로그램에서 드래그 앤 드롭을 하여 다른 프로그램에서 파일들을 받기를 구현하려고 합니다.
(예를 들면 제 프로그램에서 드래그 앤 드롭을 하여 윈도우 미디어 플레이어에 놓으면 PlayList에 등록이 되도록 하려고 합니다.)
해외 사이트에서 OLE Drag&Drop을 소스를 이용하여 Test 중입니다.
현재는 IDataObject를 하나만 생성해서 DoDragDrop의 첫번째 파라미터로 파일 하나만 넘길 수 뿐이 없습니다.
이걸 여러개를 넘기려면 어떻게 해야 합니까?
많은 가르침 부탁드립니다.
|