Setting visible columns on new directory

Viewed 339

I'm developing a shell extension that creates a new folder. I'd like the new folder to display a set of custom columns in details view once the user browses into it. I thought that maybe IColumnManager was the correct interface to accomplish this. This is the code I'm trying after the new folder has been created (I've abbreviated the PKEYs):

IShellFolder* psdf;
if (SUCCEEDED(SHGetDesktopFolder(&psdf))) {

    PIDLIST_ABSOLUTE pidl = ILCreateFromPath(pwszNewFolderPath);

    LPSHELLFOLDER psf;
    if (SUCCEEDED(psdf->BindToObject(pidl, NULL, IID_IShellFolder, (void**)& psf))) {

        SFV_CREATE sfvc = { 0 };
        sfvc.cbSize = sizeof(SFV_CREATE);
        sfvc.pshf = psf;
        sfvc.psvOuter = NULL;
        sfvc.psfvcb = NULL;

        LPSHELLVIEW psv;
        if (SUCCEEDED(SHCreateShellFolderView(&sfvc, &psv))) {

            IColumnManager* pcm;
            if (SUCCEEDED(psv->QueryInterface(IID_IColumnManager, (void**)& pcm))) {

                PROPERTYKEY rgkeys[] = {
                    PKEY_ [...] ,
                    PKEY_ [...] ,
                    PKEY_ [...] ,
                };

                if (SUCCEEDED(pcm->SetColumns(rgkeys, ARRAYSIZE(rgkeys)))) {
                    //MessageBoxA(NULL, "Success?", "Success?", MB_OK);
                }
                pcm->Release();
            }
            psv->Release();
        }
        psf->Release();
    }
    psdf->Release();
}

This code successfully executes each method call, but when I go into the newly created folder, the columns aren't as desired. Am I doing something wrong? Does IColumnManager work only when a given folder is already visible? Maybe it's only for IExplorerBrowser or something? And if it's not the right interface, how can I set a set of custom columns for when the user browses into a folder? Thanks.

EDIT: This code actually works on an active view of the folder. However, the changes it makes to the columns do not persist (unlike column changes made manually by the user, which do persist). So I guess I'm wondering if there's a way to make them persist, or if there's another approach to set columns without requiring an active view. Thanks again.

Also, might SHGetViewStatePropertyBag be relevant? Along with IExplorerBrowser::SetPropertyBag? Or could those not be used for regular shell folders?

1 Answers

SHCreateShellFolderView creates a instance of the shell provided IShellView and this interface knows how to save its settings but it asks its IShellBrowser host for the storage implementation. IShellView::CreateViewWindow connects the view to its host.

IShellView::SaveViewState:

Saves the Shell's view settings so the current state can be restored during a subsequent browsing session.

But you need to implement IShellBrowser and call something like SHGetViewStatePropertyBag to get the storage implementation used by Explorer and give this to IShellView when it asks for it. Most of the details here are undocumented and I would recommend that you use IExplorerBrowser to navigate to the folder instead of trying to host IShellView on your own. Use "Shell" as the bag name.

SHGetViewStatePropertyBag was added in Windows XP but IExplorerBrowser does not exist there. If you need to support < Vista you must debug Explorer to discover the undocumented interface that is the glue between IShellView and SHGetViewStatePropertyBag.

On Windows 2000 and older I believe the state is stored directly in the IStream and not in a property bag. OpenRegStream is used to open the stream but the function that calculates the MRU path is undocumented but KB 812003 at least tells you the root.

Related