« プログラム試行錯誤 | トップページ | コンプレックス »

2006-02-21

プログラム試行錯誤(続)

その後判明したフォルダ選択コモンダイアログボックスを表示する方法のまとめ。

// Susie Plug-in設定関数
VOID MySusie(HWND hWnd)
{
    BROWSEINFO bi;
    LPITEMIDLIST lpidRoot = NULL, lpidBrowse = NULL;
    TCHAR szCurPath[MAX_FILE], szPath[MAX_FILE];
    HRESULT hr;
    HINSTANCE hSusie;
    PGETPLUGININFO fpGetPluginInfo;

    // 初期フォルダ設定
    if(lstrlen(szSusie) == 0) {
        hr = SHGetFolderPath(hWnd, CSIDL_PROGRAM_FILES, NULL,
                SHGFP_TYPE_CURRENT, szCurPath);
        if(hr == S_FALSE || hr == E_FAIL || hr == E_INVALIDARG) {
            if(GetCurrentDirectory(sizeof(szCurPath), szCurPath) == 0) {
                MyError(hEdit, TEXT("GetCurrentDirectory"), GetLastError());
                return;
            }
        } else if(hr & 0x80000000) {
            Edit_AddMessage(hEdit, TEXT("error:SHGetFolderPath"), TRUE, TRUE);
            return;
        }
    } else
        lstrcpy(szCurPath, szSusie);

    // COM初期化
    hr = CoInitialize(NULL);
    if(hr != S_OK && hr != S_FALSE)
        return;

    if(SHGetSpecialFolderLocation(hWnd, CSIDL_DRIVES, &lpidRoot) != S_OK)
        goto MySusieEnd;

    // BROWSEINFO構造体設定
    ZeroMemory(&bi, sizeof(BROWSEINFO));
    bi.hwndOwner = hWnd;
    bi.pidlRoot = lpidRoot;
    bi.pszDisplayName = szPath;
    bi.lpszTitle = "Susie Plug-in 格納フォルダを選択して下さい";
    bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_DONTGOBELOWDOMAIN |
                 BIF_RETURNFSANCESTORS | BIF_VALIDATE | BIF_USENEWUI |
                 BIF_NONEWFOLDERBUTTON;
    bi.lpfn = BrowseCallbackProc;
    bi.lParam = (LPARAM)szCurPath;

    // フォルダ選択ダイアログ表示
    if((lpidBrowse = SHBrowseForFolder(&bi)) == NULL)
        goto MySusieEnd;

    // ITEMIDLISTからパス取得
    if(SHGetPathFromIDList(lpidBrowse, szPath) == TRUE) {
        lstrcpy(szSusie, szPath);

        // Susie Plug-inロード
        wsprintf(szPath, TEXT("%s\\"PATH_SPI), szSusie);
        if((hSusie = LoadLibrary(szPath)) == NULL) {
            MyError(hEdit, TEXT("LoadLibrary"), GetLastError());
            ZeroMemory(szSusie, sizeof(szSusie));
            goto MySusieEnd;
        }

        // 関数アドレス取得
        if((fpGetPluginInfo = (PGETPLUGININFO)GetProcAddress(hSusie,
                                            TEXT("GetPluginInfo"))) == NULL) {
            MyError(hEdit, TEXT("GetProcAddress"), GetLastError());
            FreeLibrary(hSusie);
            goto MySusieEnd;
        }

        // Susie Plug-in情報取得
        (*fpGetPluginInfo)(1, (LPSTR)szCurPath, sizeof(szCurPath));

        // Susie Plug-in解放
        FreeLibrary(hSusie);
    } else
        Edit_AddMessage(hEdit, TEXT("error:SHGetPathFromIDList"), TRUE, TRUE);

MySusieEnd:
    if(lpidBrowse != NULL)
        CoTaskMemFree(lpidBrowse);

    if(lpidRoot != NULL)
        CoTaskMemFree(lpidRoot);

    CoUninitialize();

    return;
}

// フォルダ選択ダイアログプロシージャ
INT CALLBACK BrowseCallbackProc(HWND hWnd, UINT msg, LPARAM lp, LPARAM lpData)
{
    TCHAR szPath[MAX_FILE];
    LPITEMIDLIST lpid;

    switch(msg) {
        case BFFM_INITIALIZED:
            if(lstrlen((LPTSTR)lpData) > 0)
                SendMessage(hWnd, BFFM_SETSELECTION,
                    (WPARAM)TRUE, (LPARAM)(LPTSTR)lpData);
            break;

        case BFFM_VALIDATEFAILED:
            MessageBox(hWnd, TEXT("不正なフォルダです"), NULL, MB_OK);
            return 1;
    }

    return 0;
}

例によって自作関数や外部変数を多用しているので、その辺は脳内補完のこと。

いくつかの関数の簡単な解説。詳細は Google とかで検索して調べること。

SHGetFolderPath: CSIDL 値から特殊フォルダのパスを取得する関数。

CoInitialize: COM 初期化する関数。BROWSEINFO 構造体の ulFlags メンバに BIF_NEWDIALOGSTYLE や BIF_USENEWUI を指定する際は必須。処理終了後、CoUninitialize 関数で解放しなければならない。

SHGetSpecialFolderLocation: 特殊フォルダの ITEMIDLIST 構造体へのポインタ(PIDL)を取得する関数。使用後、CoTaskMemFree 関数で PIDL を解放しなければならない。

SHBrowseForFolder: フォルダ選択コモンダイアログボックスを表示する関数。戻り値は選択したフォルダの ITEMIDLIST 構造体へのポインタ(PIDL)。使用後、CoTaskMemFree 関数で PIDL を解放しなければならない。

SHGetPathFromIDList: PIDL からパスを取得する関数。

その他の解説。

BROWSEINFO 構造体の pidlRoot メンバには、フォルダ選択コモンダイアログボックスのルートを指定する PIDL を設定する。上記のコードでは「マイ コンピュータ」以下しか表示されなくなる。NULL を指定すると「デスクトップ」以下が表示される(つまり、「マイ コンピュータ」や「マイ ネットワーク」、「マイ ドキュメント」など、全部が表示される)。

BROWSEINFO 構造体の lpfn メンバと lParam メンバには、それぞれコールバック関数とコールバック関数に引き渡すデータを指定する。上記のコードでは、初期オープンフォルダを指定し、コールバック関数内の BFFM_INITIALIZED メッセージ受信時に設定を行っている。

参考文献:
MSDN Library Japan
猫でもわかるプログラミング
HSPの裏技??

|

« プログラム試行錯誤 | トップページ | コンプレックス »

コンピュータ・プログラム」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)


コメントは記事投稿者が公開するまで表示されません。



トラックバック

この記事のトラックバックURL:
http://app.cocolog-nifty.com/t/trackback/1757/8768774

この記事へのトラックバック一覧です: プログラム試行錯誤(続):

« プログラム試行錯誤 | トップページ | コンプレックス »