C++&STLで特殊フォルダの動作を取得するサンプルコード
Windows環境、C++でSTLを使用して特殊フォルダの動作一覧を取得するサンプルコードです。サンプルコードではごみ箱の動作を取得します。開発環境はWindows10、Microsoft Visual Studio Community 2019 (Version 16.0.2)、MSVC v142、Windows 10 SDK (10.0.17763.0)です。Windows デスクトップ ウィザードで空のアプリケーション(デスクトップ アプリケーション)を作成して貼り付けることで実行できます。
実行するとverbsに次の文字列が設定されます。 "link"、"properties"、"PinToStartScreen"、"empty"、"open"
#pragma comment(lib, "shlwapi.lib") #define STRICT #include <Windows.h> #include <ShlObj.h> #include <Shlwapi.h> #include <vector> #include <set> #include <string> HRESULT GetShellFolderContextMenuVerbs(std::vector<std::wstring>& verbs, int csidl, UINT uQueryContextMenuFlags); std::vector<WORD> GetMenuAllItemIDs(HMENU hmenu); int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) { HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); if (SUCCEEDED(hr)) { std::vector<std::wstring> verbs; // TODO:CSIDL_*で取得するフォルダを指定します。 hr = GetShellFolderContextMenuVerbs( verbs, CSIDL_BITBUCKET, 0/*CMF_VERBSONLY*/); if (SUCCEEDED(hr)) { // TODO:ここで特殊フォルダの動作を処理します。 } CoUninitialize(); } return 0; } HRESULT GetShellFolderContextMenuVerbs(std::vector<std::wstring>& verbs, int csidl, UINT uQueryContextMenuFlags) { IShellFolder* pDesktop = nullptr; HRESULT hr = SHGetDesktopFolder(&pDesktop); if (SUCCEEDED(hr)) { LPITEMIDLIST pidl = nullptr; hr = SHGetFolderLocation(nullptr, CSIDL_BITBUCKET, nullptr, 0, &pidl); if (SUCCEEDED(hr)) { IContextMenu* pContextMenu = nullptr; LPCITEMIDLIST ids[] = {pidl}; hr = pDesktop->GetUIObjectOf(nullptr, 1, ids, IID_IContextMenu, nullptr, (void**)&pContextMenu); if (SUCCEEDED(hr)) { HMENU hmenu = CreateMenu(); if (hmenu != nullptr) { hr = pContextMenu->QueryContextMenu(hmenu, 0, 0, 0, uQueryContextMenuFlags); if (SUCCEEDED(hr)) { for (auto id : GetMenuAllItemIDs(hmenu)) { WCHAR name[256]; // TODO:文字数の可変長対応 hr = pContextMenu->GetCommandString(id, GCS_VERBW, nullptr, (char*)name, 256); if (SUCCEEDED(hr)) { verbs.push_back(name); } } } DestroyMenu(hmenu); } pContextMenu->Release(); } ILFree(pidl); } pDesktop->Release(); } return hr; } void GetMenuAllItemIDsWorker(HMENU hmenu, std::vector<WORD>& ids) { auto c = GetMenuItemCount(hmenu); if (c == 0) { return; } MENUITEMINFO mii = {sizeof(MENUITEMINFO), MIIM_ID | MIIM_SUBMENU}; for (auto i = 0; i < c; i++) { if (GetMenuItemInfo(hmenu, i, TRUE, &mii)) { if (mii.hSubMenu == nullptr) { ids.push_back(mii.wID); } else { GetMenuAllItemIDsWorker(mii.hSubMenu, ids); } } } } // メニューに存在するすべてのIDを取得します。 std::vector<WORD> GetMenuAllItemIDs(HMENU hmenu) { std::vector<WORD> ids; GetMenuAllItemIDsWorker(hmenu, ids); // 重複要素の削除 std::set<WORD> s(ids.begin(), ids.end()); return std::vector<WORD>(s.begin(), s.end()); }