VC如何实现跨进程拖拽文件,鼠标移动到进程其可自动弹出并置为前端

tulingwangbo 2016-11-08 04:30:26
http://bbs.csdn.net/topics/391835635?page=1#post-401756325
4楼回复的方法确实可以实现跨进程拖拽文件(比如进程A中拖到进程B中),但现在有个问题,进程A的界面比较大,那么从A拖动文件到B时候因为B最小化了,我就拖到任务栏B的图标位置,如何让B弹出并置为前端窗口,尝试了遍历任务栏进程的方法,不太好使,我看了百度云客户端等软件,都可以跨进程拖拽,比如百度云拖动到windows文件夹、浏览器等都可以;而且人家都还有提示功能,比如拖动到浏览器,鼠标还未松开,浏览器就会变色并提示“即将打开文件**”等,这个怎么做到啊?
...全文
724 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
tulingwangbo 2016-11-21
  • 打赏
  • 举报
回复
不好意思,11.18论坛出了点问题,导致我看不到大家的回复,以为没有人回复呢。今天尝试了下16楼的方法,效果还不错,可以跨进程拖拽到暴风影音、浏览器等,但是拖拽到百度云里却没能成功,不过无所谓了。效果如下:


16 17楼的方法类似,都是调用ole的接口函数,把DROPFILES结构放入到拖拽数据对象中,然后调用ole的DoDragDrop实现拖拽功能。修正下拖拽接口DragDropTo(/*WCHAR* path*/ CStringArray &arrFiles),可以实现多选文件(或文件夹)拖拽:
DragDropTo(/*WCHAR* path*/ CStringArray &arrFiles)
{
//memcpy(pData, path, sizeof(WCHAR)*wcslen(path));
for (int i=0; i<arrFiles.GetSize(); i++)
{
CString filePath = arrFiles.GetAt(i);
_tcscpy((LPTSTR)pData, filePath);
pData += (filePath.GetLength() +1)*2;
}
}
BeanJoy 2016-11-18
  • 打赏
  • 举报
回复
引用 18 楼 tulingwangbo 的回复:
怎么没有人回复了,分太少了,还是没有人知道怎么做?
要不要人手把手把代码帮你写好再发给你? 好歹也是写程序的,怎么一点学习研究心理都没有。 16、17都都已经给你说过了,这要使用拖拽功能(OLE Drag\Drop)就能实现,17楼也给了个demo,自己不去研究,干脆改行吧。
tulingwangbo 2016-11-18
  • 打赏
  • 举报
回复
怎么没有人回复了,分太少了,还是没有人知道怎么做?
BeanJoy 2016-11-14
  • 打赏
  • 举报
回复
通过msdn了解了下dropdrop功能,参考OLE Drap/Drop(1)这篇文章,我将微软的drgdrps.exe和drgdrpt.exe下载下来了,用vs2008编译了,可以实现文字的拖放,如下图,代码下载地址windows drag/drop拖放操作示例代码 ,按住鼠标左键时,再移动鼠标到任务栏应用程序的按钮上,相应的程序会恢复:

MSDN上也建议这样实现拖放功能,避免使用WM_DROPFILES来实现,原文件如下:
引用
Implement and register an OLE drop target. Avoid using Microsoft Windows 3.1 targets or the WM_DROPFILES message, if possible.
void_main_void 2016-11-13
  • 打赏
  • 举报
回复
http://www.xuwu.org/dragdropto/ OLE拖拽。复制即可使用。
BeanJoy 2016-11-11
  • 打赏
  • 举报
回复
引用 14 楼 BeanJoy 的回复:
看起来,drag & drop的功能设计,一开始就太对。应该调用windows
还没说完就发送了 应该调用windows提供的接口来实现,你这样子是直接发送的dragdrop消息给目标进程,并不是正规的方法。
BeanJoy 2016-11-11
  • 打赏
  • 举报
回复
看起来,drag & drop的功能设计,一开始就太对。应该调用windows
tulingwangbo 2016-11-11
  • 打赏
  • 举报
回复
打不开网址,有没有人知道怎么解决啊?寻找方法中....
BeanJoy 2016-11-10
  • 打赏
  • 举报
回复
要获取win7版本以上系统任务栏的信息比较麻烦,win7以下系统使用了未公开的类MSTaskListWClass描述任务栏,目前我还没有找到很好的办法来获取任务栏上图标的个数以及信息,你可以参考这个How to find the position of a taskbar button on Windows 7 or Vista,通过判断图标的RGB信息和对比来查找的,方法不太优雅。
BeanJoy 2016-11-09
  • 打赏
  • 举报
回复
把你那程序发上来看看呢
BeanJoy 2016-11-09
  • 打赏
  • 举报
回复
引用 6 楼 tulingwangbo 的回复:
我想实现在自己的进程拖拽一个条目,到其他进程时,那个进程可以自动restore(弹出并置为前端窗口),该如何实现?

这个功能windows本身就有啊,你看下是不是这样:
tulingwangbo 2016-11-09
  • 打赏
  • 举报
回复
我从自己的程序列表中拖动一个条目到任务栏,它不会自动弹出啊? 但是在windows问价夹中,拖动一个文件到任务栏可以自动弹出,百度云也可以,自己的程序中怎么实现?
tulingwangbo 2016-11-09
  • 打赏
  • 举报
回复
拖拽是在自己程序中写的,不是从windows拖,是从自己列表中拖到其他进程。 int WrapDropMsgAndSend(CPoint point, CStringArray &arrFiles, CWnd *pwndTarget) { if (arrFiles.GetSize() <= 0) { return -1; } LRESULT lr = 0; int i=0,j = 0; CString str; char tmpc[MAX_PATH] = {0}; DWORD pid; HWND hwndTop; HWND hwndPt = WindowFromPoint(point); CPoint ptCursor(point);//ClientToScreen对话框内部函数可调用,外部普通函数怎么用不了? ClientToScreen(NULL, &ptCursor); CWnd* pDropTargetWnd = CWnd::WindowFromPoint(ptCursor); CWnd* pDropWnd = NULL; int iret = ::GetWindowThreadProcessId( /*hwndPt*/pwndTarget->m_hWnd,&pid); GetTopHwndByPID(pid, hwndTop); //注:一个pid对应多个窗口,发送的窗口不能是光标点的pwndTarget,应该是响应消息的窗口(姑且用顶层窗口,有问题再想法子) if (iret <= 0) { return -2; } //若是windows目录,则复制文件 (windows目录收到DROPFILES没反应) str = GetWindowsPath(pwndTarget->GetSafeHwnd()); if (str.Find(L":\\") > 0) { CString strSrcPath, strDstPath; BOOL bCopy = FALSE; strDstPath = str; for(int i=0; i<arrFiles.GetSize(); i++) { strSrcPath = arrFiles.GetAt(i); int nPos = strSrcPath.ReverseFind(_T('\\')); CString strFileName = strSrcPath.Right(strSrcPath.GetLength() - nPos -1); strDstPath += strFileName; bCopy = CopyFile(strSrcPath,strDstPath,TRUE); } return 0; } //若是其他进程,则发送DROPFILES消息 if (pid != GetCurrentProcessId()) { ////-------封装Drop消息----------------///// int cbstrSize = 0; int sizedropfiles = sizeof(_DROPFILES); for (i=0; i<arrFiles.GetSize(); i++) { str = arrFiles.GetAt(i); cbstrSize += str.GetLength() + 1; } //字符串缓存大小 int bufSize = sizedropfiles + cbstrSize; //申请Com缓存 //IntPtr pdbuf = Marshal.AllocCoTaskMem(bufSize); // GlobalAlloc HeapAlloc() CoTaskMemAlloc() TCHAR *pdbuf = new TCHAR[bufSize]; ZeroMemory(pdbuf, bufSize*2); DROPFILES* dropfiles = (DROPFILES*)pdbuf; //计算字符串的地址 TCHAR* pstrbuf = (pdbuf + sizedropfiles/2); //移动到第21字节位置 //构造本地的DROPFILES dropfiles->pFiles = sizedropfiles; dropfiles->pt = CPoint(0,0); dropfiles->fNC = 0; dropfiles->fWide = 1;//是否使用Unicode字符 //复制填充字符串 //Marshal.Copy(strbuf, 0, pstrbuf, strbuf.Length); for (i=0; i<arrFiles.GetSize(); i++) { CString filePath = arrFiles.GetAt(i); _tcscpy(pstrbuf, filePath); pstrbuf += filePath.GetLength() +1; } ///-----------发送给目标窗口--------------/// HANDLE hproc; //打开进程 hproc = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, false, pid); if (hproc == 0) return -3; //申请远程内存 LPVOID ptrRemote = VirtualAllocEx(hproc, 0, bufSize*2, MEM_COMMIT, PAGE_READWRITE); if (ptrRemote == NULL) goto clear; SIZE_T writecount; //写入目标进程 if (WriteProcessMemory(hproc, ptrRemote, (LPCVOID)dropfiles, bufSize*2, &writecount)) { //实际应发送给响应Drop消息的窗口,这里获取不到,姑且发给顶层窗口和光标所在窗口吧 lr = ::SendMessage(hwndTop /*pwndTarget->m_hWnd*/, WM_DROPFILES, (WPARAM)ptrRemote, 0); lr = ::SendMessage(pwndTarget->m_hWnd, WM_DROPFILES, (WPARAM)ptrRemote, 0); } clear://收尾工作 delete pdbuf; if (ptrRemote != 0) { //释放远程内存 if (!VirtualFreeEx(hproc, ptrRemote, 0, MEM_RELEASE)) { throw; } } //关闭句柄 CloseHandle(hproc); } return 0; } CDYListCtrl::OnMouseMove(UINT nFlags, CPoint point) { if (m_iDragMode == DRAG_S_ITEM ) ::SetCursor(m_hCursorDrag[3]);//加载拖住啊光标 //?如何在鼠标移动到底部任务栏时,可以让对应进程弹出并置到z序前端;WindowFromPoint //可以获取桌面鼠标所在点的窗口指针,但是无法获取任务栏图标的窗口指针; } void CDYListCtrl::OnLButtonUp(UINT nFlags, CPoint point) { if (DRAG_S_ITEM == m_iDragMode) { CWnd* pDropTargetWnd = WindowFromPoint(point);//鼠标送开点的窗口 CStringArray arrFiles; GetSelFiles(arrFiles);//获得拖拽的文件 WrapDropMsgAndSend(point, arrFiles, pDropTargetWnd);//包装DROPFILES消息并发送给目标进程窗口 } }
Dobzhansky 2016-11-08
  • 打赏
  • 举报
回复
windows 自动给你激活窗口。
那个窗口能否接受你拖进去的东西,就不是你说了算了。
tulingwangbo 2016-11-08
  • 打赏
  • 举报
回复
我想实现在自己的进程拖拽一个条目,到其他进程时,那个进程可以自动restore(弹出并置为前端窗口),该如何实现?
BeanJoy 2016-11-08
  • 打赏
  • 举报
回复
我都糊涂了,你到底想实现什么功能。
tulingwangbo 2016-11-08
  • 打赏
  • 举报
回复
我也想要这个功能,在自己的进程中实现,参考了百度云、迅雷、FileZallar等软件,感觉应该是把光标变成了拖拽文件的状态,从而可以出发一些windows消息,不知道怎么实现的?学习中....
BeanJoy 2016-11-08
  • 打赏
  • 举报
回复
我测试了win10,若进程是最小化的,当我拖动文件到任务栏进程图标上时,相应的进程会恢复的。
tulingwangbo 2016-11-08
  • 打赏
  • 举报
回复
http://download.csdn.net/detail/tulingwangbo/9638587 目前已经实现了跨进程拖拽的功能,我可以把列表中的图片拖拽到暴风影音、或者浏览器;但是若暴风影音或浏览器最小化了,我拖拽列表中文件到任务栏图标后如何让进程弹出窗口并置为前端,以便于松开文件?
BeanJoy 2016-11-08
  • 打赏
  • 举报
回复
这个是进程B的自定义形为,不是进程A能决定的。 比如进程B没有实现文件拖拽功能,那么就算你将文件拖到进程B上,进程B也没有反应。

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧