初始化托拽
要让IE接受扯拽了文件,我们必须做的事是创造CF_HDROP数据和投入它在数据对象。 当然,如果它是简单的类型,我不会有什么写。 DROPFILES struct生成是棘手的 (因为它总是不是相同大小),但是,在您一次写代码之后 (或,在我一次写它!)之后 您能重复利用它到处。
当您选择在list的文件并且扯拽他们时, MultiFiler初始化拖放。当这发生时List控件传送LVN_BEGINDRAG信息,因此是MultiFiler创造数据对象并着手对OLE开始拖放操作。
在创造DROPFILES的步骤是:
1. 列举所有在list的选择的项目,把他们放入string list。
2. 当把它加入list string,记录每串的长度。
3. 分配DROPFILES的内存和文件名单。
4. 填写DROPFILES成员。
5. 复制文件名单入分配的内存。
I'll go over the MultiFiler code now, so you can see exactly how to set up a DROPFILES. If you feel like checking out the source in the MultiFiler projects, all three do it the same way, so you can look at any of the three.
The first step is to put all of the selected filenames in a list, and keep track of the memory needed to hold all of the strings.
我现在将去看看MultiFiler代码,以便您能正确地看到如何设定DROPFILES。 如果您感觉象检查在MultiFiler项目的来源,它们都做同一个方式。
第一步放入所有选择的文件名单,并且纪录需要保存所有串的内存。
void CMultiFilerDlg::OnBegindragFilelist(NMHDR* pNMHDR, LRESULT* pResult)
{
CStringList lsDraggedFiles;
POSITION pos;
CString sFile;
UINT uBuffSize = 0;
// For every selected item in the list,
// put the filename into lsDraggedFiles.
// c_FileList is our dialog's CListCtrl.
pos = c_FileList.GetFirstSelectedItemPosition();
while ( NULL != pos )
{
nSelItem = c_FileList.GetNextSelectedItem ( pos );
// put the filename in sFile
sFile = c_FileList.GetItemText ( nSelItem, 0 );
lsDraggedFiles.AddTail ( sFile );
// Calculate the # of chars required to hold this string.
uBuffSize += lstrlen ( sFile ) + 1;
}
At this point, uBuffSize holds the total length of all the strings, including nulls, in characters. We add 1 for the final null to terminate the list, then multiply that by sizeof(TCHAR) to convert from characters to bytes. We then add sizeof(DROPFILES) to get the final required buffer size.
这时, uBuffSize保存所有串的总长度,包括NULL字符。 我们加1b最后以NULL终止list,然后乘以sizeof (TCHAR)从字符转换到字节。 然后加sizeof (DROPFILES)得到最终的必需的缓冲区大小。
// Add 1 extra for the final null char,
// and the size of the DROPFILES struct.
uBuffSize = sizeof(DROPFILES) + sizeof(TCHAR) * (uBuffSize + 1);
现在我们知道我们需要多少内存了,我们可以通过使用GlobalAlloc()分配他们当我们托拽的时候。
HGLOBAL hgDrop;
DROPFILES* pDrop;
// Allocate memory from the heap for the DROPFILES struct.
hgDrop = GlobalAlloc ( GHND | GMEM_SHARE, uBuffSize );
if ( NULL == hgDrop )
return;
我们通过 GlobalLock():访问内存块
pDrop = (DROPFILES*) GlobalLock ( hgDrop );
if ( NULL == pDrop )
{
GlobalFree ( hgDrop );
return;
}
现在我们开始填充DROPFILES. GHND在 GlobalAlloc() 调用初始化是设置内存位0.,我们只需要设置这两个参数。
// Fill in the DROPFILES struct.
pDrop->pFiles = sizeof(DROPFILES);
#ifdef _UNICODE
// If we're compiling for Unicode, set the Unicode flag in the struct to
// indicate it contains Unicode strings.
pDrop->fWide = TRUE;
#endif
注意pFiles成员不表明DROPFILES struct的大小; 它是文件list的偏移。 但是,因为在struct之后的末端文件名list位于它的偏移等同于struct的大小。
现在我们可以复制所有文件名入内存,然后打开缓冲。
TCHAR* pszBuff;
// Copy all the filenames into memory after
// the end of the DROPFILES struct.
pos = lsDraggedFiles.GetHeadPosition();
pszBuff = (TCHAR*) (LPBYTE(pDrop) + sizeof(DROPFILES));
while ( NULL != pos )
{
|