Skip to content

Instantly share code, notes, and snippets.

@udaken
Last active July 22, 2016 14:06
Show Gist options
  • Save udaken/040e0a5819dbc6406a2621e32d905bda to your computer and use it in GitHub Desktop.
Save udaken/040e0a5819dbc6406a2621e32d905bda to your computer and use it in GitHub Desktop.
explorerのアイテムの並び順で、アイテムを取得するサンプル
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define WIN32_LEAN_AND_MEAN
#define STRICT
#define STRICT_CONST
#define STRICT_TYPED_ITEMIDS
#define NOMINMAX
#include <Windows.h>
#include <Shlobj.h>
#include <shlwapi.h>
#include <strsafe.h>
#include <Unknwn.h>
#include <comdef.h>
#include <Propkey.h>
_COM_SMARTPTR_TYPEDEF(IFolderView, __uuidof(IFolderView));
_COM_SMARTPTR_TYPEDEF(IFolderView2, __uuidof(IFolderView2));
_COM_SMARTPTR_TYPEDEF(IShellItemArray, __uuidof(IShellItemArray));
_COM_SMARTPTR_TYPEDEF(IShellItem, __uuidof(IShellItem));
#include <assert.h>
#include <memory>
#include <vector>
#include <string>
#include <tchar.h>
#pragma comment (lib, "shlwapi.lib")
#pragma comment( lib, "Rpcrt4.lib" ) // RpcStringFree
//#define CPPLINQ_INLINEMETHOD __forceinline
#include "cpplinq.hpp"
inline std::wstring GuidToString(const GUID *pGuid)
{
std::wstring wrk;
RPC_WSTR waString = nullptr;
if (RPC_S_OK == ::UuidToString(pGuid, &waString))
{
wrk = reinterpret_cast<const WCHAR*>(waString);
::RpcStringFree(&waString);
}
return std::move(wrk);
}
class CComHeapDeleter
{
public:
void operator()(void* p)
{
::CoTaskMemFree(p);
}
};
//typedef std::unique_ptr<WCHAR[], CComHeapDeleter> ComHeapString;
class CCoInitialize {
public:
CCoInitialize() : m_hr(::CoInitialize(NULL))
{
if (FAILED(m_hr)) _com_raise_error(m_hr);
}
~CCoInitialize() { if (SUCCEEDED(m_hr)) ::CoUninitialize(); }
operator HRESULT() const { return m_hr; }
HRESULT m_hr;
};
__inline void check(HRESULT hr)
{
if (FAILED(hr))
{
_com_issue_error(hr);
}
}
inline VARIANT CVar(int iVal)
{
VARIANT v;
v.vt = VT_I4;
v.lVal = iVal;
return v;
}
LPCWSTR GetPropertyName(const PROPERTYKEY &propKey)
{
std::make_pair(PKEY_ItemName, L"<ItemName>");
if (propKey == PKEY_ItemName)
{
return L"<ItemName>";
}
else if (propKey == PKEY_ItemNameDisplay)
{
return L"<ItemNameDisplay>";
}
else if (propKey == PKEY_DateModified)
{
return L"<DateModified>";
}
else if (propKey == PKEY_Size)
{
return L"<Size>";
}
return nullptr;
}
LPCWSTR GetSortDierctionName(const SORTDIRECTION &direction)
{
if (direction == SORT_DESCENDING)
return L"<DSC>";
else if (direction == SORT_DESCENDING)
return L"<ASC>";
return nullptr;
}
void DebugPrint(const TCHAR *fmt, ...)
{
TCHAR buf[512];
va_list args;
va_start(args, fmt);
size_t size = _vsnwprintf_s(buf, _countof(buf), fmt, args);
assert(size != -1);
::OutputDebugString(buf);
}
class CStrRet : public STRRET
{
public:
CStrRet() : STRRET() {}
~CStrRet()
{
if (uType == STRRET_WSTR)
{
::CoTaskMemFree(pOleStr);
pOleStr = nullptr;
}
}
template <UINT cchBuf>
void toBuf(TCHAR(&buf)[cchBuf], PCUITEMID_CHILD pidl = nullptr)
{
toBuf(buf, cchBuf, pidl);
}
void toBuf(LPTSTR buf, UINT cchBuf, PCUITEMID_CHILD pidl = nullptr)
{
check(::StrRetToBuf(this, pidl, buf, cchBuf));
}
};
int APIENTRY _tWinMain(HINSTANCE,
HINSTANCE,
LPTSTR /*lpCmdLine*/,
int /*nCmdShow*/)
{
CCoInitialize init;
IShellWindowsPtr pShellWindows;
check(::CoCreateInstance(CLSID_ShellWindows, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pShellWindows)));
long count;
check(pShellWindows->get_Count(&count));
for (int i = 0; i < count; i++)
{
IDispatchPtr pDispatch;
check(pShellWindows->Item(CVar(i), &pDispatch));
{
IShellBrowserPtr pShellBrowser;
check(IUnknown_QueryService(pDispatch, SID_STopLevelBrowser, IID_PPV_ARGS(&pShellBrowser)));
{
IShellViewPtr pShellView;
check(pShellBrowser->QueryActiveShellView(&pShellView));
IFolderView2Ptr pFolderView = pShellView;
// 開いているフォルダの取得
IShellFolderPtr pShellFolder;
HRESULT hr = pFolderView->GetFolder(IID_PPV_ARGS(&pShellFolder));
if (SUCCEEDED(hr))
{
PITEMID_CHILD pidlChild = nullptr;
CStrRet strret;
check(pShellFolder->GetDisplayNameOf(pidlChild, SHGDN_FORPARSING, &strret));
TCHAR szFullName[256];
strret.toBuf(szFullName, pidlChild);
//check(StrRetToBuf(&strret, pidlChild, szFullName, _countof(szFullName)));
DebugPrint(L"%s\n", szFullName);
}
// 並び順を取得する
{
int cColumns;
check(pFolderView->GetSortColumnCount(&cColumns));
std::vector<SORTCOLUMN> sortColumns(cColumns);
check(pFolderView->GetSortColumns(&sortColumns.front(), cColumns));
for (int i = 0; i < cColumns; i++)
{
const SORTCOLUMN& sortColumn = sortColumns.at(i);
auto guid = GuidToString(&sortColumn.propkey.fmtid);
DebugPrint(L"\t%d: formatid=%s(%s) %s\n", i, guid.c_str(), GetPropertyName(sortColumn.propkey), GetSortDierctionName(sortColumn.direction));
}
}
// explorerのアイテムの並び順で、アイテムを取得
{
IShellItemArrayPtr pShellItemArray;
check(pFolderView->Items(SVGIO_ALLVIEW | SVGIO_FLAG_VIEWORDER, IID_PPV_ARGS(&pShellItemArray)));
DWORD shellItemCount;
check(pShellItemArray->GetCount(&shellItemCount));
for (DWORD dwIdx = 0; dwIdx < shellItemCount; dwIdx++)
{
IShellItemPtr pShellItem;
check(pShellItemArray->GetItemAt(dwIdx, &pShellItem));
{
LPWSTR pszName = NULL;
check(pShellItem->GetDisplayName(SIGDN_FILESYSPATH, &pszName));
DebugPrint(L"%s\n", pszName);
::CoTaskMemFree(pszName);
}
}
}
}
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment