タブファイラー開発ブログ

Tablacus ExplorerやX-Finderの作者のブログ

フォルダ ツリーの自動更新の強化 - INameSpaceTreeControl

Windows Vista以降の場合、X-Finderのシステム互換やTablacus Explorerのフォルダ ツリーではINameSpaceTreeControlというVistaで追加されたツリーコントロールを使ってフォルダ ツリーを表示しています。

このツリーコントロールは自動でいろいろやってくれて便利なんですが、すでに展開しているフォルダで新規フォルダを作成しても追加されない場合があります。
例えば、コマンドラインの「mkdir フォルダ」としてフォルダを追加しても素のINameSpaceTreeControlではフォルダが追加されません。

f:id:tablacus:20150906230158p:plain

いろいろ試してみたところ、自動的に更新させる方法を2つ発見しました。

1.Windows 7で追加されたインターフェイスのINameSpaceTreeControl2のSetControlStyle2でNSTCS2_INTERRUPTNOTIFICATIONSを指定

INameSpaceTreeControl2 *pNSTC2;
if SUCCEEDED(m_pNameSpaceTreeControl->QueryInterface(IID_PPV_ARGS(&pNSTC2))) {
 pNSTC2->SetControlStyle2(NSTCS2_INTERRUPTNOTIFICATIONS, NSTCS2_INTERRUPTNOTIFICATIONS);
 pNSTC2->Release();

これだけで、Windows 7以降ではフォルダが追加されるようになりました。

ただ、Tablacus Explorerではこの方法は使わずコメントアウトしています。

何故かと言うと、私の環境では更新通知されすぎるのか、ちょっとしたファイル変更の度に更新してツリーが重くなってしまったからです。

TablacusExplorer/TE.cpp at master · tablacus/TablacusExplorer · GitHub


2.SHChangeNotifyDeregisterで通知をキャッチしてSHChangeNotifyで投げる

INameSpaceTreeControlではInterruptレベルの通知はキャッチしないが、Shellレベルの通知はキャッチしているようなので、SHChangeNotifyDeregisterでInterruptレベルの通知をキャッチしてSHChangeNotifyでShellレベルで投げる方法を考えました。

※SHChangeNotifyRegister定義でフォルダ関連のInterruptレベルの通知をキャッチ

Addons.TreeView.uRegisterId = api.SHChangeNotifyRegister(te.hwnd, SHCNRF_InterruptLevel | SHCNRF_NewDelivery, SHCNE_MKDIR | SHCNE_DRIVEREMOVED | SHCNE_MEDIAREMOVED | SHCNE_NETUNSHARE | SHCNE_RENAMEFOLDER | SHCNE_RMDIR | SHCNE_SERVERDISCONNECT | SHCNE_UPDATEDIR, Addons.TreeView.WM, ssfDESKTOP, true);

※通知をキャッチしてSHChangeNotifyでそのまま投げる

AddEvent("AppMessage", function (Ctrl, hwnd, msg, wParam, lParam)
{
 if (msg == Addons.TreeView.WM) {
  var pidls = {};
  var hLock = api.SHChangeNotification_Lock(wParam, lParam, pidls);
  if (hLock) {
   api.SHChangeNotify(pidls.lEvent, SHCNF_IDLIST, pidls[0], pidls[1]);
   api.SHChangeNotification_Unlock(hLock);
  }
  return S_OK;
 }
});

上記をTreeviewアドオンのscript.jsで行っています。

TablacusExplorerAddons/script.js at master · tablacus/TablacusExplorerAddons · GitHub

なおこの方法も副作用があります。SHChangeNotifyで投げているのでTablacus Explorerだけでなく他のアプリにも影響してしまいます。

例えば、Tablacus Explorerとツリーアドオン使用時はINameSpaceTreeControlを使っていると思われるAs/Rも、フォルダの追加等で自動的に更新されるようになります。

本当は自分だけ更新する方法があれば他のソフトへの悪影響の心配もなく良いのですが…