2017-07-12 175 views
0

我有一個包含文件列表的ListView拖放從我的應用程序的ListView的外部應用程序(如Windows資源管理器)

hList = CreateWindowEx(0, WC_LISTVIEW, L"", WS_CHILD | WS_VISIBLE | LVS_REPORT, 0, 0, 500, 400, hWnd, (HMENU)ID_LISTVIEW, hInst, NULL); 

比方說,它包含了一排c:\temp\hello.txt

如何將此文件從我的應用程序的ListView拖放到外部應用程序(如Windows資源管理器)作爲「複製」?

enter image description here

問題的GUI部分可能通過很明顯(or not?):

case WM_NOTIFY: 
{ 
    ... 
    case LVN_BEGINDRAG: 

但這裏有個問題是關於實際發送文件到外部應用程序,如Windows資源管理器。這個怎麼做?

+1

的可能的複製[拖放支持爲Win32 GUI( https://stackoverflow.com/questions/12345435/drag-and-drop-support-for-win32-gui) – VTT

+0

沒有@VTT這是相反的(從瀏覽器到我的應用程序)!這裏我想要的是相反的:從我的應用程序到外部應用程序。 – Basj

+1

這種情況也在該線程討論。只是看第二個解釋「IDropSource」的答案,然後看第三個鏈接。 – VTT

回答

0

下面是一些代碼,實現所有需要執行這樣一個ListView文件拖動&下降。首先一些包括:

#define CINTERFACE 
#define COBJMACROS 
#include "ShObjIdl.h" 
#include "ShlObj.h" 
#include "oleidl.h" 

然後這個在WinMain函數中,初始化OLE操作。

OleInitialize(NULL); 
InitCommonControls(); 

然後,IDropSource部分:

typedef struct __DSV_TDropSource { 
    IDropSource  This; 
    IDropSourceVtbl Func; 
    ULONG   RefCnt; 
} __DSV_TDropSource; 

HRESULT WINAPI __DSV_QueryInterface(IDropSource *This, REFIID riid, void **ppvObject) 
{ 
    IUnknown *punk = NULL; 

    if (riid == IID_IUnknown) 
    { 
     punk = (IUnknown*)This; 
    } 
    else if (riid == IID_IDropSource) 
    { 
     punk = (IUnknown*)This; 
    } 

    *ppvObject = punk; 

    if (punk) 
    { 
     IUnknown_AddRef(punk); 
     return S_OK; 
    } 
    else { 
     return E_NOINTERFACE; 
    } 
} 

ULONG WINAPI __DSV_AddRef(IDropSource *This) 
{ 
    __DSV_TDropSource *pThis = (__DSV_TDropSource*)This; 
    return pThis->RefCnt++; 
} 

ULONG WINAPI __DSV_Release(IDropSource *This) 
{ 
    __DSV_TDropSource *pThis = (__DSV_TDropSource*)This; 

    LONG iRes = (LONG)pThis->RefCnt - 1; 
    if (iRes < 1) { iRes = 0; } 
    pThis->RefCnt = iRes; 

    if (iRes == 0) { free(pThis); } 
    return iRes; 
} 

HRESULT WINAPI __DSV_QueryContinueDrag(IDropSource *This, BOOL fEscapePressed, DWORD grfKeyState) 
{ 
    if (fEscapePressed) { return DRAGDROP_S_CANCEL; } 

    if (!(grfKeyState & (MK_LBUTTON | MK_RBUTTON))) { return DRAGDROP_S_DROP; } 

    return S_OK; 
} 

HRESULT WINAPI __DSV_GiveFeedback(IDropSource *This, DWORD dwEffect) 
{ 
    return DRAGDROP_S_USEDEFAULTCURSORS; 
} 

IDropSource* CreateDropSource() 
{ 
    __DSV_TDropSource *pResu = (__DSV_TDropSource*)malloc(sizeof(__DSV_TDropSource)); 
    if (!pResu) { return 0; } 

    pResu->This.lpVtbl = &(pResu->Func); 
    pResu->Func.QueryInterface = __DSV_QueryInterface; 
    pResu->Func.AddRef = __DSV_AddRef; 
    pResu->Func.Release = __DSV_Release; 
    pResu->Func.QueryContinueDrag = __DSV_QueryContinueDrag; 
    pResu->Func.GiveFeedback = __DSV_GiveFeedback; 

    pResu->RefCnt = 1; 
    return (IDropSource*)pResu; 
} 


void** GetFileUiObject(TCHAR *ptFile, REFIID riid) 
{ 

    void** pInterfaceResu = 0; 
    IShellFolder *pFolder; 
    PIDLIST_RELATIVE pFile; 
    PIDLIST_ABSOLUTE pITEMDLIST_File; 
    HRESULT iResu; 

    pITEMDLIST_File = ILCreateFromPath(ptFile); 
    if (!pITEMDLIST_File) 
     return 0; 

    iResu = SHBindToParent(pITEMDLIST_File, IID_IShellFolder, (void**)&pFolder, (PCUITEMID_CHILD*)&pFile); 
    if (iResu != S_OK) 
     return 0; 

    const ITEMIDLIST* pArray[1] = { pFile }; 
    iResu = IShellFolder_GetUIObjectOf(pFolder, NULL, 1, pArray, riid, NULL, (void**)&pInterfaceResu); 
    if (iResu != S_OK) 
     return 0; 

    IShellFolder_Release(pFolder); 

    return pInterfaceResu; 
} 

最後,這應該在消息循環中被執行:

case WM_NOTIFY: 
     pdi = (NMLVDISPINFO*) lParam; 
     nmlv = (NMLISTVIEW*) lParam; 
     switch (pdi->hdr.code) 
     { 

     case LVN_BEGINDRAG: 
      wstring fName = L"C:\\test.txt"; 
      IDataObject *pObj; 
      IDropSource *pSrc; 
      pObj = (IDataObject*)GetFileUiObject(LPWSTR(fName.c_str()), IID_IDataObject); 
      if (!pObj) 
       break; 

      pSrc = CreateDropSource(); 
      if (!pSrc) 
      { 
       IDataObject_Release(pObj); 
       break; 
      } 

      DWORD dwEffect; 
      DoDragDrop(pObj, pSrc, DROPEFFECT_COPY | DROPEFFECT_LINK, &dwEffect); 

      IDropSource_Release(pSrc); 
      IDataObject_Release(pObj); 
      break; 
1

實施IDropSourceIDropSourceNotify(可選)和IDataObject,並呼籲DoDragDrop

如果您正在開發可以作爲一個OLE拖放和拖放操作的數據源作用的應用程序,你必須調用的DoDragDrop當您檢測到用戶已啓動OLE拖放操作時。

DoDragDrop函數進入一個循環,在該循環中它調用IDropSource和IDropTarget接口中的各種方法。 (對於一個成功的拖和拖放操作,作爲數據源的應用程序還必須實現IDropSource,而目標應用程序必須實現下降目標。)

SHCreateDataObject可以爲你提供一個IDataObject實例,但你經常結束由於shell提供的實現是not perfect,因此不得不。

IDragSourceHelper可以幫助您獲得一個奇特的拖動圖像。

參見:

+0

謝謝安德斯。 「不完美」的鏈接不起作用,你還有嗎?另外爲什麼IDropSourceNotify是可選的?如果我不使用它會發生什麼? – Basj

+0

鏈接工作正常,基本上你不能使用CFSTR_FILECONTENTS,因爲數據對象只支持索引-1。也許https://archive.is/xVH4X對你更好。通知是可選的,因爲您可能不關心用戶正在放入的窗口類型。 – Anders

相關問題