Example #1
0
        ///<Summary>This constructor takes a pointer to an IDataObject obtained from a
        /// IDropTarget Interface's DragEnter method.
        /// If the pointer points to a .Net DataObject (which only happens within the same app),
        /// convert it and call ProcessNetDataObject
        /// Otherwise, it from another app, possibly Win Explorer, so
        /// check it for the required formats and build m_DragList.
        /// Any error just quits, leaving m_IsValid as False ... Caller must check
        ///</Summary>
        public CProcDataObject(IntPtr pDataObj)         //Assumed to be a pointer to an IDataObject
        {
            //save it off -- DragWrapper class won't use it
            //              CDragWrapper class may, but should, in this version, use the original
            m_DataObject = pDataObj;
            bool HadError = false;             //used for various error conditions

            try
            {
                IDO = Marshal.GetTypedObjectForIUnknown(pDataObj, typeof(ShellDll.IDataObject)) as ShellDll.IDataObject;
            }
            catch (Exception)
            {
                // Debug.WriteLine("Exception Thrown in CMyDataObject -Getting COM interface: " & vbCrLf & ex.ToString)
                HadError = true;
            }
            //If it is really a .Net IDataObject, then treat it as such
            if (HadError)
            {
                try
                {
                    NetIDO = Marshal.GetTypedObjectForIUnknown(pDataObj, typeof(System.Windows.Forms.IDataObject)) as System.Windows.Forms.IDataObject;
                    IsNet  = true;
                }
                catch
                {
                    IsNet = false;
                }
            }
            if (IsNet)
            {
                //Any error in ProcessNetDataObject will leave m_IsValid as False -- our only Error Indicator
                ProcessNetDataObject(NetIDO);
            }
            else             //IDataObject not from Net, Do it the hard way
            {
                if (HadError)
                {
                    return;                     //can do no more
                }
                ProcessCOMIDataObject(IDO);
                //It either worked or not.  m_IsValid is set accordingly, so we are done
            }
        }
Example #2
0
        ///<Summary>Given an IDataObject from some non-net source, Build the
        /// m_DragList ArrayList.
        /// Also ensure that the IDataObject has "Shell IDList Array" formatted data
        /// If not, build it in m_StreamCIDA, if so, copy to m_StreamCIDA
        ///If dealing with all FileSystem Items,
        /// </Summary>
        private void ProcessCOMIDataObject(ShellDll.IDataObject IDO)
        {
            //Don't even look for an ArrayList. If there, we don't know how to access
            //Therefore, we need either a "FileDrop" or a "Shell IDList Array" to
            //extract the info for m_DragList and to ensure that the IDataObject
            //actually has a "Shell IDList Array"

            int HR;             //general use response variable

            ShellDll.FORMATETC fmtEtc;
            ShellDll.STGMEDIUM stg;
            //ensure m_StreamCIDA is nothing  - will test for this later
            m_StreamCIDA = null;
            //First check for "Shell IDList Array" -- preferred in this case (and most others)
            int cf = ShellDll.RegisterClipboardFormat("Shell IDList Array");

            if (cf != 0)
            {
                fmtEtc.cfFormat    = (ShellDll.CF)cf;
                fmtEtc.lindex      = -1;
                fmtEtc.dwAspect    = ShellDll.DVASPECT.CONTENT;
                fmtEtc.ptd         = IntPtr.Zero;
                fmtEtc.Tymd        = ShellDll.TYMED.HGLOBAL;
                stg.hGlobal        = IntPtr.Zero;
                stg.pUnkForRelease = IntPtr.Zero;
                stg.tymed          = (int)ShellDll.TYMED.HGLOBAL;
                HR = IDO.GetData(ref fmtEtc, ref stg);
                if (HR == 0)
                {
                    IntPtr cidaptr = Marshal.ReadIntPtr(stg.hGlobal);
                    m_StreamCIDA = MakeStreamFromCIDA(cidaptr);
                    MakeDragListFromCIDA();
                    ShellDll.ReleaseStgMedium(ref stg); //done with this
                }
                else
                {
                    try
                    {
                        Marshal.ThrowExceptionForHR(HR);
                    }
                    catch (Exception)
                    {
                    }
                }
            }

            //Check for "FileDrop" (CF.HDROP) if we have to
            if (m_Draglist.Count < 1)             //skip this if already have list
            {
                fmtEtc.cfFormat    = ShellDll.CF.HDROP;
                fmtEtc.lindex      = -1;
                fmtEtc.dwAspect    = ShellDll.DVASPECT.CONTENT;
                fmtEtc.ptd         = IntPtr.Zero;
                fmtEtc.Tymd        = ShellDll.TYMED.HGLOBAL;
                stg.hGlobal        = IntPtr.Zero;
                stg.pUnkForRelease = IntPtr.Zero;
                stg.tymed          = 0;
                HR = IDO.GetData(ref fmtEtc, ref stg);
                if (HR == 0)                 //we have an HDROP and stg.hGlobal points to the info
                {
                    IntPtr pHdrop  = Marshal.ReadIntPtr(stg.hGlobal);
                    int    nrItems = ShellDll.DragQueryFile(pHdrop, -1, null, 0);
                    int    i;
                    for (i = 0; i <= nrItems - 1; i++)
                    {
                        int           plen = ShellDll.DragQueryFile(pHdrop, i, null, 0);
                        StringBuilder SB   = new StringBuilder(plen + 1);
                        int           flen = ShellDll.DragQueryFile(pHdrop, i, SB, plen + 1);
                        Debug.WriteLine("Fetched from HDROP: " + SB.ToString());
                        try                         //if GetCShitem returns Nothing(it's failure marker) then catch it
                        {
                            m_Draglist.Add(ExpTreeLib.CShItem.GetCShItem(SB.ToString()));
                        }
                        catch (Exception ex)                         // in this case, just skip it
                        {
                            Debug.WriteLine("Error: CMyDataObject.ProcessComIDataObject - Adding via HDROP" + "\r\n" + "\t" + ex.Message);
                        }
                    }
                    ShellDll.ReleaseStgMedium(ref stg);                     //done with this stg
                    //Else
                    //    Marshal.ThrowExceptionForHR(HR)
                }
            }
            //Have done what we can to get m_DragList -- exit on failure
            if (m_Draglist.Count < 1)   //Can't do any more -- Quit
            {
                return;                 //leaving m_IsValid as False
            }

            //May not have Shell IDList Array in IDataObject.  If not, give it one
            if (m_StreamCIDA == null)             //IDO does not yet have "Shell IDList Array" Data
            {
                m_StreamCIDA = MakeShellIDArray(m_Draglist);
                if (m_StreamCIDA == null)
                {
                    return;                     //failed to make it
                }
                //Now put the CIDA into the original IDataObject
                fmtEtc.cfFormat = (ShellDll.CF)cf;                 //registered at routine entry
                fmtEtc.lindex   = -1;
                fmtEtc.dwAspect = ShellDll.DVASPECT.CONTENT;
                fmtEtc.ptd      = IntPtr.Zero;
                fmtEtc.Tymd     = ShellDll.TYMED.HGLOBAL;
                //note the hGlobal item in stg is a pointer to a pointer->Data
                IntPtr m_hg = Marshal.AllocHGlobal(Convert.ToInt32(m_StreamCIDA.Length));
                Marshal.Copy(m_StreamCIDA.ToArray(), 0, m_hg, (int)m_StreamCIDA.Length);
                IntPtr hg = Marshal.AllocHGlobal(IntPtr.Size);
                Marshal.WriteIntPtr(hg, 0, m_hg);
                stg.tymed          = (int)ShellDll.TYMED.HGLOBAL;
                stg.hGlobal        = hg;
                stg.pUnkForRelease = IntPtr.Zero;

                HR = IDO.SetData(ref fmtEtc, ref stg, true);                 //callee responsible for releasing stg
                if (HR == 0)
                {
                    m_IsValid = true;
                }
                else                 //failed -- we have to release stg  -- and leave m_IsValid as False
                {
                    ShellDll.ReleaseStgMedium(ref stg);
                    return;                     //m_isvalid stays False
                }
            }
            m_IsValid = true;             //already had a Shell IDList Array, so all is OK
        }
Example #3
0
 //Assumed to be a pointer to an IDataObject
 ///<Summary>This constructor takes a pointer to an IDataObject obtained from a
 /// IDropTarget Interface's DragEnter method.
 /// If the pointer points to a .Net DataObject (which only happens within the same app),
 /// convert it and call ProcessNetDataObject
 /// Otherwise, it from another app, possibly Win Explorer, so
 /// check it for the required formats and build m_DragList.
 /// Any error just quits, leaving m_IsValid as False ... Caller must check
 ///</Summary>
 public CProcDataObject(IntPtr pDataObj)
 {
     //save it off -- DragWrapper class won't use it
     //              CDragWrapper class may, but should, in this version, use the original
     m_DataObject = pDataObj;
     bool HadError = false; //used for various error conditions
     try
     {
         IDO = Marshal.GetTypedObjectForIUnknown(pDataObj, typeof(ShellDll.IDataObject)) as ShellDll.IDataObject;
     }
     catch (Exception)
     {
         // Debug.WriteLine("Exception Thrown in CMyDataObject -Getting COM interface: " & vbCrLf & ex.ToString)
         HadError = true;
     }
     //If it is really a .Net IDataObject, then treat it as such
     if (HadError)
     {
         try
         {
             NetIDO = Marshal.GetTypedObjectForIUnknown(pDataObj, typeof(System.Windows.Forms.IDataObject)) as System.Windows.Forms.IDataObject;
             IsNet = true;
         }
         catch
         {
             IsNet = false;
         }
     }
     if (IsNet)
     {
         //Any error in ProcessNetDataObject will leave m_IsValid as False -- our only Error Indicator
         ProcessNetDataObject(NetIDO);
     }
     else //IDataObject not from Net, Do it the hard way
     {
         if (HadError)
         {
             return; //can do no more
         }
         ProcessCOMIDataObject(IDO);
         //It either worked or not.  m_IsValid is set accordingly, so we are done
     }
 }