>>I am having a bit of trouble with delayed rendering
better to use COleDataSource::CacheData.
http://download.microsoft.
-MAHESH
Main Topics
Browse All TopicsI am having a bit of trouble with delayed rendering when dragging a file from my app (onto for example a Windows explorer window).
I am getting multiple calls to delay render, most of which I would like to ignore, I only actually want to "render" my data when the file is dropped on a target (like when the user lets go of the mouse button). But OnRenderGlobalData is called numerous times before that including when the file is first dragged, when the drag item passes outside of my apps focus, etc, etc.
I've seen a number of posts in other forums and on here where people have asked the same question, but not one of them has a reply or solution.
This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.
Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.
If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.
Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.
Access the answers to your technology questions today.
30-day free trial. Register in 60 seconds.
Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Try it out and discover for yourself.
30-day free trial. Register in 60 seconds.
Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.
>>I am having a bit of trouble with delayed rendering
better to use COleDataSource::CacheData.
http://download.microsoft.
-MAHESH
Thats what I expected too. But it generates multiple messages as I said - when first dragged, when passing focus to other applications windows and the final message being when dropped (mouse button up).
I'll give more detail.
I have implemented my own instance of COleDropSource and I am overwriding "virtual BOOL OnRenderGlobalData(LPFORMA
In my CListControl derived class I have a list of files on a device that I have to read (its not a Windows format). When the user drags file(s) from it and drop them on say an Explorer window, I first get the OnDragDrop message in my list control where I make a list of filenames for my render routine and I tell windows to use my COleDataSource derived class to send the render message to.
So, when my CMyOleDropSource::OnRender
Of course, since "CMyOleDropSource::OnRende
Here is the code:-
// In my list control, on a drag event, I pass a list of filenames
void CShellListCtrl::OnDragDrop
{
TRACE( "CShellListCtrl::OnDragDro
CStringList *lsSourceDraggedFiles;
int nSelItem;
CString sFile;
lsSourceDraggedFiles = new CStringList;
// lsSourceDraggedFiles is my list of files that are being dragged, this is
// just a list I want my render routine to get so it knows what to render/copy.
CMyOLEDragDrop *pDataSource = new CMyOLEDragDrop();
BOOL bAbort = FALSE;
struct sFileInfo *psFileInfo=NULL;
POSITION pos = m_pListCtrl->GetFirstSelec
while (NULL != pos && !bAbort) // Repeat for all drag items
{
nSelItem = m_pListCtrl->GetNextSelect
psFileInfo = (struct sFileInfo *)m_pListCtrl->GetItemData
if( psFileInfo!=NULL )
{
sFile = psFileInfo->csPath; // Filename of drag item
CString csPass;
csPass.Format( "%s%i%i", psFileInfo->csPath, psFileInfo->iAttribs, psFileInfo->iPartition );
lsSourceDraggedFiles->AddT
}
}
pDataSource->SetCallDatas(
pDataSource->DoDragDrop(DR
delete pDataSource;
TRACE( "out CShellListCtrl::OnDragDrop
return;
}
// In my COleDropSource derived class
BOOL CMyOleDropSource::OnRender
{
VERIFY(lpFormatEtc->cfForm
// Allocate space for DROPFILE structure plus the file path and one extra
// byte for final NULL terminator
*phGlobal = GlobalAlloc(GHND|GMEM_SHAR
if (*phGlobal)
{
// Make temp file name
BOOL bAbort = FALSE;
if( m_plsDraggedFiles != NULL )
{
POSITION pos;
TCHAR szBuff[MAX_PATH*2];
pos = m_plsDraggedFiles->GetHead
int nSelItem;
CString csFile="";
CStringList *plsNewList = new CStringList;
while (NULL != pos)
{
lstrcpy (szBuff, (LPCTSTR) m_plsDraggedFiles->GetNext
TRACE( "szBuff=%s\n", szBuff );
// Copy the file to our temp folder
struct sFileInfo sFileInfo;
sFileInfo.csPath = szBuff;
sFileInfo.iAttribs = sFileInfo.csPath.GetAt(sFi
sFileInfo.iPartition = sFileInfo.csPath.GetAt(sFi
int iLen = sFileInfo.csPath.GetLength
sFileInfo.csPath = sFileInfo.csPath.Left( iLen-2 );
// Mark this entry as processed as we get multiple calls to the render routine at present!!!
szBuff[_tcslen(szBuff)-2] = 0xff;
plsNewList->AddTail(szBuff
CString csDestFile;
CString csTemp; // Destination on PC (temp folder)
csTemp = g_AppPathName;
csTemp += "\\Temp\\";
if( sFileInfo.iAttribs>=0 )
{
if( CopyFileOrFolder( &sFileInfo, csTemp, csDestFile )!=0 )
bAbort = TRUE;
}
else
{
csDestFile = g_AppPathName;
csDestFile += "\\temp\\";
CString cs = ExtractFileName( sFileInfo.csPath );
csDestFile += cs;
}
if( !bAbort )
{
csFile.Append( csDestFile );
csFile.Append( "\1" );
}
}
delete m_plsDraggedFiles;
m_plsDraggedFiles = plsNewList;
if( !bAbort )
{
int iLen = csFile.GetLength()+2;
TCHAR *szStr = (TCHAR*)malloc( iLen );
_tcscpy( szStr, csFile.GetBuffer() );
TRACE( "To Exp: %s\n", szStr );
ReplaceAllChars( szStr, '\1', '\0' );
// Last string will end with two 0 bytes.
LPDROPFILES pDropFiles;
pDropFiles = (LPDROPFILES)GlobalLock(*p
// Set the offset where the starting point of the file start
pDropFiles->pFiles = sizeof(DROPFILES);
// File doesn't contain wide characters
pDropFiles->fWide=FALSE;
// Copy file name.
memcpy(((LPSTR)pDropFiles)
free( szStr );
}
}
GlobalUnlock(*phGlobal);
return TRUE;
}
return *phGlobal!=NULL;
}
> better to use COleDataSource::CacheData.
> http://download.microsoft.
> -MAHESH
Thanks for the comment MAHESH. I've expanded my explanation of my problem, I am using COleDataSource and hence COleDataSource::OnRenderGl
I am using CF_HDROP format.
That sample doesn't work by the way, it doesn't run properly in VC++ 6 or 7 I think it is just a very old Win32 sample that doesn't quite work anymore; But as in the sample, that is essentially what I am doing.
It all works fine apart from getting multiple calls to OnRenderGlobalData. I assume what is happening is that other windows who see the drag item passing over them, take a sneaky peek at what is being dragged and cause me to have to render the data. When I only really want to do is render the data when the real drop happens (the user lets go of the mouse button on an explorer window or editor).
In reply to Andy:
The whole thing relies on me getting a "CMyOleDropSource::OnRende
When writing the code I expected "CMyOleDropSource::OnRende
My problem is - I don't know when the last call is, or when the user has actually let go of the mouse button.
The passed parameters to "BOOL CMyOleDropSource::OnRender
Hold on, I have found a solution:
I have implemented a class COleDropSource derived class and passed it to the call of DoDragDrop in my OnDragDrop function.
class CMyDropSource : public COleDropSource
{
public:
CMyDropSource(CMyOLEDragDr
virtual ~CMyDropSource();
virtual SCODE QueryContinueDrag(BOOL bEscapePressed, DWORD dwKeyState);
private:
CMyOLEDragDrop *pDataSource;
};
// Added this to the bottom of my OnDragDrop (changing the existing call to pDataSource->DoDragDrop)
CMyDropSource DropSource(pDataSource);
pDataSource->DoDragDrop(DR
Now I can track the drag in the QueryContinueDrag override:
CMyDropSource::CMyDropSour
: COleDropSource()
, pDataSource(pDataSourcePar
{}
CMyDropSource::~CMyDropSou
{
//delete pDataSource;
}
SCODE CMyDropSource::QueryContin
{
SCODE sCode = COleDropSource::QueryConti
if ( sCode == DRAGDROP_S_DROP ) {
if ( pDataSource != NULL )
pDataSource->some function to say it is actually dropped...
}
return sCode;
}
Here is how It can be used :
STDMETHODIMP CDropSource::GiveFeedback(
{
return DRAGDROP_S_USEDEFAULTCURSO
}
STDMETHODIMP CDropSource::QueryContinue
{
if ( bEscapePressed) // If ESC was pressed, cancel the drag.
return DRAGDROP_S_CANCEL;
else
if ( (dwKeyState & MK_LBUTTON) ==0) // If the left button was released, continue with the drag-drop
return DRAGDROP_S_DROP;
else
return S_OK; // continue with the drag-drop
}
-MAHESH
Business Accounts
Answer for Membership
by: AndyAinscowPosted on 2006-10-03 at 06:07:23ID: 17651105
I am a bit uncertain of what your problem is. You say you only want to render when the file is dropped on the target - the drop should only generate a message once (mouse button up).