ドロップされたOLEデータオブジェクトに含まれるShellItem(ファイル、フォルダ、特殊フォルダ等)を列挙するサンプルコードです。
#define STRICT #include <Windows.h> #include <ShlObj.h> #include <ShObjIdl.h> #include <vector> #include <string> #include <sstream> #include <iomanip> const TCHAR MY_WINDOW_CLASS_NAME[] = TEXT("Project1"); const TCHAR MY_WINDOW_WINDOW_NAME[] = TEXT("Project1"); LRESULT CALLBACK MyWndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam); int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int nCmdShow) { if (FAILED(OleInitialize(nullptr))) return -1; WNDCLASSEX wce; wce.cbSize = sizeof(wce); wce.style = 0; wce.lpfnWndProc = MyWndProc; wce.cbClsExtra = 0; wce.cbWndExtra = 0; wce.hInstance = nullptr; wce.hIcon = LoadIcon(nullptr, IDI_APPLICATION); wce.hCursor = LoadCursor(nullptr, IDC_ARROW); wce.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); wce.lpszMenuName = nullptr; wce.lpszClassName = MY_WINDOW_CLASS_NAME; wce.hIconSm = LoadIcon(nullptr, IDI_APPLICATION); if (!RegisterClassEx(&wce)) return 0; auto hWnd = CreateWindowEx( WS_EX_OVERLAPPEDWINDOW, MY_WINDOW_CLASS_NAME, MY_WINDOW_WINDOW_NAME, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, nullptr, nullptr); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); MSG msg; while (GetMessage(&msg, nullptr, 0, 0) > 0) { TranslateMessage(&msg); DispatchMessage(&msg); } OleUninitialize(); return msg.wParam; } template<size_t INIT = 256, size_t EXPANDING = 256> std::wstring GetClipboardFormatNameW(CLIPFORMAT cf) { std::vector<WCHAR> buffer(INIT); for (;;) { auto copied = GetClipboardFormatNameW(cf, buffer.data(), buffer.size()); if (copied != buffer.size() - 1) { return std::wstring(buffer.data(), copied); } buffer.resize(buffer.size() + EXPANDING); } } std::wstring GetShellItemDisplayName(IShellItem *pShellItem, SIGDN sigdnName) { LPWSTR pszName; if (SUCCEEDED(pShellItem->GetDisplayName(sigdnName, &pszName))) { std::wstring s(pszName); CoTaskMemFree(pszName); return std::move(s); } return std::wstring(); } // https://docs.microsoft.com/ja-jp/windows/desktop/api/oleidl/nn-oleidl-idroptarget class CMyDropTarget : public IDropTarget { private: ULONG m_ref; HWND m_hwndEdit; CMyDropTarget() {} public: CMyDropTarget(HWND hwndEdit) { m_ref = 1; m_hwndEdit = hwndEdit; } HRESULT QueryInterface( REFIID riid, void **ppvObject) { if (IsEqualIID(riid, __uuidof(IUnknown))) { *ppvObject = static_cast<IUnknown*>(this); } else if (IsEqualIID(riid, __uuidof(IDropTarget))) { *ppvObject = static_cast<IDropTarget*>(this); } else { return E_NOINTERFACE; } AddRef(); return S_OK; } ULONG AddRef() { return InterlockedIncrement(&m_ref); } ULONG Release(void) { if (InterlockedDecrement(&m_ref) == 0) { delete this; return 0; } return m_ref; } HRESULT STDMETHODCALLTYPE DragEnter( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { *pdwEffect = DROPEFFECT_LINK; return S_OK; } HRESULT DragOver( DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { return S_OK; } HRESULT DragLeave() { return S_OK; } HRESULT Drop( IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) { std::vector<CLIPFORMAT> cfs; FORMATETC fmtetc = { RegisterClipboardFormat(CFSTR_SHELLIDLIST) }; if (!pDataObj->QueryGetData(&fmtetc)) return S_OK; IShellItemArray *pShellItems = nullptr; if (SUCCEEDED(SHCreateShellItemArrayFromDataObject(pDataObj, IID_IShellItemArray, (void**)&pShellItems))) { DWORD c; if (SUCCEEDED(pShellItems->GetCount(&c))) { std::wstringstream ss; // TODO:ここで表示する形式を選択してください。 ss << "SIGDN_NORMALDISPLAY" << TEXT(", ") << "SIGDN_PARENTRELATIVEPARSING" << TEXT(", ") << "SIGDN_DESKTOPABSOLUTEPARSING" << TEXT(", ") << "SIGDN_PARENTRELATIVEEDITING" << TEXT(", ") << "SIGDN_DESKTOPABSOLUTEEDITING" << TEXT(", ") << "SIGDN_FILESYSPATH" << TEXT(", ") << "SIGDN_URL" << TEXT(", ") << "SIGDN_PARENTRELATIVEFORADDRESSBAR" << TEXT(", ") << "SIGDN_PARENTRELATIVE" << TEXT(", ") << "SIGDN_PARENTRELATIVEFORUI" << TEXT("\r\n"); for (auto i = 0; i < c; i++) { IShellItem *pShellItem = nullptr; if (SUCCEEDED(pShellItems->GetItemAt(i, &pShellItem))) { // TODO:ここで表示する形式を選択してください。 ss << GetShellItemDisplayName(pShellItem, SIGDN::SIGDN_NORMALDISPLAY) << TEXT(", ") << GetShellItemDisplayName(pShellItem, SIGDN::SIGDN_PARENTRELATIVEPARSING) << TEXT(", ") << GetShellItemDisplayName(pShellItem, SIGDN::SIGDN_DESKTOPABSOLUTEPARSING) << TEXT(", ") << GetShellItemDisplayName(pShellItem, SIGDN::SIGDN_PARENTRELATIVEEDITING) << TEXT(", ") << GetShellItemDisplayName(pShellItem, SIGDN::SIGDN_DESKTOPABSOLUTEEDITING) << TEXT(", ") << GetShellItemDisplayName(pShellItem, SIGDN::SIGDN_FILESYSPATH) << TEXT(", ") << GetShellItemDisplayName(pShellItem, SIGDN::SIGDN_URL) << TEXT(", ") << GetShellItemDisplayName(pShellItem, SIGDN::SIGDN_PARENTRELATIVEFORADDRESSBAR) << TEXT(", ") << GetShellItemDisplayName(pShellItem, SIGDN::SIGDN_PARENTRELATIVE) << TEXT(", ") << GetShellItemDisplayName(pShellItem, SIGDN::SIGDN_PARENTRELATIVEFORUI) << TEXT(", ") << TEXT("\r\n"); } pShellItem->Release(); } SetWindowText(m_hwndEdit, ss.str().c_str()); } pShellItems->Release(); } *pdwEffect = DROPEFFECT_LINK; return S_OK; } HWND GetEditWindowHandle() const { return m_hwndEdit; } }; CMyDropTarget *pDropTarget = nullptr; LRESULT CALLBACK MyWndProc(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam) { switch (uiMsg) { case WM_CREATE: { // データ表示用のテキストボックス作成 auto hwndEdit1 = CreateWindowEx( WS_EX_CLIENTEDGE, TEXT("edit"), TEXT("ファイルやURLをドロップしてください。"), WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | ES_MULTILINE, 0, 0, 0, 0, hWnd, nullptr, nullptr, nullptr); SendMessage(hwndEdit1, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0)); // ドロップ対象として登録 pDropTarget = new CMyDropTarget(hwndEdit1); RegisterDragDrop(hWnd, pDropTarget); pDropTarget->Release(); return 0; } case WM_DESTROY: PostQuitMessage(0); return 0; case WM_QUIT: RevokeDragDrop(hWnd); return 0; case WM_SIZE: MoveWindow( pDropTarget->GetEditWindowHandle(), 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE); return 0; } return DefWindowProc(hWnd, uiMsg, wParam, lParam); }
出力例
デスクトップのPCをドロップした場合
SIGDN_NORMALDISPLAY, SIGDN_PARENTRELATIVEPARSING, SIGDN_DESKTOPABSOLUTEPARSING, SIGDN_PARENTRELATIVEEDITING, SIGDN_DESKTOPABSOLUTEEDITING, SIGDN_FILESYSPATH, SIGDN_URL, SIGDN_PARENTRELATIVEFORADDRESSBAR, SIGDN_PARENTRELATIVE, SIGDN_PARENTRELATIVEFORUI コントロール パネル, ::{5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}, ::{5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}, コントロール パネル, コントロール パネル, , , コントロール パネル, コントロール パネル, コントロール パネル, PC, ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}, ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}, PC, PC, , , PC, PC, PC,