ごみ箱の ITEMIDLIST を取得
# include <ShlObj.h>
LPITEMIDLIST pidlBitBucket;
SHGetSpecialFolderLocation(nullptr, CSIDL_BITBUCKET, &pidlBitBucket);
SHGetSpecialFolderLocation function (shlobj_core.h) - Win32 apps | Microsoft Docs
シェルの変更通知に登録
# define WM_SHCHANGENOTIFY (WM_APP + 1)
SHChangeNotifyEntry changeNotifyEntry = { 0 };
changeNotifyEntry.fRecursive = FALSE;
changeNotifyEntry.pidl = pidlBitBucket;
ULONG ulID = SHChangeNotifyRegister(
hWnd,
(SHCNRF_ShellLevel | SHCNRF_NewDelivery),
SHCNE_UPDATEIMAGE,
WM_SHCHANGENOTIFY,
1,
&changeNotifyEntry);
SHChangeNotifyRegister function (shlobj_core.h) - Win32 apps | Microsoft Docs
SHChangeNotifyRegister
の第3引数(fEvents
)にSHCNE_UPDATEIMAGE
を渡すと、アイコンの変更が通知されます。
Window メッセージ を処理
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_SHCHANGENOTIFY:
LPITEMIDLIST* ppidl;
LONG lEvent;
HANDLE hLock = SHChangeNotification_Lock((HANDLE)wParam, (DWORD)lParam, &ppidl, &lEvent);
if (!hLock) {
break;
}
if (lEvent == SHCNE_UPDATEIMAGE) {
AnalyzeIcon();
}
SHChangeNotification_Unlock(hLock);
break;
...
}
return 0;
}
SHChangeNotification_Lock function (shlobj_core.h) - Win32 apps | Microsoft Docs
SHChangeNotification_Unlock function (shlobj_core.h) - Win32 apps | Microsoft Docs
ごみ箱のアイコンを取得
# include <shellapi.h>
void AnalyzeIcon()
{
SHFILEINFO shFileInfo = { 0 };
if (SUCCEEDED(SHGetFileInfo(
(LPCTSTR)pidlBitBucket,
-1,
&shFileInfo,
sizeof(shFileInfo),
(SHGFI_PIDL | SHGFI_ICON)))) {
HICON hIcon = shFileInfo.hIcon;
// アイコンを使う処理
...
if (hIcon) {
DestroyIcon(hIcon);
}
}
}
SHGetFileInfoA function (shellapi.h) - Win32 apps | Microsoft Docs
SHGetFileInfo
の第1引数(pszPath
)にITEMIDLIST
のポインタ、第5引数にSHGFI_PIDL
を渡すのがポイント。
取得したアイコンのハンドルは破棄が必要。
サンプル
# include <ShlObj.h>
# include <shellapi.h>
# define WM_SHCHANGENOTIFY (WM_APP + 1)
LPITEMIDLIST g_pidlBitBucket = nullptr;
ULONG g_ulID = 0;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message) {
case WM_CREATE:
CoInitialize(nullptr);
{
SHChangeNotifyEntry changeNotifyEntry = { 0 };
changeNotifyEntry.fRecursive = FALSE;
changeNotifyEntry.pidl = g_pidlBitBucket;
g_ulID = SHChangeNotifyRegister(
hWnd,
(SHCNRF_ShellLevel | SHCNRF_NewDelivery),
SHCNE_UPDATEIMAGE,
WM_SHCHANGENOTIFY,
1,
&changeNotifyEntry);
if (!g_ulID) {
break;
}
}
break;
case WM_DESTROY:
SHChangeNotifyDeregister(g_ulID);
if (g_pidlBitBucket) {
CoTaskMemFree(g_pidlBitBucket);
}
CoUninitialize();
PostQuitMessage(0);
break;
case WM_SHCHANGENOTIFY:
{
LPITEMIDLIST* ppidl;
LONG lEvent;
HANDLE hLock = SHChangeNotification_Lock((HANDLE)wParam, (DWORD)lParam, &ppidl, &lEvent);
if (!hLock) {
break;
}
if (lEvent == SHCNE_UPDATEIMAGE) {
AnalyzeIcon();
}
SHChangeNotification_Unlock(hLock);
}
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
余談
.NETではshell32.dllを参照に追加するだけで、こんなコードが書けます。
using Shell32;
using System;
static class Program
{
static void Main()
{
Shell shell = new Shell();
// ShellSpecialFolderConstants::ssfBITBUCKET: 10
Folder bitBucketFolder = shell.NameSpace(10);
foreach (FolderItem2 item in bitBucketFolder.Items())
{
Console.WriteLine(item.Name);
}
}
}
Windows Shell - Win32 apps | Microsoft Docs
追記
IShellFolder
は使用しないので、説明を削除しました。
(ごみ箱の中身を検証する時に使用します)