CSDN上的一个帖子,我好像没有遇到问题,楼主的代码我也没有仔细调
关于copy/paste和Dragdrop的问题。
我在我的应用程序中增加了copy/paste和DragDrop功能,我把原来的window_Format matefile改成了enhanced-format metafile,这时我的程序可以和安全的向word中进行copy/paste,但不能dragdrop(拖放),在拖源方一切正常,当我在word是松开拖放键时,系统会提示我“内存不足”警告。我不明白为什么.
下面是我ServerItem类的部分代码。
//当对象调用CopyToClipboard和DoDragDrop时,OnGetClipboard被自动调用。
COleDataSource* CSrvrItem::OnGetClipboardData(BOOL bIncludeLink,
LPPOINT pptOffset, LPSIZE pSize)
{
ASSERT_VALID(this);
COleDataSource* pDataSource = new COleDataSource;
TRY
{
GetNativeClipboardData(pDataSource);
GetEnhMetaFileToClip(pDataSource);//增加增强图元到数据对象。
GetClipboardData(pDataSource, bIncludeLink, pptOffset, pSize);
//把即将复制到剪贴板中的所有数据(如果调用CopyToClipboard)填充指定的COleDataSource对象中
}
CATCH_ALL(e)
{
delete pDataSource;
THROW_LAST();
}
END_CATCH_ALL
ASSERT_VALID(pDataSource);
return pDataSource;
}
//被OnGetClipboardData所调用。
void CSrvrItem::GetNativeClipboardData(COleDataSource *pDataSource)
{
ASSERT_VALID(this);
ASSERT(CCvtGraphDoc::m_cfFirst != NULL);
// Create a shared file and associate a CArchive with it
CSharedFile file;
CArchive ar(&file,CArchive::store);
// Serialize selected objects to the archive
dview.m_selection.Serialize(ar);
ar.Close();
// put on local format instead of or in addation to COleDataSource
pDataSource->CacheGlobalData(CCvtGraphDoc::m_cfFirst,file.Detach());
}
//重载函数。
BOOL CSrvrItem::OnRenderData( LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium )
{
ASSERT_VALID(this);
ASSERT(AfxIsValidAddress(lpFormatEtc, sizeof(FORMATETC), FALSE));
ASSERT(AfxIsValidAddress(lpStgMedium, sizeof(STGMEDIUM)));
// default implementation does not support extended layout
if (lpFormatEtc->lindex != -1)
return FALSE;
// default implementation supports both types of metafiles
//去掉原先的Window_format metafile支持。
//if (lpFormatEtc->cfFormat == CF_METAFILEPICT)
// return GetMetafileData(lpFormatEtc, lpStgMedium);
return FALSE; // cfFormat not supported
}
void CSrvrItem::GetEnhMetaFileToClip(COleDataSource* pDataSource)
{
// Obtain a handle to a reference DC.
HDC hdcRef = GetDC(gpView->m_hWnd);
// Determine the picture frame dimensions.
// iWidthMM is the display width in millimeters.
// iHeightMM is the display height in millimeters.
// iWidthPels is the display width in pixels.
// iHeightPels is the display height in pixels.
int iWidthMM = GetDeviceCaps(hdcRef, HORZSIZE);
int iHeightMM = GetDeviceCaps(hdcRef, VERTSIZE);
int iWidthPels = GetDeviceCaps(hdcRef, HORZRES);
int iHeightPels = GetDeviceCaps(hdcRef, VERTRES);
// Use iWidthMM, iWidthPels, iHeightMM, and iHeightPels to determine the number of .01-millimeter units per pixel in the x and y directions.
int iMMPerPelX = (iWidthMM * 100)/iWidthPels;
int iMMPerPelY = (iHeightMM * 100)/iHeightPels;
CClientDC dc(gpView);
CRect rcSelBox;
gpView->OnPrepareDC(&dc);
dview.CalcSelectedItemRect(&dc,rcSelBox);
//convert from the word coordinates to the client coordinates;
dview.DocToClient(rcSelBox,gpView);
CPoint ptTopLeft = rcSelBox.TopLeft();
CSize rSize = rcSelBox.Size();
AdjustSize(rSize);//适当调整包围盒大小。
// Convert client coordinates to .01-mm units.
rSize.cx = rSize.cx * iMMPerPelX;
rSize.cy = rSize.cy * iMMPerPelY;
ptTopLeft = CPoint (0,0);
CRect rcNew(ptTopLeft,rSize);
CClientDC cdc(gpView);
CMetaFileDC * pMetaDC = new CMetaFileDC();
BOOL bRet = pMetaDC->CreateEnhanced(&cdc,NULL,rcNew,"whatever");
if(bRet == FALSE)
{
TRACE("Create Enhanced metafile failed!/n");
return;
}
// create attribute DC according to lpFormatEtc->ptd
HDC hAttribDC = ::GetDC(gpView->GetSafeHwnd());
if (hAttribDC == NULL)
{
TRACE("Create attribute DC failed!/n");
return;
}
pMetaDC->SetAttribDC(hAttribDC);
CSize size;
this->OnDraw(pMetaDC); //在增加图元中画。
pMetaDC->HIMETRICtoLP(&rSize);
pMetaDC->SetAttribDC(NULL);
::DeleteDC(hAttribDC);
//close meta file dc and prepare for clipboard;
HENHMETAFILE hMF = pMetaDC->CloseEnhanced();
tagSTGMEDIUM * data = new tagSTGMEDIUM;
data->tymed = TYMED_ENHMF;
data->hEnhMetaFile = hMF;
data->pUnkForRelease = NULL;
tagFORMATETC* fec = new tagFORMATETC;
fec->cfFormat = CF_ENHMETAFILE;
fec->dwAspect = DVASPECT_CONTENT;
fec->ptd = NULL;
fec->tymed = TYMED_ENHMF;
fec->lindex = -1;
pDataSource->CacheData(CF_ENHMETAFILE, data,fec);
delete pMetaDC;
}