Drag Drop Win API 32
Drag Drop Win API 32
我正在尝试将ListView项从我的程序拖放到另一个程序(例如将路径拖动到VLC上,然后播放视频文件)。我使用的是CF_HDROP剪贴板格式。CopySelect 是将 STGMEDIUM hglobal 变量设置为 DROPFILES 结构的原因。
void CopySelection(HWND hwndList, STGMEDIUM &stgmed)
{
HGLOBAL hMem;
DROPFILES *ptr;
DROPFILES dfiles;
POINT p;
// get the selection inside the list control
int iPos = SendMessage(hwndList, LVM_GETNEXTITEM, (WPARAM)-1,(LPARAM)LVNI_SELECTED);
cout << "iPos: " << iPos << endl;
LVITEM item;
char buffer[256];
string fileDir = "";
item.iItem = iPos;
item.iSubItem = 1;
item.cchTextMax = 256;
item.pszText = buffer;
item.mask = LVIF_TEXT;
ListView_GetItem(hwndList, &item);
fileDir += string(item.pszText);
fileDir += "\";
item.iItem = iPos;
item.iSubItem = 0;
ListView_GetItem(hwndList, &item);
fileDir += string(item.pszText);
item.iItem = iPos;
item.iSubItem = 2;
ListView_GetItem(hwndList, &item);
fileDir += string(item.pszText);
cout << "fileDir: " << fileDir << endl;
hMem = GlobalAlloc(GHND, sizeof(DROPFILES));
ptr = (DROPFILES *)GlobalLock(hMem);
dfiles.fNC = TRUE;
dfiles.fWide = FALSE;
memcpy((void*)&dfiles.pFiles, (fileDir.c_str()+' '), fileDir.size()+1);
GetCursorPos(&p);
dfiles.pt=p;
// copy the selected text and nul-terminate
memcpy(ptr, (void*)&dfiles, sizeof(DROPFILES));
GlobalUnlock(hMem);
stgmed.hGlobal = hMem;
//return hMem;
}
但这似乎会导致段错误。下面是调用它的鼠标移动列表消息代码:
case WM_MOUSEMOVE:
{
// stop drag-drop from happening when the mouse is released.
if(fMouseDown)
{
IDataObject *pDataObject;
IDropSource *pDropSource;
DWORD dwEffect;
DWORD dwResult;
FORMATETC fmtetc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stgmed = { TYMED_HGLOBAL , { 0 }, 0 };
// transfer the current selection into the IDataObject
CopySelection(hwnd, stgmed);
cout << "DO WE?" << endl;
// Create IDataObject and IDropSource COM objects
CreateDropSource(&pDropSource);
CreateDataObject(&fmtetc, &stgmed, 1, &pDataObject);
//
// ** ** ** The drag-drop operation starts here! ** ** **
//
//dwResult = DoDragDrop(pDataObject, pDropSource, DROPEFFECT_COPY|DROPEFFECT_MOVE, &dwEffect);
dwResult = DoDragDrop(pDataObject, pDropSource, DROPEFFECT_COPY, &dwEffect);
// success!
if(dwResult == DRAGDROP_S_DROP)
{
if(dwEffect & DROPEFFECT_MOVE)
{
// remove selection from list control
}
else if(dwEffect & DROPEFFECT_LINK)
{
}
}
// cancelled
else if(dwResult == DRAGDROP_S_CANCEL)
{
}
pDataObject->Release();
pDropSource->Release();
ReleaseCapture();
fMouseDown = FALSE;
fDidDragDrop = TRUE;
}
代码格式正确(我已经检查过),但不确定为什么这不起作用。我什至使用正确的 OLE 剪贴板格式来实现这一点吗?我不确定要使用哪个,我找到的文档也不是很好。
干杯抢
附言我试图改编这个例子:http://www.catch22.net/tuts/drop-source
不同的是,他只是移动文本,而我试图移动文件列表(例如在窗口中选择图标并拖动到视频播放器上)。
您没有为HGLOBAL
块分配足够的内存。 您只分配了足够的内存来保存DROPFILES
本身,但没有内存来保存随之而来的文件名。但是,即使您正确分配了内存,也没有正确使用DROPFILES::pFiles
字段。 它需要指定从文件名列表开始的DROPFILES
结构开头的偏移量,但您将其视为内存地址。
试试这个:
HGLOBAL CopySelection(HWND hwndList)
{
// get the selection inside the list control
int iPos = SendMessage(hwndList, LVM_GETNEXTITEM, (WPARAM)-1,(LPARAM)LVNI_SELECTED);
if (iPos == -1)
return NULL;
cout << "iPos: " << iPos << endl;
LVITEM item = {0};
char buffer[256];
string fileDir;
item.cchTextMax = 256;
item.pszText = buffer;
item.mask = LVIF_TEXT;
item.iItem = iPos;
item.iSubItem = 1;
ListView_GetItem(hwndList, &item);
fileDir = item.pszText;
fileDir += "\";
item.iItem = iPos;
item.iSubItem = 0;
ListView_GetItem(hwndList, &item);
fileDir += item.pszText;
item.iItem = iPos;
item.iSubItem = 2;
ListView_GetItem(hwndList, &item);
fileDir += item.pszText;
cout << "fileDir: " << fileDir << endl;
// +2 = the filename's null terminator and the file list's null terminator
HGLOBAL hMem = GlobalAlloc(GHND, sizeof(DROPFILES) + fileDir.length() + 2);
if (!hMem)
return NULL;
DROPFILES *dfiles = (DROPFILES*) GlobalLock(hMem);
if (!dfiles)
{
GlobalFree(hMem);
return NULL;
}
dfiles->pFiles = sizeof(DROPFILES);
GetCursorPos(&(dfiles->pt));
dfiles->fNC = TRUE;
dfiles->fWide = FALSE;
memcpy(&dfiles[1], fileDir.c_str(), fileDir.length());
GlobalUnlock(hMem);
return hMem;
}
.
case WM_MOUSEMOVE:
{
// stop drag-drop from happening when the mouse is released.
if (fMouseDown)
{
IDataObject *pDataObject;
IDropSource *pDropSource;
DWORD dwEffect;
DWORD dwResult;
FORMATETC fmtetc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stgmed = { TYMED_HGLOBAL , { 0 }, 0 };
// transfer the current selection into the IDataObject
stgmed.hGlobal = CopySelection(hwnd);
if (stgmed.hGlobal)
{
cout << "DO WE?" << endl;
// Create IDataObject and IDropSource COM objects
CreateDropSource(&pDropSource);
CreateDataObject(&fmtetc, &stgmed, 1, &pDataObject);
//
// ** ** ** The drag-drop operation starts here! ** ** **
//
//dwResult = DoDragDrop(pDataObject, pDropSource, DROPEFFECT_COPY|DROPEFFECT_MOVE, &dwEffect);
dwResult = DoDragDrop(pDataObject, pDropSource, DROPEFFECT_COPY, &dwEffect);
// success!
if(dwResult == DRAGDROP_S_DROP)
{
if(dwEffect & DROPEFFECT_MOVE)
{
// remove selection from list control
}
else if(dwEffect & DROPEFFECT_LINK)
{
}
}
// cancelled
else if(dwResult == DRAGDROP_S_CANCEL)
{
}
pDataObject->Release();
pDropSource->Release();
ReleaseCapture();
fMouseDown = FALSE;
fDidDragDrop = TRUE;
}
}
如果要一次拖动多个选定文件,请尝试以下操作:
HGLOBAL CopySelection(HWND hwndList)
{
vector<string> files;
UINT len = 0;
// get the selection inside the list control
int iPos = -1;
do
{
int iPos = SendMessage(hwndList, LVM_GETNEXTITEM, iPos, LVNI_SELECTED);
if (iPos == -1)
break;
LVITEM item = {0};
char buffer[256];
string fileDir;
item.cchTextMax = 256;
item.pszText = buffer;
item.mask = LVIF_TEXT;
item.iItem = iPos;
item.iSubItem = 1;
ListView_GetItem(hwndList, &item);
fileDir = item.pszText;
fileDir += "\";
item.iItem = iPos;
item.iSubItem = 0;
ListView_GetItem(hwndList, &item);
fileDir += item.pszText;
item.iItem = iPos;
item.iSubItem = 2;
ListView_GetItem(hwndList, &item);
fileDir += item.pszText;
files.push_back(fileDir);
// +1 = the filename's null terminator
len += (fileDir.length() + 1);
cout << "iPos: " << iPos << ", fileDir: " << fileDir << endl;
}
while (true);
if (files.empty())
return NULL;
// +1 = the file list's null terminator
HGLOBAL hMem = GlobalAlloc(GHND, sizeof(DROPFILES) + len + 1);
if (!hMem)
return NULL;
DROPFILES *dfiles = (DROPFILES*) GlobalLock(hMem);
if (!dfiles)
{
GlobalFree(hMem);
return NULL;
}
dfiles->pFiles = sizeof(DROPFILES);
GetCursorPos(&(dfiles->pt));
dfiles->fNC = TRUE;
dfiles->fWide = FALSE;
char *pFile = (char*) &dfiles[1];
for (vector<string>::size_type i = 0; i < files.size(); ++i)
{
string &fileDir = files[i];
// +1 = the filename's null terminator
len = (fileDir.length() + 1);
memcpy(pFile, fileDir.c_str(), len);
pFile += len;
}
GlobalUnlock(hMem);
return hMem;
}
相关文章:
- sf::Windows上的音乐:api-ms-win-crt-locale-l1-1-0.dll:无法打开共享对象文件
- Win API对齐按钮上的文本
- 放大倍率低于 125% 默认 win API(介于 101 - 124% 之间)
- C++ API-MS-WIN-SERVICE-PRIVATE-L1-1-1.DLL依赖项问题
- [WIN API]为什么共享相同的 WriteFile(sync) 和 ReadFile(sync) 句柄会导致 Rea
- C++ WIN API:为什么我不能使用WM_CREATE
- 如何使用 Win API 获取文件夹中的文件列表(带过滤器)
- win api readConsole()
- 为什么Win API线程执行函数,而标准线程则没有
- 在 Windows 7 下的 Visual Studio 2015 上缺少 Api-ms-win-core-errorh
- 在win API中带有图像和整行选择的组合框
- Drag Drop Win API 32
- Win API串行端口初始化后需要等待
- 在DLL的基地址处Win API ReadProcessMemory返回意外数据
- 控制台应用程序的 WIN API 计时器
- Win 32 API,使用垂直拆分条绘制两个子窗口
- WIN 32 用于检测已启动和终止的应用程序/进程的 API
- Visual Studio 2015 C++ 应用程序需要在客户端客户端上使用 api-ms-win-crt-runti
- 如何通过Win API配置快捷方式标题
- MS Http Server API (< Win 8) 和 WebSockets