views:

270

answers:

3

Obviously this is trivial to do with win32 api - CreateDirectory(). But I'm trying to host an IShellView, and would like to do this the most shell-oriented way. I would have thought that there would be a createobject or createfolder or some such from an IShellFolder. But neither IShellView nor IShellFolder nor even IFolderView seem to have anything quite like this.

Is there a Shell-programming way to create a new folder? Or do I need to create a folder using a pathname, the old-fashioned way?

If I have to do it via CreateDirectory(), then my next question might be: any ideas as to how to get the IShellView / IFolderView to actually see this new object and display it to the user?

Motivation: Creating my own File Dialog replacement and I want to provide the "new folder" toolbar icon functionality of the standard XP-style file dialog.

EDIT: I went ahead and created something that basically works, using CreateDirectory. However, I'm still hoping that there's a better way to do this, but so that you can see how that works, and to offer better ideas as to solve this issue better:

    PidlUtils::Pidl pidl(m_folder);
    CFilename folderName(GetDisplayNameOf(pidl), "New Folder");
    for (int i = 2; folderName.Exists(); ++i)
     folderName.SetFullName(FString("New Folder (%d)", i));
    if (!CPathname::Create(folderName, false))
     throw CContextException("Unable to create a new folder here: ");

    // get the PIDL for the newly created folder
    PidlUtils::Pidl pidlNew;
#ifdef UNICODE
    const wchar_t * wszName = folderName.c_str();
#else
    wchar_t wszName[MAX_PATH];
    MultiByteToWideChar(CP_ACP, 0, folderName.GetFullName(), -1, wszName, MAX_PATH);
#endif
    m_hresult = m_folder->ParseDisplayName(NULL, NULL, wszName, NULL, pidlNew, NULL);
    if (FAILED(m_hresult))
     throw CLabeledException(FString("Unable to get the PIDL for the new folder: 0x%X", m_hresult));

    // upgrade our interface so we can select & rename it
    CComQIPtr<IShellView2> sv2(m_shell_view);
    if (!sv2)
     throw CLabeledException("Unable to obtain the IShellView2 we need to rename the newly created folder.");

    // force it to see thew new folder
    sv2->Refresh();

    // select the new folder, and begin the rename process
    m_hresult = sv2->SelectAndPositionItem(pidlNew, SVSI_EDIT|SVSI_DESELECTOTHERS|SVSI_ENSUREVISIBLE|SVSI_POSITIONITEM, NULL);
    if (FAILED(m_hresult))
     throw CLabeledException(FString("Unable to select and position the new folder item: 0x%X", m_hresult));
+3  A: 

Yes, you can get IContextMenu and look for sub menus, but why bother, just call SHChangeNotify after you call CreateDirectory

Sheng Jiang 蒋晟
Getting an IContextMenu sounds like it might be very useful for obtaining the list of view options in a given shell view (details, small icons, etc.). Are you saying I could try to dig up the command for create new folder from within a context menu and invoke that? Yeah, if that's what you mean, that sounds like a bad idea! I was hopeing for more like IFolderView::CreateObject() or some such.
Mordachai
Yes.. Call SHChangeNotify as this is the correct way to do it. Poking around in the IContextMenu is a good way to ensure your program breaks on the next version of Windows.
Jesse Weigert
+1  A: 

The Win32 API function CreateDirectory seems to be the "correct way". At least, I can find nothing better - and the answers here don't really shed any light on a better way to do it.

Mordachai
+1  A: 
ac
Thank you! Having to mix COM and Win32 to accomplish this seemed bizarre. Of course, this COM Shell way may well bottom out in a call to "CreateDirectory()"! lol ;)
Mordachai