「お気に入りの追加」「お気に入りの整理」ダイアログを表示させる (2)

結局、Shell.UIHelperをやめて、Windowsの「DoAddToFavDlg」、「DoOrganizeFavDlg」で実装しました。
理由は、Windows標準の「お気に入りフォルダ」以外をルートにすることで、IEのお気に入り管理機能をHoven側の更新に使って楽をしようと思ったからです。好きなフォルダを「お気に入りフォルダ」として扱えるようになります。
今のところは、IEのお気に入りは基本的にはリードオンリーで、新月内もウェブも、お気に入りの更新はHoven側で行うことにしました。これは、管理情報を全てHovenフォルダ配下におけるようにするためで、IE側にお気に入りを入れていたから別のPCへ持っていった際に見れない!ことがないようにです。ただ、持ち歩くことなんてないし、IEのお気に入りを使いたいという方もいると思うので、お気に入り管理するフォルダパスは変更できるようにしようと思います。このフォルダパスを、IEのお気に入りと同じパスにすると、IEのお気に入りフォルダが更新できます。よって、保存形式はIEにあわせました。

D言語は、特定のプラットホームでやるぶんには、OSのAPIが直接扱えるという点で、Javaよりも手数が多いと思いました。

  • 追記

検索でもなかなか方法が見つからなくて徹夜してしまったのと、同じ質問もちらほら見かけたのでソースコード。DからはDoAddToFavoriteあたりの関数の呼び出し規約分からなくて*1変なふうになっていたので、Cで関数を作って、Dからextern(C)して使うようにしました。dmcで確認しています。
アルゴリズムは考えれば分かりますが、APIの名前や機能はひたすら探すしかないので大変です。

#include <windows.h>
#include <ShlObj.h>
#include <ObjIdl.h>

/**
 * 「お気に入りに追加」「お気に入りの整理」ダイアログ表示関数 
 *
 */

typedef BOOL (CALLBACK* LPFNORGFAV)(HWND, CHAR*);
typedef BOOL (CALLBACK* LPFNADDFAV)(HWND, CHAR*, UINT, CHAR*, UINT, LPITEMIDLIST);
typedef LPITEMIDLIST (CALLBACK* LPFNCRPATH)(LPCTSTR);

/**
 * お気に入りの整理
 * 
 */
BOOL doOrganizeFavoriteFolderDialog(
    HWND hWindow,        //< Window Handle, NULL以外の場合Modalになる
    IN CHAR* szPath)     //< お気に入りフォルダのルートパス
{
									
    BOOL        bResult             = FALSE;
    LPFNORGFAV  DoOrganizeFavDlg    = NULL;
    HMODULE     hModuleShdocvw      = (HMODULE)LoadLibrary("shdocvw.dll");
    
    if(!hModuleShdocvw) {
        return FALSE;
    }
    
    DoOrganizeFavDlg = (LPFNORGFAV)GetProcAddress(hModuleShdocvw, "DoOrganizeFavDlg");
    if (DoOrganizeFavDlg) {
        bResult = DoOrganizeFavDlg(hWindow, szPath);
    }
    
    FreeLibrary(hModuleShdocvw);
}

/**
 * お気に入りに追加
 * 
 * remark: 厳密には「選択」.urlファイルの作成は呼び出し元で行う
 */
							
BOOL doAddToFavoriteFolderDialog(
    HWND hWindow,           //< Window Handle, NULL以外の場合Modalになる
    IN OUT CHAR *szPath,    //< IN: お気に入りフォルダのルートパス, OUT: 選択されたパス
    UINT nPathLength,       //< szPathのOUT用に使えるバッファサイズ
    IN OUT CHAR *szTitle,   //< IN: タイトル初期値, OUT: 選択されたタイトル
    UINT nTitleLenght)      //< szTitleのOUT用に使えるバッファサイズ
{
										
    BOOL            bResult             = FALSE;
    LPFNADDFAV      DoAddToFavDlg       = NULL;
    LPFNCRPATH      ILCreateFromPath    = NULL;
    HMODULE         hModuleShdocvw      = (HMODULE)LoadLibrary("shdocvw.dll");
    HMODULE         hModuleShell32      = (HMODULE)LoadLibrary("shell32.dll");
    LPITEMIDLIST    pItemIdList;
    IMalloc         *pAllocator;
    
    if(!hModuleShdocvw) {
        return FALSE;
    }
    if (!hModuleShell32) {
        FreeLibrary(hModuleShdocvw);
        return FALSE;
    }
        
    SHGetMalloc(&pAllocator);
    
    ILCreateFromPath = (LPFNCRPATH)GetProcAddress(hModuleShell32, "ILCreateFromPathA");
    if (!ILCreateFromPath) {
        FreeLibrary(hModuleShdocvw);
        FreeLibrary(hModuleShell32);
        pAllocator->lpVtbl->Release(pAllocator);
        return FALSE;
    }
    pItemIdList = ILCreateFromPath(szPath);
    if (!pItemIdList) {
        FreeLibrary(hModuleShdocvw);
        FreeLibrary(hModuleShell32);
        pAllocator->lpVtbl->Release(pAllocator);
        return FALSE;
    }
    
    DoAddToFavDlg = (LPFNADDFAV)GetProcAddress(hModuleShdocvw, "DoAddToFavDlg");
    if (DoAddToFavDlg) {
        bResult = DoAddToFavDlg(hWindow, szPath, nPathLength,
                                szTitle, nTitleLenght, pItemIdList);
    }
    
    pAllocator->lpVtbl->Free(pAllocator, pItemIdList);
    pAllocator->lpVtbl->Release(pAllocator);
    
    FreeLibrary(hModuleShdocvw);
    FreeLibrary(hModuleShell32);
    
    return bResult;
}

*1:これなに?extern(C)でもextern(Windows)でもダメでした