EverythingでもMigemoを使えるようになりました。 - Tablacus Explorer
EverythingアドオンでもMigemoを使えるようになりました。
前回のブログで紹介したようにMigemoアドオンをインストールしてから…
Everythingアドオンのオプションの「Regular Expression/Migemo」にチェックして下さい。
フィルターバーと同じ要領ですね。
前回書き忘れた 正規表現/Migemo インクリメンタルサーチ の機能
インクリメンタルサーチ中に「PGDN」キーで当てはまる次の項目に移動し、「PGUP」キーで当てはまる前の項目に移動します。
ローマ字で日本語検索 Migemo - Tablacus Explorer
Migemo: ローマ字のまま日本語をインクリメンタル検索 がTablacus Explorerでも使えるようになりました。
Tablacus Explorerでは JavaScript/Migemo のJavaScriptで実装したMigemoエンジンを使用しています。
インストール方法
まず、アドオンの「Migemo」をインストールします。
次にMigemoのオプションを開き、
「インストール」を押せば、上記のサイトからMigemoエンジンと辞書をダウンロードしてインストールできます。
テストの場所でローマ字入力をして、Regular Expressionの場所に日本語を含む正規表現が表示されればOKです。
Migemoでリスト上での検索を行う場合は、「正規表現/Migemo インクリメンタルサーチ」をインストールして下さい。
Migemoでフィルタリングしたい場合は、フィルターバー(Innerフィルターバー)のオプションに入り
「Regular Expression/Migemo」にチェックして下さい。
日本語のファイルを扱う際に便利ですね。
Migemoの原作者の高林様、JavaScript版の作者のふるかわ様、便利な機能の公開ありがとうございます。
フォルダ ツリーの自動更新の強化2 - INameSpaceTreeControl
前回のふたつ目はAs/Rの作者さんにこちらでOS安定稼動を考えると良くないとアドバイスを頂いたので、Tablacus Explorer 15.10.5から別の方法で実装してみました。
今回の実装は
SHChangeNotifyDeregisterでInterruptレベルの通知をキャッチして………
ツリーに項目を追加する場合は INameSpaceTreeControl::SetItemState(IShellItem *, NSTCIS_EXPANDED, NSTCIS_EXPANDED) で追加する。
ツリーから項目を削除等する場合は NamespaceTreeControl のウインドウに WM_USER + 1 でメッセージを横流しする。
追加の方はまだ良いとして、削除などの方はOSのバージョンアップ等で仕様が変わったらアウトなんですが、SHChangeNotifyで投げるのに比べたら他のアプリに影響しないのでマシかなと。
ついでに、みもふたもない言い方になりますが、そもそもDOSコマンドのmkdirとか「シェル通知を送らないことで高速化している」という側面もあるので、そっとしておいてあげた方が良いんじゃね?という考え方もあります。
エクスプローラーはmkdir等も対応してて自動的に追加されたりするので、「エクスプローラーはちゃんと動くんですが………」等と言われちゃいがちなのでなんとかしたいなと………
機会がありましたら、一緒にご飯したいですね。
フォルダ ツリーの自動更新の強化 - INameSpaceTreeControl
Windows Vista以降の場合、X-Finderのシステム互換やTablacus Explorerのフォルダ ツリーではINameSpaceTreeControlというVistaで追加されたツリーコントロールを使ってフォルダ ツリーを表示しています。
このツリーコントロールは自動でいろいろやってくれて便利なんですが、すでに展開しているフォルダで新規フォルダを作成しても追加されない場合があります。
例えば、コマンドラインの「mkdir フォルダ」としてフォルダを追加しても素のINameSpaceTreeControlではフォルダが追加されません。
いろいろ試してみたところ、自動的に更新させる方法を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も、フォルダの追加等で自動的に更新されるようになります。
本当は自分だけ更新する方法があれば他のソフトへの悪影響の心配もなく良いのですが…
独自関連付け・マウス・キーをメニューで選ぶ - Tablacus Explorer
Tablacus Explorer 15.8.16で独自関連付け等をメニューで選んで実行できるようになりました。
例えば、htmlファイルをダブルクリックすると「ブラウザ」と「メモ帳」のメニューが表示され、選んで実行するという感じです。
設定方法はツール(T)→オプション(O)→メニュー→既定
フィルタを「*.html」
タイプを「メニュー」
オプションを「開く」にします。
その下にメニューで表示させて実行する項目を作成します。
最後にタイプを「メニュー」にし、オプションを「閉じる」にするとそこまでがメニューになります。
同様にマウスで項目のない場所をホイールクリックした場合にメニューを表示するには
マウス欄がメニューに表示される名前になります。
最後にタイプを「メニュー」にし、オプションを「閉じる」にするとそこまでがメニューになります。
同様にShift+1でドライブCとドライブDのメニューを表示させて選べるようにするには
キー欄がメニューに表示される名前になります。
英数字の前に「&」を入れると、メニューを表示している時に前の文字を押すだけで実行できるようになります。
最後にタイプを「メニュー」にし、オプションを「閉じる」にするとそこまでがメニューになります。
ちょっとしたスクリプト - Tablacus Explorer
・フォルダ構成のみクリップボードにコピー
var CreateFolderOnly2 = function (path, dest, Items, nAdd)
{
api.SetWindowText(te.hwnd, path);
CreateFolder(dest);
if (nAdd == 0) {
Items.AddItem(dest);
}
var wfd = api.Memory("WIN32_FIND_DATA");
var hFind = api.FindFirstFile(path + "\\*", wfd);
var bFind = hFind != INVALID_HANDLE_VALUE;
while (bFind) {
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
var fn = wfd.cFileName;
if (fn != "." && fn != "..") {
CreateFolderOnly2(fso.BuildPath(path, fn), fso.BuildPath(dest, fn), Items, nAdd - 1);
}
}
bFind = api.FindNextFile(hFind, wfd);
}
api.FindClose(hFind);
};var CreateFolderOnly = function (Item, Items, temp, nAdd)
{
var path = api.GetDisplayNameOf(Item, SHGDN_FORPARSING);
if (/^[A-Z]:\\|^\\/i.test(path)) {
var fn = fso.GetFileName(path);
if (fn && fso.FolderExists(path)) {
var dest = fso.BuildPath(temp, fn);
CreateFolderOnly2(path, dest, Items, nAdd);
}
}
};var title = api.GetWindowText(te.hwnd);
var temp = fso.BuildPath(fso.GetSpecialFolder(2).Path, "tablacus");
if (!IsExists(temp)) {
CreateFolder(temp);
}
temp += "\\folder";
DeleteItem(temp);
CreateFolder(temp);var FV = GetFolderView(Ctrl, pt);
var Items = te.FolderItems();
var Selected = FV.SelectedItems();
if (Selected) {
for (var i = 0; i < Selected.Count; i++) {
CreateFolderOnly(Selected.Item(i), Items, temp, 0);
}
}
if (Items.Count == 0) {
CreateFolderOnly(FV, Items, temp, 1);
}
api.OleSetClipboard(Items);
api.SetWindowText(te.hwnd, title);
長いしフォルダがたくさんあると時間が掛るので、WSHにするとか、アドオンにしてマルチプロセスにする方が良さそうな感じですが…
・1階層上に送る
var FV = GetFolderView(Ctrl, pt);
var Selected = FV.SelectedItems();
if (Selected) {
var oDest = sha.NameSpace(fso.GetParentFolderName(api.GetDisplayNameOf(FV, SHGDN_FORPARSING)));
if (oDest) {
oDest.MoveHere(Selected, FOF_ALLOWUNDO);
}
}
・1階層下から吸い出す
var FV = GetFolderView(Ctrl, pt);
var path = OpenDialog(fso.GetParentFolderName(api.GetDisplayNameOf(FV, SHGDN_FORPARSING)));
if (path) {
FV.Folder.MoveHere(path, FOF_ALLOWUNDO);
}