1 //*******************************************************************************
4 // You may use this source code, compile or redistribute it as part of your application
5 // for free. You cannot redistribute it as a part of a software development
6 // library without the agreement of the author. If the sources are
7 // distributed along with the application, you should leave the original
8 // copyright notes in the source code without any changes.
9 // This code can be used WITHOUT ANY WARRANTIES at your own risk.
11 // For the latest updates to this code, check this site:
12 // http://www.masmex.com
15 // Copyright(C) 2000 Philip Oldaker <email: philip@masmex.com>
16 //*******************************************************************************
19 #include "cbformats.h"
21 #include "ShellPidl.h"
27 static char THIS_FILE[] = __FILE__;
31 CWDClipboardData *CWDClipboardData::Instance()
33 static CWDClipboardData data;
37 CWDClipboardData::CWDClipboardData()
39 m_aFormatIDs[e_cfString] = CF_TEXT;
40 m_aFormatIDs[e_cfHDROP] = CF_HDROP;
41 m_aFormatIDs[e_cfWebSiteURL] = ::RegisterClipboardFormat(CFSTR_SHELLURL);
43 m_aFormatIDs[e_cfFileGroupDesc] = ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORW);
45 m_aFormatIDs[e_cfFileGroupDesc] = ::RegisterClipboardFormat(CFSTR_FILEDESCRIPTORA);
47 m_aFormatIDs[e_cfHTMLFormat] = ::RegisterClipboardFormat(_T("HTML Format"));
48 m_aFormatIDs[e_cfWebSite] = ::RegisterClipboardFormat(_T("CF_WD_WEBSITE"));
49 m_aFormatIDs[e_cfRightMenu] = ::RegisterClipboardFormat(_T("CF_WD_RIGHTMENU"));
50 m_aFormatIDs[e_cfFolder] = ::RegisterClipboardFormat(_T("CF_WD_WEBSITE_CATEGORY"));
51 m_aFormatIDs[e_cfShellIDList] = ::RegisterClipboardFormat(CFSTR_SHELLIDLIST);
54 CWDClipboardData::~CWDClipboardData()
58 bool CWDClipboardData::IsValidFormat(CLIPFORMAT cfFormat)
60 for(int i=0;i < e_cfMax;i++)
62 if (m_aFormatIDs[i] == cfFormat)
68 bool CWDClipboardData::IsDataAvailable(COleDataObject *pDataObject)
70 // Iterate through the clipboard formats
71 pDataObject->BeginEnumFormats();
77 while (pDataObject->GetNextFormat(&FormatEtc))
81 if (FormatEtc.cfFormat > CF_MAX)
83 ::GetClipboardFormatName(FormatEtc.cfFormat,szBuf,sizeof(szBuf)-1);
87 lstrcpy(szBuf,_T("Predefined Format"));
89 TRACE(_T("Enum formats returned %u(%s) %d\n"),FormatEtc.cfFormat,szBuf,FormatEtc.tymed);
91 if (IsValidFormat(FormatEtc.cfFormat))
94 TRACE(_T("Clipboard format found %u(%s) tymed(%d), Aspect(%d)\n"),FormatEtc.cfFormat,szBuf,FormatEtc.tymed,FormatEtc.dwAspect);
102 CLIPFORMAT CWDClipboardData::GetClipboardFormat(eCBFormats format)
104 return m_aFormatIDs[format];
107 void CWDClipboardData::SetData(COleDataSource *pOleDataSource,CObject *pObj,eCBFormats format,LPFORMATETC lpFormatEtc)
109 ASSERT(pOleDataSource);
114 CArchive ar(&file,CArchive::store);
118 // cache into drag drop source
119 pOleDataSource->CacheGlobalData(CWDClipboardData::Instance()->GetClipboardFormat(format),file.Detach(),lpFormatEtc);
122 bool CWDClipboardData::GetData(COleDataObject *pDataObject,CObject *pObj,eCBFormats format)
126 if (pDataObject == NULL || pObj == NULL)
129 if (m_aFormatIDs[format] == CF_HDROP)
131 FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
133 if (pDataObject->GetData(CF_HDROP, &medium, &fmte))
135 HDROP hDropInfo = (HDROP)medium.hGlobal;
136 UINT wNumFilesDropped = DragQueryFile(hDropInfo, 0XFFFFFFFF, NULL, 0);
137 TCHAR szFile[MAX_PATH];
138 ASSERT_KINDOF(CCF_HDROP,pObj);
139 CCF_HDROP *pHDROP = (CCF_HDROP*)pObj;
141 for(UINT i=0; i < wNumFilesDropped;i++)
143 nLen = DragQueryFile(hDropInfo,i,szFile,sizeof(szFile)/sizeof(TCHAR));
146 pHDROP->AddFileName(szFile);
149 if (medium.pUnkForRelease)
150 medium.pUnkForRelease->Release();
152 GlobalFree(medium.hGlobal);
157 CFile *pFile = pDataObject->GetFileData(CWDClipboardData::Instance()->GetClipboardFormat(format));
160 CArchive ar(pFile,CArchive::load);
169 ///////////////////////////////////////////
173 ///////////////////////////////////////////
174 IMPLEMENT_SERIAL(CCF_App, CObject, 0 );
175 IMPLEMENT_SERIAL(CCF_WebSites,CObject,0);
176 IMPLEMENT_SERIAL(CCF_String, CObject, 0 );
177 IMPLEMENT_SERIAL(CCF_WebSite, CObject, 0 );
178 IMPLEMENT_SERIAL(CCF_FolderType, CObject, 0 );
179 IMPLEMENT_SERIAL(CCF_DBFolderList,CObject,0);
180 IMPLEMENT_SERIAL(CCF_RightMenu, CObject, 0 );
181 IMPLEMENT_SERIAL(CCF_FileGroupDescriptor,CObject,0);
182 IMPLEMENT_SERIAL(CCF_ShellIDList,CObject,0);
183 IMPLEMENT_SERIAL(CCF_HDROP,CObject,0);
184 ///////////////////////////////////////////
185 bool CCF_RightMenu::IsRightDrag()
190 void CCF_RightMenu::SetRightDrag(bool bRightDrag)
192 m_bRightDrag = bRightDrag;
195 void CCF_RightMenu::Serialize(CArchive &ar)
201 m_bRightDrag = nRightDrag == 1;
209 CCF_FileGroupDescriptor::CCF_FileGroupDescriptor()
211 m_pFileDescrs = NULL;
215 CCF_FileGroupDescriptor::~CCF_FileGroupDescriptor()
217 delete []m_pFileDescrs;
220 LPFILEDESCRIPTOR CCF_FileGroupDescriptor::GetFileDescriptor(UINT nItem)
222 if (m_pFileDescrs == NULL)
224 if (nItem >= m_nItems)
229 return &m_pFileDescrs[nItem];
232 void CCF_FileGroupDescriptor::SetTitle(const CString &sTitle)
237 CString CCF_FileGroupDescriptor::GetFileName(UINT nItem)
239 if (nItem >= m_nItems || m_pFileDescrs == NULL)
244 return m_pFileDescrs[nItem].cFileName;
247 CString CCF_FileGroupDescriptor::GetTitle(UINT nItem)
249 if (nItem >= m_nItems || m_pFileDescrs == NULL)
254 CString strLink(m_pFileDescrs[nItem].cFileName);
255 int nPos = strLink.Find(_T(".URL"));
257 nPos = strLink.Find(_T(".url"));
260 return strLink.Left(nPos);
265 void CCF_FileGroupDescriptor::Serialize(CArchive &ar)
269 ar.Read(&m_nItems,sizeof(UINT));
272 m_pFileDescrs = new FILEDESCRIPTOR[m_nItems];
273 ar.Read(m_pFileDescrs,sizeof(FILEDESCRIPTOR)*m_nItems);
274 for(UINT i=0;i < m_nItems;i++)
275 TRACE3("(%u) - cFileName %s, Size=%u\n",i,m_pFileDescrs[i].cFileName,m_pFileDescrs[i].nFileSizeLow);
281 ar.Write(&cItems,sizeof(UINT));
282 FILEDESCRIPTOR FileDesc;
283 ZeroMemory(&FileDesc,sizeof(FILEDESCRIPTOR));
284 FileDesc.dwFlags = (FD_LINKUI | FD_FILESIZE);
285 if (!m_sTitle.IsEmpty())
287 lstrcpy(FileDesc.cFileName,m_sTitle);
288 lstrcat(FileDesc.cFileName,_T(".url"));
289 FileDesc.nFileSizeLow = lstrlen(FileDesc.cFileName)+24;
290 ar.Write(&FileDesc,sizeof(FILEDESCRIPTOR));
295 ////////////////////////////////////////////////
297 ////////////////////////////////////////////////
298 CCF_HDROP::CCF_HDROP()
304 CCF_HDROP::~CCF_HDROP()
308 CString CCF_HDROP::GetFileName(UINT nItem)
310 if (m_sFileNames.GetSize() > 0)
311 return m_sFileNames[nItem];
315 void CCF_HDROP::AddDropPoint(CPoint &pt,BOOL fNC)
321 void CCF_HDROP::AddFileName(LPCTSTR pszFileName)
323 m_sFileNames.SetAtGrow(m_nFiles++,pszFileName);
326 void CCF_HDROP::Serialize(CArchive &ar)
330 // handled in GetData
335 dropfiles.pFiles = sizeof(dropfiles);
336 dropfiles.fNC = m_fNC;
339 dropfiles.fWide = TRUE;
341 dropfiles.fWide = FALSE;
343 ar.Write(&dropfiles,sizeof(DROPFILES));
344 LPCTSTR pszFileName=NULL;
345 for(int i=0; i < m_nFiles;i++)
347 pszFileName=m_sFileNames[i];
348 ar.Write(pszFileName,lstrlen(pszFileName)+sizeof(TCHAR));
351 ar.Write(&rchar,sizeof(TCHAR));
355 ////////////////////////////////////////////////
357 ////////////////////////////////////////////////
358 CCF_ShellIDList::CCF_ShellIDList()
362 CCF_ShellIDList::~CCF_ShellIDList()
366 LPCITEMIDLIST CCF_ShellIDList::operator[](UINT nIndex) const
368 return GetPidl(nIndex);
371 LPCITEMIDLIST CCF_ShellIDList::GetPidl(UINT nIndex) const
373 if (nIndex > (UINT)m_pidls.GetSize())
377 return(m_pidls[nIndex]);
380 UINT CCF_ShellIDList::GetCount() const
382 return m_pidls.GetSize();
385 void CCF_ShellIDList::AddPidl(LPCITEMIDLIST pidl)
390 void CCF_ShellIDList::Serialize(CArchive &ar)
396 ar.Read(&cida,sizeof(CIDA));
397 LPCITEMIDLIST pidl=NULL;
399 // read the ITEMIDLIST structures
400 for(UINT i=0;i < cida.cidl+1;i++)
402 nOffset = cida.aoffset[i];
403 ar.GetFile()->Seek(CFile::begin,nOffset*sizeof(UINT));
404 ar.Read((void*)pidl,sizeof(ITEMIDLIST));
410 CShellPidl ShellPidl;
412 cida.cidl = m_pidls.GetSize();
413 ASSERT(cida.cidl > 1);
416 UINT pidls=cida.cidl-1;
417 ar.Write(&pidls,sizeof(pidls));
418 const UINT nOffset=sizeof(UINT);
421 for(UINT i1=0;i1 < cida.cidl;i1++)
423 nElemOffset = sizeof(cida.cidl)+(cida.cidl*sizeof(nElemOffset))+nOffset+nPidlSize;
424 ar.Write(&nElemOffset,sizeof(nElemOffset));
425 nPidlSize += ShellPidl.GetSize(m_pidls[i1]);
428 for(int i=0;i < nOffset;i++)
429 ar.Write(&nZero,sizeof(nZero));
430 TRACE1("Writing %u pidls\n",cida.cidl);
431 LPSHELLFOLDER pFolder=ShellPidl.GetFolder((LPITEMIDLIST)m_pidls[0]);
432 for(UINT i2=0;i2 < cida.cidl;i2++)
436 ShellPidl.SHPidlToPathEx((LPITEMIDLIST)m_pidls[i2],sPath,pFolder);
437 TRACE3("Writing pidl %s (%u) size(%u)\n",sPath,i2,ShellPidl.GetSize(m_pidls[i2]));
439 ar.Write(m_pidls[i2],ShellPidl.GetSize(m_pidls[i2]));
446 ///////////////////////////////////////////////////////////////////
447 // Private clipboard formats for drag and drop
448 ///////////////////////////////////////////////////////////////////
449 const CCF_WebSite &CCF_WebSite::operator=(const CCF_WebSite &rThat)
453 m_strURL = rThat.m_strURL;
454 m_strTitle = rThat.m_strTitle;
459 CCF_WebSite::CCF_WebSite(const CCF_WebSite &WebSite)
464 ////////////////////////////////////////////
466 void CCF_App::Serialize(CArchive &ar)
479 /////////////////////////////////////////
481 void CCF_WebSites::Serialize(CArchive &ar)
484 m_listWebSites.Serialize(ar);
487 /////////////////////////////////////////
489 CCF_String::CCF_String(LPCTSTR pszText) : m_sText(pszText)
493 CCF_String::~CCF_String()
497 LPCTSTR CCF_String::GetString()
502 void CCF_String::SetString(LPCTSTR pszText)
507 void CCF_String::Serialize(CArchive &ar)
511 TCHAR szText[MAX_PATH+1];
515 ZeroMemory(szText,sizeof(szText));
516 ar.Read(szText,MAX_PATH);
518 if (lstrlen(szText) < MAX_PATH)
524 ar.Write((LPCTSTR)m_sText, m_sText.GetLength()*sizeof(TCHAR));
526 ar.Write(&null,sizeof(null));
531 // Private clipboard formats for drag and drop
533 CCF_WebSite::CCF_WebSite(LPCTSTR pszURL,LPCTSTR pszTitle) :
539 CCF_WebSite::~CCF_WebSite()
543 void CCF_WebSite::Serialize(CArchive &ar)
558 //////////////////////////////////////////////////////
560 CCF_FolderType::CCF_FolderType(LPCTSTR pszParentCategory,long nCategory,LPCTSTR pszCategory) :
561 m_strParentCategory(pszParentCategory),
562 m_nCategory(nCategory),
563 m_strCategory(pszCategory)
567 CCF_FolderType::~CCF_FolderType()
571 const CCF_FolderType &CCF_FolderType::operator=(const CCF_FolderType &rThat)
575 m_nCategory = rThat.m_nCategory;
576 m_strCategory = rThat.m_strCategory;
577 m_strParentCategory = rThat.m_strParentCategory;
582 CCF_FolderType::CCF_FolderType(const CCF_FolderType &WebSiteCategory)
584 *this = WebSiteCategory;
587 void CCF_FolderType::Serialize(CArchive &ar)
593 ar >> m_strParentCategory;
599 ar << m_strParentCategory;
603 /////////////////////////////////////////////////
605 void CCF_DBFolderList::Serialize(CArchive &ar)
616 CList<CCF_FolderType,CCF_FolderType&>::Serialize(ar);
619 template <> void AFXAPI SerializeElements <CCF_FolderType>(CArchive& ar, CCF_FolderType *pWebSite, int nCount )
621 for ( int i = 0; i < nCount; i++, pWebSite++ )
623 pWebSite->Serialize(ar);
627 template<> void AFXAPI DestructElements<CCF_FolderType> (CCF_FolderType *pElements, int nCount)
629 for ( int n = 0; n < nCount; n++, pElements++ )
631 pElements->CCF_FolderType::~CCF_FolderType();
635 template<> void AFXAPI ConstructElements<CCF_FolderType> (CCF_FolderType *pElements, int nCount)
637 for ( int n = 0; n < nCount; n++, pElements++ )
639 pElements->CCF_FolderType::CCF_FolderType();
643 ///////////////////////////////////////////////////
644 template <> void AFXAPI SerializeElements <CCF_WebSite>(CArchive& ar, CCF_WebSite *pWebSite, int nCount )
646 for ( int i = 0; i < nCount; i++, pWebSite++ )
648 pWebSite->Serialize(ar);
652 template<> void AFXAPI DestructElements<CCF_WebSite> (CCF_WebSite *pElements, int nCount)
654 for ( int n = 0; n < nCount; n++, pElements++ )
656 pElements->CCF_WebSite::~CCF_WebSite();
660 template<> void AFXAPI ConstructElements<CCF_WebSite> (CCF_WebSite *pElements, int nCount)
662 for ( int n = 0; n < nCount; n++, pElements++ )
664 pElements->CCF_WebSite::CCF_WebSite();