Implementation des interfaces IDropTarget, IDropSource...

Programmation d'applications complexes
Avatar de l’utilisateur
ZapMan
Messages : 460
Inscription : ven. 13/févr./2004 23:14
Localisation : France
Contact :

Implementation des interfaces IDropTarget, IDropSource...

Message par ZapMan »

Il semble que personne ne s'y était encore collé... Pour bien comprendre toute la mécanique du drag and drop avec OLE, j'ai implémenté les 3 interfaces IDropSource, IDropTarget et IDataObject.

Ca servira sans doute à bien peu de gens puisque PureBasic comporte déjà une gestion assez complete du Drag &Drop qui répond de façon simple aux besoins les plus courants. Mais si vous avez besoin d'une gestion un peu particulière de ce mécanisme (ce qui était mon cas) il vous faudra plonger les mains dans le cambouis. Ce qui suit défriche bien le terrain :

Le premier code doit être enregistré dans un fichier PB que vous nommerez "dataobject.pb"

Code : Tout sélectionner

;***************************************************************************
;
;          IMPLEMENTATION OF IDATAOBJET, IDROPSOURCE & IDROPTARGET
; 
; By Zapman
; From a Nico code (http://www.purebasic.fr/english/viewtopic.php?p=201027&sid=a993c3617a34f5a2ee4ccdaa9a3dd8c4#p201027)
; And from "Implementing IDataObject" CATCH 22 : http://www.catch22.net/tuts/dragdrop/3
;
;***************************************************************************
;
;
;***************************************************************************
;                            CUSTOM STRUCTURES
; Don't look for those structures in the Microsoft documentation, you won't
; find them. They're only to help the implementation of
; iDataObject, IdropSource and IDropTarget in PureBasic
;***************************************************************************
;

#DataMax = 100
Structure iDataObjectData
  *pIntf.IDataobject
  Refcount.l
  m_count.l ; number of STGMEDIUM and FORMATETC objects
  m_stgmed.l[#DataMax];We'll store here pointers to a tab of STGMEDIUM objects
  m_format.l[#DataMax];We'll store here pointers to a tab of FORMATETC objects
EndStructure 

Structure iDropSourceData
  *pIntf.IDropSource
  Refcount.l
  LastEffect.l
  pDataobject.l ; we'll store here a pointer to the DataObject used for this DropSource
EndStructure

Structure iDropTargetData
  *pIntf.IDropTarget
  Refcount.l
  TargetGadget.l ; We'll store here a pointer to the target Gadget
  AcceptedFormats.s ; We'll store here the list of formats accepted by our targets
  FormatMatchs.l ; On DragEnter, we'll store here 1 if the accepted formats and the DataSource formats match and 0 if not
  FormatList.s ; We'll store here a list of formats available from the dataSource (this is only for the demo)
  InfoWinHdl.l ; We'll store here a pointer to the target GadgetID wich will display infos (this is only for the demo)
EndStructure

Global NewList IDataObject.iDataObjectData()
Global NewList IDropSource.iDropSourceData()
Global NewList IDropTarget.iDropTargetData()
;

;
;***************************************************************************
;                            GENERAL FUNCTIONS
; By Zapman
;***************************************************************************
;
Procedure.s FormatMessage(lngErrorCode.l)
  ; Unknown author
  MemoryID.l = AllocateMemory (255) 
  tchar.l = FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, #Null, lngErrorCode, 0, MemoryID, 255, #Null) 
  e$ = PeekS(MemoryID) 
  FreeMemory(MemoryID) 
  If tchar > 0
      e$ = Trim(Left(e$, tchar))
  Else
      e$ = ""
  EndIf
  ProcedureReturn e$
EndProcedure
;
Procedure.s ProgNameFromCLSID(MyCLSID)
  ; By Zapman
  *Buffer = AllocateMemory(100)
  For ct = 1 To Len("CLSID\") ; Write "CLSID\" in Unicode Mode
    PokeB(*Buffer+ct*2-2,Asc(Mid("CLSID\",ct,1)))
    PokeB(*Buffer+ct*2-1,0)
  Next
  Slen = StringFromGUID2_(MyCLSID,*Buffer+Len("CLSID\")*2,100)*2 ; add the CLSID String (always coded in Unicode)
  Slen+Len("CLSID\")*2
  sk$ = ""
  For ct = 1 To SLen Step 2 ; Get the string in Unicode OR Ascii depending on our compilation mode
    sk$ + Chr(PeekC(*Buffer+ct-1))
  Next
  FreeMemory(*Buffer)
  If SLen
    Ret = RegOpenKeyEx_(#HKEY_CLASSES_ROOT,@sk$, 0, #KEY_ALL_ACCESS, @hKey)
    If (Ret =#ERROR_SUCCESS)
      ; Query value of key To get Path And close the key
      Ret = RegQueryValueEx_(hKey, #Null, #Null, #Null, #Null, @cSize)
      If (Ret = #ERROR_SUCCESS)
        *szPath = AllocateMemory(cSize)
        Ret = RegQueryValueEx_(hKey, #Null, #Null, #Null, *szPath, @cSize)
        If (Ret = #ERROR_SUCCESS)
          RegCloseKey_(hKey);
          File$ = PeekS(*szPath)
          FreeMemory(*szPath)
        EndIf
      EndIf
    EndIf
  EndIf
  If (Ret <>#ERROR_SUCCESS)
    File$ = FormatMessage(Ret)
  EndIf
  ProcedureReturn File$
EndProcedure
;
Procedure SetCharPosFromXY(GadgetID,x,y)
; By Zapman
; Set cursor/carret position in a listview or editor gadget
; x and y are absolute coordinates (from top/left corner of the screen)
  GetWindowRect_(GadgetID, rc.RECT)
  x - rc\left
  y - rc\top
  CharPos = SendMessage_(GadgetID,#EM_CHARFROMPOS,0,(x | y <<16)) 
  SendMessage_(GadgetID,#EM_SETSEL,CharPos,CharPos) 
EndProcedure

Procedure DupGlobalMem(hMem.l)
; By Zapman
  If hMem
    len    = GlobalSize_(hMem);
    If len
      source = GlobalLock_(hMem)
      If source
        dest   = GlobalAlloc_(#GMEM_FIXED, len)
        If dest
          CopyMemory(source,dest,len)
        Else
          Debug "*************** ERROR in DupGlobalMem ****************"
          Debug "dest is null"
          Debug "******************************************************"
        EndIf
      EndIf
      GlobalUnlock_(hMem)
    Else
      Debug "*************** ERROR in DupGlobalMem ****************"
      Debug "len mem is null"
      Debug "******************************************************"
    EndIf
  Else
    Debug "*************** ERROR in DupGlobalMem ****************"
    Debug "hmem is null"
    Debug "******************************************************"
  EndIf
  ProcedureReturn dest;
EndProcedure

Procedure.s GetTymedName(Tymed)
; By Zapman
; This is just for the demo. Your can delete that in your final project
  Select tymed
    Case #TYMED_GDI
      ret$ = "TYMED_GDI"
    Case #TYMED_MFPICT
      ret$ = "TYMED_MFPICT"
    Case #TYMED_ENHMF
      ret$ = "TYMED_ENHMF"
    Case #TYMED_HGLOBAL
      ret$ = "TYMED_HGLOBAL"
    Case #TYMED_FILE
      ret$ = "TTYMED_FILE"
    Case #TYMED_ISTREAM
      ret$ = "TYMED_ISTREAM"
    Case #TYMED_ISTORAGE
      ret$ = "TYMED_ISTORAGE"
  EndSelect
  ProcedureReturn ret$
EndProcedure
;
Procedure.s GetDropEffectName(dwEffect)
; By Zapman
; This is just for the demo. Your can delete that in your final project
  ret$ = ""
  If dwEffect = 0
    ret$ = "NONE"
  Else
    If dwEffect&1
      ret$ = "COPY/"
    EndIf
    If dwEffect&2
      ret$ + "MOVE/"
    EndIf
    If dwEffect&4
      ret$ + "LINK/"
    EndIf
  EndIf
  If dwEffect<0
    ret$+"SCROLL"
  EndIf
  If Right(ret$,1)="/"
    ret$=Left(ret$,Len(ret$)-1)
  EndIf
  ProcedureReturn ret$
EndProcedure
;
Procedure.s  GetClipboardFormatName(Format)
  ; By Zapman
  ret$ = ""
  Buffer$ = Space(255)
  If GetClipboardFormatName_(Format, @Buffer$, 255) > 0
    ret$ = Buffer$
  EndIf
  ProcedureReturn ret$
EndProcedure

Procedure.s GetFormatName(Format)
; By Zapman
; This is just for the demo. Your can delete that in your final project

  Select Format
    Case 1
      ret$ = "CF_TEXT"
    Case 2
      ret$ = "CF_BITMAP"
    Case 3
      ret$ = "CF_METAFILEPICT"
    Case 4
      ret$ = "CF_SYLK"
    Case 5
      ret$ = "CF_DIF"
    Case 6
      ret$ = "CF_TIFF"
    Case 7
      ret$ = "CF_OEMTEXT"
    Case 8
      ret$ = "CF_DIB "
    Case 9
      ret$ = "CF_PALETTE"
    Case 10
      ret$ = "CF_PENDATA"
    Case 11
      ret$ = "CF_RIFF"
    Case 12
      ret$ = "CF_WAVE"
    Case 13
      ret$ = "CF_UNICODETEXT"
    Case 14
      ret$ = "CF_ENHMETAFILE"
    Case 15
      ret$ = "CF_HDROP"
    Case 16
      ret$ = "CF_LOCALE "
    Case 17
      ret$ = "CF_MAX/CF_DIBV5"
    Case 18 ; (WINVER >= 0x0500)
      ret$ = "CF_MAX"
    Case $80
      ret$ = "CF_OWNERDISPLAY"
    Case $81
      ret$ = "CF_DSPTEXT"
    Case $82
      ret$ = "CF_DSPBITMAP"
    Case $83
      ret$ = "CF_DSPMETAFILEPICT"
    Case $8E
      ret$ = "CF_DSPENHMETAFILE"
    Case $0200
      ret$ = "CF_PRIVATEFIRST"
    Case $02FF
      ret$ = "CF_PRIVATELAST"
    Case $0300
      ret$ = "CF_GDIOBJFIRST"
    Case $03FF
      ret$ = "CF_GDIOBJLAST"
    Default
      ret$ = GetClipboardFormatName(Format)
    EndSelect
    If ret$ = ""
      ret$ = "Unknown ClipFormat: "+Str(Format)
    EndIf
  ProcedureReturn ret$
EndProcedure
;
Procedure LookupFormatEtc(*dataobject.iDataObjectData,*pFormatEtc.FORMATETC) ; This procedure is used by the DataObject Interface
  ;                                                                             It checks each of our formats in turn to see If one matches with *pFormatEtc
  ;
  ;                                                                             This procedure uses our particular iDataObjectData structure
  ;                                                                             and depends on the choices we made to store pointers to
  ;                                                                             our FORMATETC objects. It'll have to be adapted if you
  ;                                                                             organize your implementation in another way.
  If *dataobject And *pFormatEtc
    For i = 0 To *dataobject\m_count-1
      *DataFormatEtc.FORMATETC = *dataobject\m_format[i]
      If *DataFormatEtc\tymed & *pFormatEtc\tymed
        If *DataFormatEtc\cfFormat = *pFormatEtc\cfFormat
          If *DataFormatEtc\dwAspect = *pFormatEtc\dwAspect
            ProcedureReturn i ;index of stored format pointer
          EndIf
        EndIf
      EndIf
    Next
  EndIf
  ProcedureReturn -1;
EndProcedure
;
Procedure ComputeDropEffect_OnKey (grfKeyState,dwAllowed)
  ; By Zapman
  dwEffect = dwAllowed;
  If(grfKeyState & #MK_CONTROL)
    dwEffect = dwAllowed & #DROPEFFECT_COPY;
  ElseIf(grfKeyState & #MK_SHIFT)
    dwEffect = dwAllowed & #DROPEFFECT_MOVE;
  EndIf
  ProcedureReturn dwEffect
EndProcedure

Procedure ComputeDropEffect (grfKeyState,PtX,PtY,dwAllowed) ; This procedure is used by the DropTarget interface
  ; By Zapman
  dwEffect = 0;

   ; 1. check "pt" -> do we allow a drop at the specified coordinates?

   ;       complete the function here if needed

   ; 2. work out that the drop-effect should be based on grfKeyState
   dwEffect = ComputeDropEffect_OnKey (grfKeyState,dwAllowed)
   
   ;3    No key-modifiers were specified (Or drop effect Not allowed),
   ;    so base the effect on those allowed by the dropsource
   If((dwEffect = 0) Or (dwEffect=dwAllowed))
    If(dwAllowed & #DROPEFFECT_COPY)  : dwEffect = #DROPEFFECT_COPY : EndIf
    If(dwAllowed & #DROPEFFECT_MOVE) : dwEffect = #DROPEFFECT_MOVE : EndIf
   EndIf
   ProcedureReturn dwEffect
EndProcedure
;
Procedure SetFormatEtc(*etc.FORMATETC,cfFormat,ptd=0,dwAspect=#DVASPECT_CONTENT,lindex=-1,tymed=#TYMED_HGLOBAL)
; By Zapman
  *etc\cfFormat = cfFormat;
  *etc\ptd = ptd 
  *etc\dwAspect = dwAspect
  *etc\lindex = lindex
  *etc\tymed = tymed
EndProcedure
;
Procedure SetStgMedium (*stgmed.STGMEDIUM,hmem,tymed=#TYMED_HGLOBAL,pUnkForRelease=#Null)
; By Zapman
  *stgmed\tymed = tymed
  *stgmed\hGlobal = hmem
  *stgmed\pUnkForRelease = pUnkForRelease
EndProcedure

Procedure StringToHandle(MyString.s,AsciiUnicode)
; By Zapman
  If (AsciiUnicode = #PB_Unicode And #PB_Compiler_Unicode) Or (AsciiUnicode = #PB_Ascii And #PB_Compiler_Unicode=0)
    convert = 0
    SOC = SizeOf(Character)
  ElseIf (AsciiUnicode = #PB_Unicode And #PB_Compiler_Unicode=0) ; we need to convert the string to unicode mode
    convert = #PB_Unicode
    SOC = 2 ; Each Unicode character needs two bytes
  Else;                                                             we need to convert the string to ascii mode
    convert = #PB_Ascii
    SOC = 1
  EndIf
  StringSize = SOC * (Len(MyString)+1) ; add one to the string length to contain the zero ending the string
  hData = GlobalAlloc_(#GMEM_MOVEABLE,StringSize)
  If hData
    pData = GlobalLock_(hData)
    If pData
      If convert = 0
        PokeS(pData,MyString,Len(MyString))
      ElseIf convert = #PB_Unicode
        PokeS(pData,MyString,Len(MyString),#PB_Unicode)
      Else
        PokeS(pData,MyString,Len(MyString),#PB_Ascii)
      EndIf
    Else
      GlobalUnlock_(hData)
      GlobalFree_(hData)
      ProcedureReturn 0
    EndIf
    GlobalUnlock_(hData)
  EndIf
  ProcedureReturn hData
EndProcedure
;
Procedure.s HandleToString(hData)
  ; By Zapman
  pData = GlobalLock_(hData)
  If pData
    ProcedureReturn PeekS(pData)
  EndIf
  GlobalUnlock_(hData)
EndProcedure
;
Procedure FilesListToHandle(MyString.s)
; copy string To a Global memory block inside a DROPFILE Structure
; the original string must be a list of filenames separated by the chr(10) character
; By Zapman
  If Right(MyString,1)<>Chr(10) ; if we have no chr(10) at the end of the list, we add one
    MyString + Chr(10)
  EndIf
  ; the string included into the DROPFILES structure must be terminated by a double zero
  MyString + Chr(10)
  ; chr(10) will be replaced by zero, so we'll get a string terminated by a double zero
  StringSize = (SizeOf(Character) * Len(MyString)) ; to be compatible with Unicode compilation mode
  hData = GlobalAlloc_(#GMEM_MOVEABLE,SizeOf(DROPFILES) + StringSize)
  If hData
    *pDrop.DROPFILES = GlobalLock_(hData)
    If *pDrop
      *pDrop\pFiles = SizeOf(DROPFILES) ; size of the DROPFILES structure
      pData = *pDrop + *pDrop\pFiles ; data will be paste at the end of the DROPFILES structure
      CopyMemory(@MyString,pData, StringSize)
      For ct = pData To (pData+StringSize) Step SizeOf(Character) ; replace all chr(10) by zero
        If PeekB(ct)=10 : PokeB(ct,0) : EndIf
      Next
      If #PB_Compiler_Unicode 
        ; If we're compiling for Unicode, set the Unicode flag in the struct to
        ; indicate it contains Unicode strings.
        *pDrop\fWide =#True;
      Else
        *pDrop\fWide =#False
      EndIf
    Else
      GlobalUnlock_(hData)
      GlobalFree_(hData)
      ProcedureReturn 0
    EndIf
    GlobalUnlock_(hData)
  EndIf
  ProcedureReturn hData
EndProcedure
;
Procedure.s HandleToFilesList(handle)
  ; Extract FilesList from a DROPFILE Structure
  ; By Zapman
  *pDrop.DROPFILES = GlobalLock_(handle)
  *buffer = *pDrop + *pDrop\pFiles ; data is stored at this adress
  If *pDrop\fWide =#True ; if FilesList is stored in unicode mode, each character has 2 bytes size
    SOC = 2
  Else
    SOC = 1
  EndIf
  pos = -SOC
  nbzero = 0
  Repeat ; look for a double zero at the end of the FilesList
    pos + SOC
    If PeekB(*buffer+pos)=0
      nbzero + 1
    Else
      nbzero = 0
    EndIf
  Until nbzero = 2 Or pos>1000 ; If we don't find a double zero, we stop to explore the memory after 1000 character
  If nbzero = 2 ; OK, we now have the lenght of the FilesList
    StringSize = pos
    *buffer2 = AllocateMemory(StringSize)
    CopyMemory(*buffer,*buffer2,StringSize) ; duplicate the buffer to leave the original buffer as it is
    ct = 0
    Repeat
      If PeekB(*buffer2+ct)=0
        PokeB(*buffer2+ct,10) ; replace zero by chr(10) in all the FilesList
      EndIf
      ct + SOC
    Until ct = (StringSize-SOC)
    If *pDrop\fWide =#True
      MyString.s = PeekS(*buffer2,#PB_Any,#PB_Unicode)
    Else
      MyString.s = PeekS(*buffer2,#PB_Any,#PB_Ascii)
    EndIf
    FreeMemory(*buffer2)
  EndIf
  GlobalUnlock_(handle)
  ProcedureReturn MyString
EndProcedure
;
;***************************************************************************
;
;                      IMPLEMENTATION OF IDATAOBJET
; 
; By Zapman
; From a Nico code (http://www.purebasic.fr/english/viewtopic.php?p=201027&sid=a993c3617a34f5a2ee4ccdaa9a3dd8c4#p201027)
; And from "Implementing IDataObject" CATCH 22 : http://www.catch22.net/tuts/dragdrop/3
;
;***************************************************************************
;

Procedure dataobject_AddRef(*dataobject.iDataObjectData)
   Debug "dataobject AddRef : "+Str(*dataobject\Refcount+1) 
  *dataobject\Refcount=*dataobject\Refcount+1
   ProcedureReturn *dataobject\Refcount
EndProcedure 

Procedure dataobject_Release(*dataobject.iDataObjectData)
  Debug "dataobject Release : "+Str(*dataobject\Refcount-1)
  *dataobject\Refcount=*dataobject\Refcount-1
   If *dataobject\Refcount
     ProcedureReturn *dataobject\Refcount
   Else
     ForEach IDataObject()
       If IDataObject()=*dataobject
         For ct = 1 To *dataobject\m_count
           If *dataobject\m_stgmed[ct]
             *medium.STGMEDIUM = *dataobject\m_stgmed[ct]
             If *medium\tymed<>#TYMED_FILE ; I don't want to delete the source file if any
               ReleaseStgMedium_(*medium) ; free memory
             EndIf
           EndIf
         Next
         DeleteElement (IDataObject())
         Debug "dataobject is now deleted."
         Break
       EndIf 
     Next 
     ProcedureReturn 0
   EndIf 
EndProcedure 

Procedure dataobject_QueryInterface(*dataobject.IDataobject, iid, *ppvObject.Long)
   If CompareMemory (iid, ?IID_IUnknown, 16)=1 Or CompareMemory (iid, ?IID_IDataObject, 16)=1
     Debug "dataobject QueryInterface" 
    *ppvObject\l = *dataobject
    *dataobject\AddRef()
     ProcedureReturn #S_OK 
   Else 
    *ppvObject\l=0
     ProcedureReturn #E_NOINTERFACE 
   EndIf 
EndProcedure 
   
Procedure dataobject_GetData(*dataobject.iDataObjectData,*pformatetcIn.FORMATETC, *pmedium.STGMEDIUM)
; This implementation is not complete !
; You'll have to do some work if you want to use it with
; data which is different from hGlobal
  If *pformatetcIn = 0
    Debug "dataobject GetData : *pformatetcIn is null!!"
    ProcedureReturn #DV_E_FORMATETC
  EndIf
  If *pmedium = 0
    Debug "dataobject GetData : *pmedium is null!!"
    ProcedureReturn #STG_E_MEDIUMFULL
  EndIf
  Index = LookupFormatEtc(*dataobject,*pformatetcIn)
  If Index = -1
    Debug "dataobject GetData for : " + GetFormatName(*pformatetcIn\cfFormat)+" ---> NOT AVAILABLE"
    ProcedureReturn #DV_E_FORMATETC
  Else
    *medium.STGMEDIUM = *dataobject\m_stgmed[Index]
    If *medium\tymed = #TYMED_HGLOBAL ; need to be adapted if the data in not hGlobal !!!
      Debug "dataobject GetData for : " + GetFormatName(*pformatetcIn\cfFormat)+" ---> OK"
      
      *pmedium\tymed = *medium\tymed
      *pmedium\hGlobal = DupGlobalMem(*medium\hGlobal)
      *pmedium\pUnkForRelease = *medium\pUnkForRelease
      ProcedureReturn #S_OK
    Else
      Debug "dataobject GetData for : " + GetTymedName(*medium\tymed)+" ---> NOT IMPLEMENTED"
      ProcedureReturn #E_NOTIMPL 
    EndIf
  EndIf 
EndProcedure 

Procedure dataobject_GetDataHere(*dataobject, *pformatetc, *pmedium )
; This implementation is not done !
   Debug "dataobject GetDataHere" 
   ProcedureReturn #E_NOTIMPL 
EndProcedure 

Procedure dataobject_QueryGetData(*dataobject.iDataObjectData, *pformatetc.FORMATETC )
  If *pFormatEtc
    If LookupFormatEtc(*dataobject,*pFormatEtc) = -1
      Debug "dataobject QUERY GetData for : " + GetFormatName(*pformatetc\cfFormat)+" ---> NOT AVAILABLE"
      ProcedureReturn #DV_E_FORMATETC
    Else
      Debug "dataobject QUERY GetData for : " + GetFormatName(*pformatetc\cfFormat)+" ---> OK"
      ProcedureReturn #S_OK
    EndIf
  Else
    Debug "dataobject QUERY GetData : formatetc is null!!"
    ProcedureReturn #DV_E_FORMATETC
  EndIf
EndProcedure 

Procedure dataobject_GetCanonicalFormatEtc(*dataobject, *pformatectIn ,*pformatetcOut )
; This implementation is not done !
   Debug "dataobject GetCanonicalFormatEtc" 
   ProcedureReturn #E_NOTIMPL 
EndProcedure 

Procedure dataobject_SetData(*dataobject.iDataObjectData, *pformatetc.FORMATETC , *pmedium.STGMEDIUM, fRelease )
  ;
  Debug "dataobject SetData with: " +GetFormatName(*pformatetc\cfFormat)+" - "+GetTymedName(*pmedium\tymed)
  ;
  If *dataobject\m_count<#DataMax
    *dataobject\m_format[*dataobject\m_count] = *pformatetc
    *dataobject\m_stgmed[*dataobject\m_count] = *pmedium
    *dataobject\m_count + 1
    RetValue = #S_OK 
  Else
    Debug "dataobject SetData with: " +GetFormatName(*pformatetc\cfFormat)+" - "+GetTymedName(*pmedium\tymed)
    Debug "dataobject SetData: Out of memory -> Limit of "+Str(#DataMax)+" data reached"
    RetValue = #E_OUTOFMEMORY
  EndIf
  ;
  ; ------------------- Here is a small demo about reading data added to a HDrop DataObject by Windows Explorer
  ;
  If GetClipboardFormatName(*pformatetc\cfFormat)="TargetCLSID" And *pmedium\tymed=#TYMED_HGLOBAL
    ;
    ; We receive info from the target
      source = GlobalLock_(*pmedium\hGlobal)
      Debug "Target application is: " +ProgNameFromCLSID(source) ; Convert CLSID To String
      GlobalUnlock_(*pmedium\hglobal)
  EndIf
  ;
  ; ---------------------------------------------------------------------------------------------------------
  ;
  ProcedureReturn RetValue
EndProcedure 

Procedure dataobject_EnumFormatEtc(*dataobject.iDataObjectData, dwDirection , *ppenumFormatEtc.IEnumFORMATETC)
  If dwDirection = #DATADIR_GET
   ; Will store a tab of our formatetc objects into a *ppenumFormatEtc enumeration
   ; ATTENTION : our m_format array is an array of POINTERS to formatetc objects
   ; What we need now is an array of formatetc objects!!!!
   ; So, we'll create this array now
    Dim FormatEtcArray.FormatEtc(*dataobject\m_count-1)
    For i = 0 To *dataobject\m_count-1
      CopyMemory(*dataobject\m_format.l[i],@FormatEtcArray(i),SizeOf(FormatEtc))
    Next
    SHCreateStdEnumFmtEtc_(*dataobject\m_count,@FormatEtcArray(0),*ppenumFormatEtc)
    Debug "dataobject EnumFormatEtc" 
    ProcedureReturn #S_OK
  Else ; EnumFormatEtc for SetData is not implemented
    ProcedureReturn #E_NOTIMPL
  EndIf
EndProcedure 

Procedure dataobject_DAdvise(*dataobject,*pformatetc, advf, *pAdvSink, *pdwConnection)
; This implementation is not done !
   Debug "dataobject DAdvise" 
   ProcedureReturn #E_NOTIMPL 
EndProcedure 

Procedure dataobject_DUnadvise(*dataobject, dwConnection)
; This implementation is not done !
   Debug "dataobject DUnadvise" 
   ProcedureReturn #E_NOTIMPL 
EndProcedure 

Procedure dataobject_EnumDAdvise(*dataobject, *ppenumAdvise)
; This implementation is not done !
   Debug "dataobject EnumDAdvise" 
   ProcedureReturn #E_NOTIMPL 
EndProcedure

Procedure CreateDataObject()
  OleInitialize_(0)
  AddElement (IDataObject())
  IDataObject()\pIntf=?VTable_IDataObject_Interface
  IDataObject()\m_count = 0
  ProcedureReturn IDataObject()
EndProcedure
   
;
;
;***************************************************************************
;
;                      IMPLEMENTATION OF IDropSource
; 
; By Zapman
:
;
; The goal of my implementation is to be able to drag a virtual file to Explorer
; or to any other application able to receive a file by the drag and drop way.
; By "virtual file", I mean that the file does'nt yet exist when the user begin
; to drag its name. It will be created on the fly when the receiving application
; will ask for the data after a successfull drop.
;
; I need this when developping a FTP client: the user drag a file from the FTP
; directory to Explorer, THEN and IF the drop is successful, I download the file
; from the FTP and give Explorer the data.
;
;
;***************************************************************************
;

#DRAGDROP_S_USEDEFAULTCURSORS = $00040102
Procedure DropSource_AddRef(*dropsource.iDropSourceData)
  Debug "*DropSource AddRef : "+Str(*dropsource\Refcount+1)
  *dropsource\Refcount=*dropsource\Refcount+1
  ProcedureReturn *dropsource\Refcount
EndProcedure

Procedure DropSource_Release(*dropsource.iDropSourceData)
  Debug "*DropSource Release : "+Str(*dropsource\Refcount-1)
  *dropsource\Refcount=*dropsource\Refcount-1
  If *dropsource\Refcount > 0
    ProcedureReturn *dropsource\Refcount
  Else
    ForEach IDropSource()
      If IDropSource()=*dropsource
        Debug "IDropSource is now deleted"
        DeleteElement(IDropSource()) : Break
      EndIf
    Next
    *dropsource=0
    ProcedureReturn 0
  EndIf
EndProcedure

Procedure DropSource_QueryInterface(*dropsource.IDropSource, iid, *ppvObject.Long)
  If CompareMemory(iid, ?IID_IUnknown, 16)=1 Or CompareMemory(iid, ?IID_IDropSource, 16)=1
    Debug "*DropSource QueryInterface"
    *ppvObject\l = *dropsource
    *dropsource\AddRef()
    ProcedureReturn #S_OK
  Else
    *ppvObject\l =0
    ProcedureReturn #E_NOINTERFACE
  EndIf
EndProcedure

Procedure.l DropSource_QueryContinueDrag(*dropsource.iDropSourceData,fEscapePressed.b, grfKeyState.l)
  ;Can return S_OK, DRAGDROP_S_DROP, or DRAGDROP_S_CANCEL
  Debug "*DropSource_QueryContinueDrag : "+Str(fEscapePressed)+" - "+Str(grfKeyState)
  If(fEscapePressed = #True)

    ProcedureReturn #DRAGDROP_S_CANCEL
  ElseIf (grfKeyState & #MK_LBUTTON)=0
    ;
    ; I Choose to allow only COPY and MOVE, but you can make a different choice
    AllowedEffect = ComputeDropEffect_OnKey (grfKeyState,#DROPEFFECT_COPY|#DROPEFFECT_MOVE)
    If *dropsource\LastEffect & AllowedEffect
      ;
      Debug "*DropSource -----------------> Drop occured !!"
  
      ; -----------------------------------------------------------
      ;
      ;          Particular implementation for my project :
      :
      ; What follows will create files on fly when the user drops
      ; a filenam with success
      ;
      *Dataobject.IDataObject = *dropsource\pDataObject ; retreive the data object from its pointer
      ;                                                   we did store the pointer using "CreateDropSource" 
      SetFormatEtc(pformatetc.FORMATETC,#CF_HDROP)
      SetStgMedium (pmedium.STGMEDIUM,0)
      If *Dataobject\GetData(pformatetc,pmedium) = #S_OK ; Check if the data object contains a Files list
        If pmedium\tymed = #TYMED_HGLOBAL
          Files$ = HandleToFilesList(pmedium\hGlobal)        
          index = 1
          While StringField(Files$,index,Chr(10))
            FileName$ = StringField(Files$,index,Chr(10))
      
            Debug "---------------------------------"
            Debug "Creating "+FileName$+" on the fly"
            Debug "---------------------------------"
            If CreateFile(0,FileName$)
              WriteString(0,"Test content"+Str(index))
              CloseFile(0)
            EndIf

            index + 1
          Wend
        EndIf
      EndIf
  ; -----------------------------------------------------------
    EndIf
    
    ProcedureReturn #DRAGDROP_S_DROP
  Else
    ProcedureReturn #S_OK
  EndIf
EndProcedure

Procedure.l DropSource_GiveFeedback(*dropsource.iDropSourceData,dwEffect.l)
  ;Can return S_OK or DRAGDROP_S_USEDEFAULTCURSORS
Debug "*DropSource_GiveFeedback : "+Str(dwEffect)+" ("+GetDropEffectName(dwEffect)+")"
  *dropsource\LastEffect = dwEffect
  ProcedureReturn #DRAGDROP_S_USEDEFAULTCURSORS
EndProcedure

Procedure.l CreateDropSource(*Dataobject.IDataobjectData)
  OleInitialize_(0)
  AddElement (IDropSource())
  IDropSource()\pIntf=?VTable_IDropSource_Interface
  IDropSource()\pDataobject = *Dataobject ; store a pointer to the current data object
  ProcedureReturn IDropSource()
EndProcedure


;
;
;***************************************************************************
;
;                      IMPLEMENTATION OF IDroptarget
; 
; By Zapman
;
;***************************************************************************
;


Procedure DropTarget_AddRef(*DropTarget.iDropTargetData)
  Debug "   DropTarget AddRef : "+Str(*DropTarget\Refcount+1)
  *DropTarget\Refcount=*DropTarget\Refcount+1
  ProcedureReturn *DropTarget\Refcount
EndProcedure

Procedure DropTarget_Release(*DropTarget.iDropTargetData)
  Debug "   DropTarget Release : "+Str(*DropTarget\Refcount-1)
  *DropTarget\Refcount=*DropTarget\Refcount-1
  If *DropTarget\Refcount > 0
    ProcedureReturn *DropTarget\Refcount
  Else
    ForEach IDropTarget()
      If IDropTarget()=*DropTarget
        Debug "DropTarget is now deleted"
        DeleteElement(IDropTarget()) : Break
      EndIf
    Next
    *DropTarget=0
    ProcedureReturn 0
  EndIf
EndProcedure

Procedure DropTarget_QueryInterface(*DropTarget.IDropTarget, iid, *ppvObject.Long)
  If CompareMemory(iid, ?IID_IUnknown, 16)=1 Or CompareMemory(iid, ?IID_IDropTarget, 16)=1
    Debug "   DropTarget QueryInterface"
    *ppvObject\l = *DropTarget
    *DropTarget\AddRef()
    ProcedureReturn #S_OK
  Else
    *ppvObject\l=0
    ProcedureReturn #E_NOINTERFACE
  EndIf
EndProcedure
;
Procedure.l DropTarget_DragEnter(*DropTarget.IDropTarget,*Dataobject.IDataobject,grfKeyState.l,ptx,pty,*pdwEffect.l)
  
  info$ = "DragEnter : grfKeyState = "+Str(grfKeyState)+" - point : "+Str(ptx)+"/"+Str(pty)+" - pdwEffect = "+GetDropEffectName(PeekL(*pdwEffect))
  Debug "   DropTarget_"+info$
  
  If *pdwEffect=0
    ProcedureReturn #E_INVALIDARG
  Else
    *Target.iDropTargetData = *DropTarget
    SetFocus_(GadgetID(*Target\TargetGadget))

    *Dataobject\EnumFormatEtc(#DATADIR_GET,@ppenumFormatEtc.IEnumFORMATETC) ; enumerate all the formats contained by the data object
    *Target\FormatList = ""
    *Target\FormatMatchs = 0
    While ppenumFormatEtc\Next(1,@TempFormatEtc.FormatEtc, #Null) = #S_OK ; check if one of them match with the formats accepted by our drop target
      If FindString(*Target\AcceptedFormats,"/"+Str(TempFormatEtc\cfFormat)+"/",0)
        *Target\FormatMatchs = 1
      EndIf
      ;
      If FindString(*Target\FormatList,GetFormatName(TempFormatEtc\cfFormat),0)=0 ; For Demo only
        *Target\FormatList + GetFormatName(TempFormatEtc\cfFormat)+" - ";            For Demo only
        Debug "---------------------------------------"+GetFormatName(TempFormatEtc\cfFormat)
      EndIf;                                                                        For Demo only

      GlobalFree_(@TempFormatEtc)
    Wend
    
    ; -------------  For Demo ------------
    If Right(*Target\FormatList,3)=" - "
      *Target\FormatList = Left(*Target\FormatList,Len(*Target\FormatList)-3)
    EndIf
    
    If IsGadget(*Target\InfoWinHdl)
      If *Target\FormatList
        info$ + Chr(13) + "DragSource available formats: "+ *Target\FormatList
      EndIf
      SetGadgetText(*Target\InfoWinHdl,info$)
    EndIf
    
    ; -----------------------------------
    
    Effect = PeekL(*pdwEffect) & ComputeDropEffect (grfKeyState,PtX,PtY,#DROPEFFECT_COPY); our DropTarget implementation will only accept DROPEFFECT_COPY from the source
    If Effect = 0
      *Target\FormatMatchs = 0
    EndIf
    PokeL(*pdwEffect,Effect) ; set the return value
    
    If *Target\FormatMatchs
      If GadgetType(*Target\TargetGadget) = #PB_GadgetType_String Or GadgetType(*Target\TargetGadget) = #PB_GadgetType_Editor
        SetCharPosFromXY(GadgetID(*Target\TargetGadget),ptx,pty)
      EndIf
    EndIf
    
    ProcedureReturn #S_OK
  EndIf
EndProcedure
;
Procedure.l DropTarget_DragOver(*DropTarget.IDropTarget,grfKeyState.l,ptx,pty,*pdwEffect.l)
  *Target.iDropTargetData = *DropTarget

  ; -------------  For Demo ------------
  info$ = "DragOver  "+" - point : "+Str(ptx)+"/"+Str(pty)+" - grfKeyState = "+Str(grfKeyState)+" - DropEffect : "+GetDropEffectName(PeekL(*pdwEffect))
  Debug "   DropTarget_"+info$
  
  If *Target\FormatList ; in our implementation, the Format List has be initialized by DragEnter
    info$ + Chr(13) + "DragSource available formats: "+ *Target\FormatList
  EndIf
  If IsGadget(*Target\InfoWinHdl)
    SetGadgetText(*Target\InfoWinHdl,info$)
  EndIf
  ; -----------------------------------
  
  
  If *Target\FormatMatchs = 0 ; The formats available from the drop source and accepted by our target don't match
    PokeL(*pdwEffect,#DROPEFFECT_NONE) ; set the return value
  Else
    If GadgetType(*Target\TargetGadget) = #PB_GadgetType_String Or GadgetType(*Target\TargetGadget) = #PB_GadgetType_Editor
      SetCharPosFromXY(GadgetID(*Target\TargetGadget),ptx,pty)
    EndIf
  EndIf
  ProcedureReturn #S_OK
EndProcedure

Procedure.l DropTarget_DragLeave(*DropTargetData.iDropTargetData)
  ; -------------  For Demo ------------
  Debug "   DropTarget_DragLeave"
  SetGadgetText(*DropTargetData\InfoWinHdl,"DragLeave")
  ; -----------------------------------
  ProcedureReturn #S_OK
EndProcedure

Procedure.l DropTarget_Drop(*DropTarget.IDropTarget,*Dataobject.IDataobject,grfKeyState.l,ptx,pty,*pdwEffect.l)
  ; -------------  For Demo ------------
  info$ = "Drop : "+" - point : "+Str(ptx)+"/"+Str(pty)+" - grfKeyState = "+Str(grfKeyState)+" - DropEffect : "+GetDropEffectName(PeekL(*pdwEffect))
  Debug "   DropTarget_"+info$
  ; -----------------------------------
  
  *Target.iDropTargetData = *DropTarget
  If *Target\FormatMatchs = 0 ; The formats available from the drop source and those accepted by our target don't match
    PokeL(*pdwEffect,#DROPEFFECT_NONE) ; set the return value
    ProcedureReturn #S_OK
  EndIf
  
  
  ; -----------------------------------------------------------
  ;
  ;          Particular implementation for this project :
  ;
  ; What must be done when the drop is successfull depends on the type of target gagdet
  ; and on what your application is made for.
  ; So, you'll have to adapt the following code.
  
  If GadgetType(*Target\TargetGadget) = #PB_GadgetType_String Or GadgetType(*Target\TargetGadget) = #PB_GadgetType_Editor
    SFormat = 0
    If #PB_Compiler_Unicode
      ; we'll try to get the text in unicode mode
      ; if it does'nt work, we'll get it in ascii mode
      SetFormatEtc(pformatetc.FORMATETC,#CF_UNICODETEXT)
      If *Dataobject\QueryGetData(pformatetc) = #S_OK
        SFormat = #PB_Unicode
      EndIf
    EndIf
    If SFormat = 0
      SetFormatEtc(pformatetc.FORMATETC,#CF_TEXT)
      SFormat = #PB_Ascii
    EndIf
    
    If SFormat = #PB_Unicode Or *Dataobject\QueryGetData(pformatetc) = #S_OK
      SetStgMedium (pmedium.STGMEDIUM,0)
      If *Dataobject\GetData(pformatetc,pmedium) = #S_OK
        If pmedium\tymed = #TYMED_HGLOBAL
          MyData = GlobalLock_(pmedium\hGlobal)
          MyString.s = PeekS(MyData,#PB_Any,SFormat)
          GlobalUnlock_(pmedium\hGlobal)
          SendMessage_(GadgetID(*Target\TargetGadget), #EM_REPLACESEL, #True, @MyString)
          ;
          PokeL(*pdwEffect,#DROPEFFECT_COPY) ; set the return value
          ;
          ; -------------  For Demo ------------
          If SFormat = #PB_Ascii
            Info$ + Chr(13)+"Text has been dropped in ascii mode (CF_TEXT/TYMED_HGLOBAL)"
          Else
            Info$ + Chr(13)+"Text has been dropped in Unicode mode (CF_UNICODETEXT/TYMED_HGLOBAL)"
          EndIf
          ; -----------------------------------
        EndIf
      EndIf
    EndIf
  EndIf
  
  ; -----------------------------------------------------------
  ;
  ; -------------  For Demo ------------
  
  If IsGadget(*Target\InfoWinHdl)
    SetGadgetText(*Target\InfoWinHdl,info$)
  EndIf
  ; -----------------------------------
  

  ProcedureReturn #S_OK
EndProcedure

Procedure.l CreateDropTarget(TargetGadget,InfoGadget,AcceptedFormats$)
  OleInitialize_(0)
  AddElement (IDropTarget())
  IDropTarget()\pIntf=?VTable_IDropTarget_Interface
  IDropTarget()\TargetGadget = TargetGadget ; Register a handle to the target gadget
  IDropTarget()\InfoWinHdl = InfoGadget ; Register a handle to the info gadget
  IDropTarget()\AcceptedFormats = "/"+AcceptedFormats$+"/" ; Register the list of formats accepted by our targets

  ;                                                  Example : if our target accepts CF_TEXT (value=1) and CF_BITMAP (value=2)
  ;                                                                 The AcceptedFormats$ input parameter must be a string containing "1/2"
  ;
  If #PB_Compiler_Unicode
    If FindString(IDropTarget()\AcceptedFormats,"/1/",0) And FindString(IDropTarget()\AcceptedFormats,"/13/",0) = 0
      ;                                      if the gadget accepts CF_TEXT and the program is running in Unicode mode
      IDropTarget()\AcceptedFormats +"13/" ; we'll also accept CF_UNICODETEXT"
    EndIf
  EndIf
  RegisterDragDrop_(GadgetID(TargetGadget),IDropTarget()) ; declare our gadget as a potential drop target
  ProcedureReturn IDropTarget()
EndProcedure

;
;
;***************************************************************************
;
;                     GENERAL FUNCTIONS FOR DRAG AND DROP
; 
; By Zapman
;
;***************************************************************************
;



Procedure  OleSetClipboardWithDebug(pDataObject)
; By Zapman
  result = OleSetClipboard_(pDataObject)

  If result = #CLIPBRD_E_CANT_OPEN
    Debug "The OpenClipboard function used within OleSetClipboard failed."
  ElseIf result = #CLIPBRD_E_CANT_EMPTY
    Debug "The EmptyClipboard function used within OleSetClipboard failed."
  ElseIf result = #CLIPBRD_E_CANT_CLOSE
    Debug "The CloseClipboard function used within OleSetClipboard failed."
  ElseIf result = #CLIPBRD_E_CANT_SET
    Debug "The SetClipboardData function used within OleSetClipboard failed."
  ElseIf result = #E_NOTIMPL
    Debug "Member function contains no implementation."
  ElseIf result = -2147221008
    Debug "OleInitialize has not been called"
  ElseIf result
    Debug "Error with OleSetClipboard : "+Str(result)
    SetClipboardText("Error with OleSetClipboard : "+Str(result))
  EndIf
  ProcedureReturn result
EndProcedure
;
Procedure DoDragDropWithDebug(pDataObject, pDropSource ,DROPEFFECT,pdwEffect)
; By Zapman
  result = DoDragDrop_(pDataObject, pDropSource ,DROPEFFECT,pdwEffect)

  If result = #DRAGDROP_S_DROP
    Debug "The OLE drag-and-drop operation was successful."
  ElseIf result = #DRAGDROP_S_CANCEL
    Debug "The OLE drag-and-drop operation was canceled."
  ElseIf result = -2147221008
    Debug "OleInitialize has not been called"
  ElseIf result = #E_INVALIDARG
    Debug "Error with DoDragDrop : Invalid argument"
  ElseIf result = #DV_E_FORMATETC
    Debug "Invalid FORMATETC structure"
  ElseIf result = -1;#E_UNSPEC
    Debug "Unexpected error occurred."
  ElseIf result
    Debug "Error with DoDragDrop : "+Str(result)
  EndIf
  ProcedureReturn result
EndProcedure

;***************************************************************************
;
;                               DATA SECTION 
; 
; By Zapman
;
;***************************************************************************

DataSection 
  VTable_IDataObject_Interface:
   Data.l @dataobject_QueryInterface(), @dataobject_AddRef(), @dataobject_Release()
   Data.l @dataobject_GetData(),@dataobject_GetDataHere(),@dataobject_QueryGetData()
   Data.l @dataobject_GetCanonicalFormatEtc(),@dataobject_SetData(),@dataobject_EnumFormatEtc()
   Data.l @dataobject_DAdvise(),@dataobject_DUnadvise(),@dataobject_EnumDAdvise()
   
  VTable_IDropSource_Interface:
   Data.l @DropSource_QueryInterface(), @DropSource_AddRef(), @DropSource_Release()
   Data.l @DropSource_QueryContinueDrag(), @DropSource_GiveFeedback()
   
  VTable_IDropTarget_Interface:
   Data.l @DropTarget_QueryInterface(), @DropTarget_AddRef(), @DropTarget_Release()
   Data.l @DropTarget_DragEnter(), @DropTarget_DragOver(),@DropTarget_DragLeave(), @DropTarget_Drop()
  
  IID_IDataObject: ;{0000010e-0000-0000-C000-000000000046"} 
   Data.l $0000010E
   Data.w $0000,$0000
   Data.b $C0,$00,$00,$00,$00,$00,$00,$46
  
  IID_IDropSource:  ;{00000121-0000-0000-C000-000000000046}
   Data.l $00000121
   Data.w $0000,$0000
   Data.b $C0,$00,$00,$00,$00,$00,$00,$46
   
  IID_IDropTarget:  ;{00000122-0000-0000-C000-000000000046}
   Data.l $00000122
   Data.w $0000,$0000
   Data.b $C0,$00,$00,$00,$00,$00,$00,$46
   
  IID_IUnknown:   ;"{00000000-0000-0000-C000-000000000046}"
   Data.l $00000000
   Data.w $0000,$0000
   Data.b $C0,$00,$00,$00,$00,$00,$00,$46 
  
EndDataSection
Et voici un petit programme de démonstration qui illustre le fonctionnement de ces interfaces :

Code : Tout sélectionner

;
; Drag virtual files from List View to Explorer using OLE functions
;
; Translated for PureBasic by Zapman
;
; From "How to Implement Drag and Drop Between Your Program and Explorer" CATCH 22 : http://www.catch22.net/tuts/dragdrop/3


XIncludeFile "DataObject.pb"

appdir$=Space(255) : GetCurrentDirectory_(255,appdir$) ; get the current directory of our application


If OpenWindow(0, 0, 0, 410, 505, "Drag virtual files from List View to Explorer", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)=0:End:EndIf 
If CreateGadgetList(WindowID(0))=0:End:EndIf
GText = TextGadget(#PB_Any,10,10,390,30,"Drag those file names to the finder desktop!!")
SetGadgetColor(GText, #PB_Gadget_BackColor, RGB(240,240,155))


If LoadFont(0, "Arial", 12,#PB_Font_Bold)
  SetGadgetFont(GText, FontID(0)) 
EndIf



ELIGRef = ListIconGadget(#PB_Any, 10, 50, 390, 200, "Files", 360, #PB_ListIcon_AlwaysShowSelection|#PB_ListIcon_MultiSelect|#PB_ListIcon_FullRowSelect) 
AddGadgetItem(ELIGRef, -1, "testfile.txt")
AddGadgetItem(ELIGRef, -1, "testfile2.txt") ; Those files don't exist ! They we'll be generated on the fly by our IDataObject Interface
BCopy = ButtonGadget(#PB_Any,10,270,150,20,"Copy selection to clipboard")
OText = OptionGadget(#PB_Any,200,270,100,20,"As text")
OFilesList = OptionGadget(#PB_Any,310,270,100,20,"As files list")
SetGadgetState(OFilesList,1)
DisableGadget(BCopy,1)

Frame3DGadget(#PB_Any, 10, 310, 390, 1, "",#PB_Frame3D_Flat)

TextGadget(#PB_Any,10,330,390,20,"Drag viewer")

SDragViewer = StringGadget(#PB_Any,10,350,390,90,"Drag something here to see what it is...")

TDragInfo = TextGadget(#PB_Any,10,445,390,55,"")



*pDropTarget.IDropTarget = CreateDropTarget(SDragViewer,TDragInfo,Str(#CF_TEXT))  ; Create a IDropTarget Interface for the SDragViewer gadget
;                                                                                   Our gadget will only accept #CF_TEXT




Repeat
  EventID = WaitWindowEvent()

  If EventID=#PB_Event_Gadget
    If EventGadget()=OText Or EventGadget()=OFilesList
      If EventGadget()=OFilesList
        setgadgettext(GText,"Drag those file names to the finder desktop!!")
        DisableGadget(BCopy,1)
      Else
        setgadgettext(GText,"Drag those file names to a text application!!")
        DisableGadget(BCopy,0)
      EndIf
    EndIf
    If (EventGadget()=ELIGRef And EventType() = #PB_EventType_DragStart) Or EventGadget()=BCopy

      Files$ = ""       
      For i = 0 To CountGadgetItems(ELIGRef)-1
        If GetGadgetItemState(ELIGRef, i) & #PB_ListIcon_Selected
          Files$ + appdir$+"\"+GetGadgetItemText(ELIGRef, i,0) + Chr(10)
        EndIf
      Next i
      
      If Files$ = ""
        Files$ = "Empty selection !!!"
      EndIf
      
      *pDataObject.IDataobject = CreateDataObject()  ; Create a IDataObject Interface
      
      If GetGadgetState(OText)
        
        If #PB_Compiler_Unicode ; If we compile in Unicode Mode, we'll register two different formats in our DataObject
          ;
          SetFormatEtc(@etcU.FORMATETC,#CF_UNICODETEXT) ; register the format in a FORMATETC structure
          hDataU = StringToHandle(Files$,#PB_Unicode); Copy the text string To a Global memory block.
          SetStgMedium (@stgmedU.STGMEDIUM,hDataU) ; include the handle into a STGMEDIUM Structure
          *pDataObject\setdata(@etcU,@stgmedU, 1) ;          Set the DataObject with our data
          
        EndIf
          
        SetFormatEtc(@etc.FORMATETC,#CF_TEXT) ; register the format in a FORMATETC structure
        hData = StringToHandle(Files$,#PB_Ascii); Copy the text string To a Global memory block.
        SetStgMedium (@stgmed.STGMEDIUM,hData) ; include the handle into a STGMEDIUM Structure
        *pDataObject\setdata(@etc,@stgmed, 1) ;          Set the DataObject with our data
        
      Else
      
        hgDrop = FilesListToHandle(Files$) ; copy string To a Global memory block inside a DROPFILE Structure
        
        SetStgMedium (@stgmed.STGMEDIUM,hgDrop); include the handle into a STGMEDIUM Structure
        
        SetFormatEtc(@etc.FORMATETC,#CF_HDROP); register the format in a FORMATETC structure
        
        *pDataObject\setdata(@etc,@stgmed, 1) ;          Set the DataObject with our data
        
      EndIf
      

      
      If (EventGadget()=ELIGRef And EventType() = #PB_EventType_DragStart)
        Debug "DragStart"

        *pDropSource.IDropSource = CreateDropSource(*pDataObject) ; Create a IDropSource Interface
        
        DoDragDropWithDebug(*pDataObject, *pDropSource ,#DROPEFFECT_COPY,@pdwEffect.l)
      Else
      
        OleSetClipboardWithDebug(*pDataObject)
  
        OleFlushClipboard_();
        Debug "The clipboard is now containing : ''"+GetClipboardText()+"''" ; to see if it works
        
      EndIf
    EndIf
  EndIf

  
Until EventID=#PB_Event_CloseWindow 

End


IMPORTANT : l'implémentation de IDataObject n'est que rarement nécessaire, on peut souvent se contenter d'implémenter uniquement IDropSource ou IDropTarget (selon les besoins qu'on a). Je complèterais ce post un peu plus tard en montrant comment on peut utiliser un IDataObject généré par Windows sans avoir à le recréer de toute pièce.
Dernière modification par ZapMan le mer. 21/juil./2010 7:08, modifié 4 fois.
Tout obstacle est un point d'appui potentiel.

Bibliothèques PureBasic et autres codes à télécharger :https://www.editions-humanis.com/downlo ... ads_FR.htm
nico
Messages : 3702
Inscription : ven. 13/févr./2004 0:57

Re: Implementation des interfaces IDropTarget, IDropSource..

Message par nico »

J'ai une erreur à cette ligne:

Code : Tout sélectionner

*dataobject\m_format[*dataobject\m_count] = pformatetc
quand on essaye de faire drag/drop sur le bureau!
Avatar de l’utilisateur
ZapMan
Messages : 460
Inscription : ven. 13/févr./2004 23:14
Localisation : France
Contact :

Re: Implementation des interfaces IDropTarget, IDropSource..

Message par ZapMan »

Merci de faire le test, Nico :P

Quelle erreur obtiens-tu ?
Tout obstacle est un point d'appui potentiel.

Bibliothèques PureBasic et autres codes à télécharger :https://www.editions-humanis.com/downlo ... ads_FR.htm
El Papounet
Messages : 57
Inscription : mer. 09/juin/2010 23:47

Re: Implementation des interfaces IDropTarget, IDropSource..

Message par El Papounet »

Même erreur chez moi (Seven 32bits/PB4.50)
Structure array index out of bounds
En tout cas, merci pour les infos
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Re: Implementation des interfaces IDropTarget, IDropSource..

Message par comtois »

Salut Zapman

Je n'ai pas encore testé, mais j'avais l'intention de mettre ton code sur dvp si tu es d'accord ?
http://purebasic.developpez.com/
Je ne réponds à aucune question technique en PV, utilisez le forum, il est fait pour ça, et la réponse peut profiter à tous.
Avatar de l’utilisateur
ZapMan
Messages : 460
Inscription : ven. 13/févr./2004 23:14
Localisation : France
Contact :

Re: Implementation des interfaces IDropTarget, IDropSource..

Message par ZapMan »

El Papounet a écrit :Même erreur chez moi (Seven 32bits/PB4.50)
Structure array index out of bounds
En tout cas, merci pour les infos
Bizarre ! Moi je tourne sur XP avec PB4.5 sans problème. Si l'un de vous deux à le temps, pourriez-vous modifier la procédure SetData comme suit :

Code : Tout sélectionner

Procedure dataobject_SetData(*dataobject.iDataObjectData, pformatetc , pmedium , fRelease )
   Debug "dataobject SetData" 
   Debug *dataobject\m_count
   *dataobject\m_format[*dataobject\m_count] = pformatetc
   *dataobject\m_stgmed[*dataobject\m_count] = pmedium
   *dataobject\m_count + 1
   ProcedureReturn #S_OK 
EndProcedure 
et me dire quelle valeur le debugeur vous affiche pour m_count ?
comtois a écrit :Salut Zapman

Je n'ai pas encore testé, mais j'avais l'intention de mettre ton code sur dvp si tu es d'accord ?
Salut Comtois, je vois que les piliers de PureBasic sont toujours là! Oui, bien sûr !
Tout obstacle est un point d'appui potentiel.

Bibliothèques PureBasic et autres codes à télécharger :https://www.editions-humanis.com/downlo ... ads_FR.htm
El Papounet
Messages : 57
Inscription : mer. 09/juin/2010 23:47

Re: Implementation des interfaces IDropTarget, IDropSource..

Message par El Papounet »

Ça plante quand m_count est à 10
Avatar de l’utilisateur
ZapMan
Messages : 460
Inscription : ven. 13/févr./2004 23:14
Localisation : France
Contact :

Re: Implementation des interfaces IDropTarget, IDropSource..

Message par ZapMan »

El Papounet a écrit :Ça plante quand m_count est à 10
Merci pour ton aide. Ta réponse me surprend :

8O La seule procédure qui incrémente m_count, c'est dataobject_SetData et cette procédure n'est appelée qu'une seule fois au cours d'un drag/drop vers le bureau. m_count ne devrait donc jamais être supérieur à 1 pour cette manip.
Est-ce que le progamme principal ne bouclerait pas chez vous ?
Si tu mets un DEBUG avant

Code : Tout sélectionner

If GetGadgetState(OText)
dans le programme principal, est-ce que tu constates une boucle ?
Tout obstacle est un point d'appui potentiel.

Bibliothèques PureBasic et autres codes à télécharger :https://www.editions-humanis.com/downlo ... ads_FR.htm
El Papounet
Messages : 57
Inscription : mer. 09/juin/2010 23:47

Re: Implementation des interfaces IDropTarget, IDropSource..

Message par El Papounet »

Pas de boucle, on y passe seulement une fois lors de l'événement.

Si ça peut t'aider, voici le contenu de la fenêtre du débogueur:
DropTarget AddRef : 1
m_count: 0
DragStart
dataobject QueryInterface
dataobject AddRef : 1
dataobject AddRef : 2
dataobject Release : 1
dataobject QueryInterface
dataobject AddRef : 2
dataobject QueryInterface
dataobject AddRef : 3
dataobject EnumFormatEtc
dataobject QUERY GetData for : CF_HDROP ---> OK
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_GiveFeedback : 0 (NONE)
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_GiveFeedback : 0 (NONE)
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -16212 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15833 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15837 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15835 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15832 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16186 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15832 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16187 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16196 ---> NOT AVAILABLE
*DropSource_GiveFeedback : 1 (COPY)
dataobject GetData for : Unknown ClipFormat: -15828 ---> NOT AVAILABLE
dataobject QUERY GetData for : Unknown ClipFormat: -16212 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16212 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16212 ---> NOT AVAILABLE
dataobject GetData for : CF_HDROP ---> OK
dataobject GetData for : Unknown ClipFormat: -16202 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16212 ---> NOT AVAILABLE
dataobject GetData for : CF_HDROP ---> OK
m_count: 1
m_count: 2
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : ---> NOT IMPLEMENTED
m_count: 3
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : ---> NOT IMPLEMENTED
m_count: 4
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : ---> NOT IMPLEMENTED
m_count: 5
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : ---> NOT IMPLEMENTED
m_count: 6
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : ---> NOT IMPLEMENTED
m_count: 7
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : ---> NOT IMPLEMENTED
m_count: 8
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : ---> NOT IMPLEMENTED
m_count: 9
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
dataobject GetData for : ---> NOT IMPLEMENTED
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : ---> NOT IMPLEMENTED
m_count: 10
Avatar de l’utilisateur
ZapMan
Messages : 460
Inscription : ven. 13/févr./2004 23:14
Localisation : France
Contact :

Re: Implementation des interfaces IDropTarget, IDropSource..

Message par ZapMan »

El Papounet a écrit :Pas de boucle, on y passe seulement une fois lors de l'événement.

Si ça peut t'aider, voici le contenu de la fenêtre du débogueur:
DropTarget AddRef : 1
...
Woaw! Merci beaucoup El Papounet ! Tes infos m'ont permis de comprendre ce qui se passait : à ma grande surprise, Windows Explorer appelle la méthode SetData de mon DataObject (alors qu'en principe, il n'est là que pour lire des données, pas pour les bricoler !!!)
J'ai donc ajouté un champ dans la structure IDataObjectData qui permet de verrouiller le DataObject une fois qu'on la remplie avec nos données, afin de s'assurer que Windows Explorer ne puisse plus faire de bêtise avec. Dans mon implémentation, je verrouille ce champ lors de l'appel de CreateDropSource.

J'ai mis à jour le programme proposé ci-dessus. Si tu veux bien refaire un test en refaisant un copier collé chez toi, ça me rendrait bien service.

Merci encore une fois pour ton aide précieuse. Ce bug ne se produisait pas chez moi.
Tout obstacle est un point d'appui potentiel.

Bibliothèques PureBasic et autres codes à télécharger :https://www.editions-humanis.com/downlo ... ads_FR.htm
El Papounet
Messages : 57
Inscription : mer. 09/juin/2010 23:47

Re: Implementation des interfaces IDropTarget, IDropSource..

Message par El Papounet »

ZapMan a écrit : J'ai mis à jour le programme proposé ci-dessus. Si tu veux bien refaire un test en refaisant un copier collé chez toi, ça me rendrait bien service.

Merci encore une fois pour ton aide précieuse. Ce bug ne se produisait pas chez moi.
Alors maintenant il n'y a plus de plantage, par contre les fichiers testfile.txt ou testfile2.txt ne sont pas créés sur le bureau :(

Dans la procédure DropSource_QueryContinueDrag, quand je relache le bouton de la souris après avoir glissé le fichier sur le bureau, à la ligne If *dropsource\LastEffect = #DROPEFFECT_COPY Or *dropsource\LastEffect = #DROPEFFECT_MOVE, la variable LastEffect de la structure pointée par *dropsource est à 0xFFFFFFFF80000001

En espérant que cela puisse t'aider...
dataobject SetData with: CF_HDROP - TYMED_HGLOBAL
DragStart
dataobject QueryInterface
dataobject AddRef : 1
dataobject AddRef : 2
dataobject Release : 1
dataobject QueryInterface
dataobject AddRef : 2
dataobject QueryInterface
dataobject AddRef : 3
dataobject EnumFormatEtc
dataobject QUERY GetData for : CF_HDROP ---> OK
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_GiveFeedback : 0 (NONE)
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_GiveFeedback : 0 (NONE)
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -16215 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15727 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15726 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15725 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16075 ---> NOT AVAILABLE
*DropSource_GiveFeedback : 1 (COPY)
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject QUERY GetData for : Unknown ClipFormat: -16215 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16215 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16215 ---> NOT AVAILABLE
dataobject GetData for : CF_HDROP ---> OK
dataobject GetData for : Unknown ClipFormat: -16119 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16215 ---> NOT AVAILABLE
dataobject GetData for : CF_HDROP ---> OK
dataobject SetData with: Unknown ClipFormat: -16122 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 1
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16068 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16068 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15724 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16122 ---> NOT AVAILABLE
*DropSource_GiveFeedback : -2147483647 (COPY/SCROLL)
*DropSource_QueryContinueDrag : 0 - 0
dataobject SetData with: Unknown ClipFormat: -15722 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject SetData with: Unknown ClipFormat: -15727 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -15701 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16215 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16215 ---> NOT AVAILABLE
dataobject GetData for : CF_HDROP ---> OK
dataobject GetData for : Unknown ClipFormat: -16119 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16215 ---> NOT AVAILABLE
dataobject GetData for : CF_HDROP ---> OK
dataobject GetData for : Unknown ClipFormat: -16215 ---> NOT AVAILABLE
dataobject GetData for : CF_HDROP ---> OK
dataobject GetData for : CF_HDROP ---> OK
dataobject SetData with: Unknown ClipFormat: -16108 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject GetData for : Unknown ClipFormat: -16067 ---> NOT AVAILABLE
dataobject GetData for : CF_HDROP ---> OK
dataobject GetData for : CF_HDROP ---> OK
dataobject GetData for : Unknown ClipFormat: -16215 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16081 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -16081 ---> NOT AVAILABLE
dataobject GetData for : Unknown ClipFormat: -15697 ---> NOT AVAILABLE
dataobject SetData with: Unknown ClipFormat: -16078 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject SetData with: Unknown ClipFormat: -16109 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject SetData with: Unknown ClipFormat: -16078 - TYMED_HGLOBAL
dataobject SetData: Data won't be added because DataObject is now closed.
dataobject Release : 2
dataobject Release : 1
dataobject Release : 0
dataobject is now deleted.
The OLE drag-and-drop operation was successful.
gnozal
Messages : 832
Inscription : mar. 07/déc./2004 17:35
Localisation : France
Contact :

Re: Implementation des interfaces IDropTarget, IDropSource..

Message par gnozal »

Y a un autre bug (signalé par Fr34k) : http://www.purebasic.fr/english/viewtop ... =5&t=42926
Avatar de l’utilisateur
ZapMan
Messages : 460
Inscription : ven. 13/févr./2004 23:14
Localisation : France
Contact :

Re: Implementation des interfaces IDropTarget, IDropSource..

Message par ZapMan »

El Papounet a écrit : Alors maintenant il n'y a plus de plantage, par contre les fichiers testfile.txt ou testfile2.txt ne sont pas créés sur le bureau :(
En effet, je constate dans tes logs que ton Explorer envoie en permanence un message de Scroll (ce qui est un peu étrange) et je n'avais pas filtré ce message dans QueryContinueDrag. C'est corrigé. Merci encore pour ton aide précieuse. Tu m'a rendu un fier service. :P
gnozal a écrit :Y a un autre bug (signalé par Fr34k) : http://www.purebasic.fr/english/viewtop ... =5&t=42926
Merci à toi aussi, Gnozal. J'ai corrigé le bug de forme signalé par Freak.

La version proposée en tête de post est mise à jour.

Je me suis aussi amusé à regarder ce que c'était que ces SetData qu'Explorer tentait sur mon DataObject et j'ai trouvé la réponse ici :http://netez.com/2xExplorer/shellFAQ/adv_drag.html. Du coup, dans la nouvelle version, j'ai inclus un décodage des données "TargetCLSID".
Tout obstacle est un point d'appui potentiel.

Bibliothèques PureBasic et autres codes à télécharger :https://www.editions-humanis.com/downlo ... ads_FR.htm
pbprint
Messages : 6
Inscription : lun. 19/juil./2010 17:03

Re: Implementation des interfaces IDropTarget, IDropSource..

Message par pbprint »

@ZapMan

Bonsoir, (très intéressant comme code)

1. En règle générale, (selon ton code), la valeur du pointeur (*buffer=*X+*X/Y) doit servir d'adresse de stockage de l'information, mais, après plusieurs itérations, cette adresse se déplace d'1 octet vers la gauche, est-ce que vous pensez que ce déplacement a un rapport avec la capacité mémoire, ou un cas volontaire prévu pour les valeurs non unicodes?

2. Pourquoi le nbre d'octets est limité à 1000? Cette instruction est très claire :
[CopyMemory(*buffer,*buffer2,StringSize)], mais elle ne sera exécutée que si:
[ (nbzero = 2 Or limit>=1000 ], c'est à dire que la taille de notre DataString peut très bien être égale=1000. Je voudrais savoir pourquoi cette limite.

Merci
El Papounet
Messages : 57
Inscription : mer. 09/juin/2010 23:47

Re: Implementation des interfaces IDropTarget, IDropSource..

Message par El Papounet »

Merci Zapman, ce coup-ci ça à l'air de fonctionner.

Maintenant il va me falloir un certain temps pour essayer de comprendre. :lol:
En plus je ne me maitrise pas l'anglais et c'est malheureusement dans cette langue qu'on trouve le plus d'infos.
Répondre