1

どうやら、Vista 以降のアプリでエクスプローラーをホストするかなり簡単な方法があるようです: http://www.codeproject.com/KB/vista/ExplorerBrowser.aspx

ただし、そのインターフェイスは Vista 以降でのみ使用できます。

別の方法があることがわかります。「95 までさかのぼりますが、さらに作業が必要です。IExplorerBrowser を実装し、IShellFolder::CreateViewObject(IID_IShellView) を介してデータ ソースからビューを取得します」

だから私はこの後者のルートに行きたいと思います: IExplorerBrowser を実装します。

そもそもボールを転がすには、どこから IShellFolder * を取得すればよいですか? シェル ビュー コントロールを格納するホスト ウィンドウを指定するにはどうすればよいですか? シェル ビューの境界 rect を指定 (およびサイズ変更) するにはどうすればよいですか?

Windows シェルのこれらのインターフェイスを文書化した包括的なドキュメント セット (またはホワイトページ) はありますか? これまでに収集した情報は非常に断片的であるように思われ、いくつかの例は非常に古く、コンパイルさえできません (現在のバージョンの ATL に大幅に書き直す必要があります)。まったくMFC。

4

4 に答える 4

1

最初にSHGetDesktopFolder()を呼び出すことでボールを転がすことができます。これにより、デスクトップ用の IShellFolder が提供されます。次に、ISF::BindToObject()を呼び出して、表示する特定のサブフォルダーの IShellFolder を取得します。必要な子フォルダーの PIDL がない場合は、SHParseDisplayName()を呼び出してその PIDL を取得できます。

于 2009-10-25T18:17:14.047 に答える
0

残念ながら、私はこのルートにたどり着くことはありませんでした。代わりに、XP..Windows 7 と互換性のある方法で、CFileDialog を調整して、私が望んでいたことを実現しました。

ソリューションの要点は、コモン ダイアログ コントロールから IShellBrowser* インスタンスを取得することです。

// return the IShellBrowser for the common dialog
// NOTE: we force CComPtr to create a new AddRef'd copy (since the one that this gives us is synthesized, and hasn't had an AddRef on our behalf)
CComPtr<IShellBrowser> GetShellBrowser() const { return (IShellBrowser*)::SendMessage(GetCommonDialogHwnd(), CDM_GETISHELLBROWSER, 0, 0); }

より手の込んだことを行うために (実際に何が選択されているかを把握する - ユーザーが隠しファイル拡張子を持っているかどうかに関係なく、その本当のアイデンティティは何か) - 結果の IShellBrowser* を使用します。

例えば:

//////////////////////////////////////////////////////////////////////////
// Get display name of item in file open dialog. Flags tell how.
// SHGDN_FORPARSING gets the full path name even when user has
// checked `Hide extensions for known file types` in Explorer.
//
CString CMFCToolboxAdvancedFileDialog::GetDisplayNameOfItem(int nItem) const
{
    // get the item ID of the given item from the list control
    LPITEMIDLIST pidlAbsolute = GetItemIDListOf(nItem);

    // no PIDL = no display name 
    if (!pidlAbsolute)
        return "";

    // get the display name of our item from the folder IShellFolder interface
    CString path = GetDisplayNameOf(pidlAbsolute);

    // deallocate the PIDL
    ILFree(pidlAbsolute);

    // return the pathname
    return path;
}

どの呼び出し:

// return the ITEMIDLIST for the item at the specified index in the list view (caller is responsible for freeing)
LPITEMIDLIST CMFCToolboxAdvancedFileDialog::GetItemIDListOf(UINT nItem) const
{
    // This can only succeed if there is an IShellView currently (which implies there is a list control)
    CListCtrl * pListCtrl = GetListCtrl();
    if (!pListCtrl)
        return NULL;

    // Use undocumented method (the pidl is stored in the item data)
    // NOTE: Much thanks to Paul DiLascia for this technique (worked up until Vista)
    //       http://www.dilascia.com/index.htm
    if (LPCITEMIDLIST pidlChild = (LPCITEMIDLIST)pListCtrl->GetItemData(nItem))
    {

        // get PIDL of current folder from the common dialog
        LRESULT len = ::SendMessage(GetCommonDialogHwnd(), CDM_GETFOLDERIDLIST, 0, NULL);
        if (!len)
            return NULL;
        LPCITEMIDLIST pidlFolder = (LPCITEMIDLIST)CoTaskMemAlloc(len);
        ::SendMessage(GetCommonDialogHwnd(), CDM_GETFOLDERIDLIST, len, (LPARAM)(void*)pidlFolder);

        // return the absolute ITEMIDLIST
        return ILCombine(pidlFolder, pidlChild);
    }

    // Use another undocumented feature: WM_GETISHELLBROWSER
    CComPtr<IShellBrowser> pShellBrowser(GetShellBrowser());
    if (!pShellBrowser)
        return NULL;

    // attempt to get access to the view
    CComPtr<IShellView> pShellView;
    if (FAILED(pShellBrowser->QueryActiveShellView(&pShellView)))
        return NULL;

    // attempt to get an IDataObject of all items in the view (in view-order)
    CComPtr<IDataObject> pDataObj;
    if (FAILED(pShellView->GetItemObject(SVGIO_ALLVIEW|SVGIO_FLAG_VIEWORDER, IID_IDataObject, (void**)&pDataObj)))
        return NULL;

    // attempt to get the ITEMIDLIST from our clipboard data object
    const UINT cfFormat = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
    FORMATETC fmtetc = { cfFormat, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
    ClipboardStorageMedium stgmed;
    if (FAILED(pDataObj->GetData(&fmtetc, &stgmed)))
        return NULL;

    // cast to the actual data requested
    CIDA * pida = (CIDA*)stgmed.hGlobal;

    // ensure we have that index
    ASSERT(pida->cidl > nItem);
    if (nItem >= pida->cidl)
        return NULL;

    // find the data for the item requested
    const ITEMIDLIST * pidlParent = GetPIDLFolder(pida);
    const ITEMIDLIST * pidlChild = GetPIDLItem(pida, nItem);

    // return the absolute PIDL
    return ILCombine(pidlParent, pidlChild);
}

どの呼び出し:

// NOTE: this is the only way I know to get the actual list control!
CListCtrl * GetListCtrl() const
{
    // return &GetListView()->GetListCtrl();

    // we have to be a window to answer such a question
    ASSERT(IsWindow(GetCommonDialogHwnd()));

    HWND hwnd = ::GetDlgItem(GetCommonDialogHwnd(), IDC_FILE_LIST_VIEW);
    if (hwnd)
        return static_cast<CListCtrl*>(CListCtrl::FromHandle(::GetWindow(hwnd, GW_CHILD)));
    return NULL;
}

うまくいけば、それでアイデアが得られ、ここから先に進むことができます。G/L! ;)

于 2010-09-23T18:42:28.733 に答える
0

IExplorerBrowserを実際に実装する必要はありません。IShellViewを直接操作する方法を知りたいのです。

jeffamaphone の回答は、IShellView を取得するための初期インターフェイスを取得するのに十分なはずです。その後、IShellView::CreateViewWindowメソッドはおそらく開始するのに適した場所です。

ちなみに、MFC はおそらくこのプロセスには関係ありません。ATL スマート ポインター CComPtr または CComQIPtr を使用して、インターフェイス ポインターを保持します。MFC は純粋な Windows オブジェクトのラッパーですが、COM インターフェイスはそのすべてをユーザーから隠します。

于 2010-09-23T19:13:05.243 に答える
-1

Doing so could make some shell namespace extensions think they are running on Vista and trigger undesired results.

Why you think you need to implement IExplorerBrowser for Window versions earlier than Vista? Who would be your interface's clients? This interface is guarded in Windows SDK header files to prevent it to be used in earlier versions.

There are some shell view hosting examples at http://www.codeproject.com/KB/shell/. I am afraid shell view hosting in earlier versions is not as easy as using Vista's IExplorerBrowser .

于 2009-10-25T18:09:25.060 に答える