C++实现win32窗口文件拖拽

C++实现win32窗口文件拖拽,直接上代码

第一种方法:(使用win32消息实现,无法选择可以拖拽的文件、拖拽的图标也无法像资源管理器那样)

if(uMsg == WM_DROPFILES) {
  HDROP hDrop = (HDROP)wParam;
  UINT uCount = ::DragQueryFileA(hDrop,0xFFFFFFFF,NULL,0);
  if(uCount > 0) {
    char buffer[MAX_PATH]={0};
    char path[MAX_PATH]={0};
    for (UINT i=0;i<uCount;++i) {
      ::DragQueryFileA(hDrop,i,path,MAX_PATH);
      sprintf_s(buffer,"第%d个文件:%s\n",i,path);
      OutputDebugStringA(buffer);
    }
  }
  ::DragFinish(hDrop);
  DragAcceptFiles(m_hWnd,FALSE);
}

注意:
需要创建窗口时需在exStyle添加WS_EX_ACCEPTFILES
或者 this->DragAcceptFiles(TRUE);

需要过滤消息、否则程序以管理员启动会导致拖动无效
BOOL ChangeWndMessageFilter(UINT uMessage, BOOL bAllow) {
  typedef BOOL(WINAPI* ChangeWindowMessageFilterFn)(UINT, DWORD);
  HMODULE hUserMod = NULL;
  BOOL bResult = FALSE;
  hUserMod = LoadLibrary(L"user32.dll");
  if (hUserMod == NULL) {
    return FALSE;
  }

  // 获取ChangeWindowMessageFilter函数接口指针  
  ChangeWindowMessageFilterFn pfnChangeWindowMessageFilter = (ChangeWindowMessageFilterFn)GetProcAddress(hUserMod, "ChangeWindowMessageFilter");
  if (pfnChangeWindowMessageFilter == NULL) {
    FreeLibrary(hUserMod);
    return FALSE;
  }

  bResult = pfnChangeWindowMessageFilter(uMessage, bAllow ? 1 : 2); // 1-MSGFLT_ADD, 2-MSGFLT_REMOVE  
  FreeLibrary(hUserMod);
  return bResult;
}

utils::ChangeWndMessageFilter(0x0049, MSGFLT_ADD);
utils::ChangeWndMessageFilter(WM_DROPFILES, MSGFLT_ADD);

第二章方法:(使用com组件IDropTarget实现)


class MyIDropTarget : public IDropTarget {
public:
	MyIDropTarget()
		:m_pDropTargetHelper(NULL) {
		if (FAILED(CoCreateInstance(CLSID_DragDropHelper, NULL, CLSCTX_INPROC_SERVER,
			IID_IDropTargetHelper, (LPVOID*)&m_pDropTargetHelper)))
			m_pDropTargetHelper = NULL;
	}
	~MyIDropTarget() {
		if (m_pDropTargetHelper != NULL) {
			m_pDropTargetHelper->Release();
			m_pDropTargetHelper = NULL;
		}
	}

	virtual HRESULT STDMETHODCALLTYPE QueryInterface(
		/* [in] */ REFIID riid,
		/* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject) {
		return S_OK;
	}

	virtual ULONG STDMETHODCALLTYPE AddRef(void) {
		return 1;
	}

	virtual ULONG STDMETHODCALLTYPE Release(void) {
		return 0;
	}

	virtual HRESULT STDMETHODCALLTYPE DragEnter(
		/* [unique][in] */ __RPC__in_opt IDataObject *pDataObj,
		/* [in] */ DWORD grfKeyState,
		/* [in] */ POINTL pt,
		/* [out][in] */ __RPC__inout DWORD *pdwEffect) {
		if (pDataObj == NULL)
			return E_INVALIDARG;

		if (m_pDropTargetHelper)
			m_pDropTargetHelper->DragEnter(g_hWnd, pDataObj, (LPPOINT)&pt, *pdwEffect);

		*pdwEffect = DROPEFFECT_COPY;
		return S_OK;
	}

	virtual HRESULT STDMETHODCALLTYPE DragOver(
		/* [in] */ DWORD grfKeyState,
		/* [in] */ POINTL pt,
		/* [out][in] */ __RPC__inout DWORD *pdwEffect) {
		if (m_pDropTargetHelper)
			m_pDropTargetHelper->DragOver((LPPOINT)&pt, *pdwEffect);

		*pdwEffect = DROPEFFECT_COPY;

		return S_OK;
	}

	virtual HRESULT STDMETHODCALLTYPE DragLeave(void) {
		if (m_pDropTargetHelper)
			m_pDropTargetHelper->DragLeave();

		return S_OK;
	}

	virtual HRESULT STDMETHODCALLTYPE Drop(
		/* [unique][in] */ __RPC__in_opt IDataObject *pDataObj,
		/* [in] */ DWORD grfKeyState,
		/* [in] */ POINTL pt,
		/* [out][in] */ __RPC__inout DWORD *pdwEffect) {
		if (pDataObj == NULL)
			return E_INVALIDARG;

		if (m_pDropTargetHelper)
			m_pDropTargetHelper->Drop(pDataObj, (LPPOINT)&pt, *pdwEffect);

		*pdwEffect = DROPEFFECT_NONE;

		return S_OK;
	}

private:
	struct IDropTargetHelper *m_pDropTargetHelper;  // 这个用来实现资源管理器那种拖放图标
};

使用::RegisterDragDrop(g_hWnd, g_MyDragFiles);注册

本文为@艺文笔记原创文章,转载请注明出处:https://www.xuwenyan.com/archives/522,非常感谢!
上一篇:  下一篇: