Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the "Shell Namespace" way to create a new folder?

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));
like image 709
Mordachai Avatar asked Oct 15 '25 16:10

Mordachai


2 Answers

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

like image 82
Sheng Jiang 蒋晟 Avatar answered Oct 17 '25 05:10

Sheng Jiang 蒋晟


Shell folders usually implement the IStorage interface, so this is pretty simple. For example, the following creates a folder named "abcd" on the desktop:

  CComPtr<IShellFolder> pDesktop;
  HRESULT hr = SHGetDesktopFolder(&pDesktop);
  if (FAILED(hr)) return;
  CComQIPtr<IStorage> pStorage(pDesktop);
  if (!pStorage) return;
  CComPtr<IStorage> dummy;
  hr = pStorage->CreateStorage(L"abcd", STGM_FAILIFTHERE, 0, 0, &dummy);
like image 43
ac. Avatar answered Oct 17 '25 04:10

ac.