SHBrowseForFolder"制作新文件夹" Windows XP中的行为

时间:2013-05-10 09:07:53

标签: visual-c++ mfc

我正在使用SHBrowseForFolder和新的对话框样式,它为您提供了“创建新文件夹”按钮

我在Windows XP中遇到了一些问题。

行为是这样的:

1)首先,当我调用对话框时,行为是正常的(即,它正在选择当前文件夹。但是 焦点不在树项上(变暗)。

如果单击“使用此状态创建新文件夹”按钮,则会创建一个新文件夹,但该文件夹未处于选中状态 状态(即,当我们创建一个新文件夹时,它允许您重命名选择文件夹 项目和编辑框)。

如果我选择目录(即,将焦点设置为项目),然后单击新文件夹创建文件夹 处于选定状态。 (在Windows 8,Windows 7和Windows Vista中它工作正常) 任何人都遇到了这个问题。

有没有解决方案?

        bool GetFolder(std::string& folderpath, const char* szCaption = NULL, HWND       hOwner = NULL)

{         bool retVal = false;

// The BROWSEINFO struct tells the shell 
// how it should display the dialog.
BROWSEINFO bi;
memset(&bi, 0, sizeof(bi));

bi.ulFlags   = BIF_NEWDIALOGSTYLE|BIF_RETURNFSANCESTORS|BIF_RETURNONLYFSDIRS; 


bi.hwndOwner = hOwner;
bi.lpszTitle = szCaption;

// must call this if using BIF_USENEWUI
::OleInitialize(NULL);

// Show the dialog and get the itemIDList for the selected folder.
LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);

if(pIDL != NULL)
{
    // Create a buffer to store the path, then get the path.
    char buffer[_MAX_PATH] = {'\0'};
    if(::SHGetPathFromIDList(pIDL, buffer) != 0)
      {
          // Set the string value.
           folderpath = "";
           retVal = true;
      }     

      // free the item id list
          CoTaskMemFree(pIDL);
  }

    ::OleUninitialize();

    return retVal;
    }

1 个答案:

答案 0 :(得分:0)

这似乎是Windows XP中的一个错误。

尝试以下代码。这可能不是您想要的,它会自动扩展默认文件夹,但至少会导致或多或少的正确行为。我在Windows XP和Windows 7上测试过它。在Windows的更高版本中,这可能无法按预期工作,因此您可能应该检查您是否在XP下运行并且只有在XP下运行时才会这样做。

int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM pData)
{
  if (uMsg == BFFM_INITIALIZED)
  {
    HWND hchild = GetWindow(hWnd, GW_CHILD) ;

    while (hchild != NULL)
    {
      TCHAR classname[200] ;
      GetClassName(hchild, classname, 200) ;

      if (lstrcmp(classname, "SHBrowseForFolder ShellNameSpace Control") == 0)
      {
        // hchild is the handle to the ShellName Space Control
        HWND hlistctrl = GetWindow(hchild, GW_CHILD) ;

        do
        {
          // browse through all controls of the ShellnameSpace control
          GetClassName(hlistctrl, classname, 200) ;

          if (lstrcmp(classname, "SysTreeView32") == 0)
            break ;   // we've got the list control

          hlistctrl = GetWindow(hlistctrl, GW_HWNDNEXT) ;
        } while (hlistctrl != NULL) ;

        if (hlistctrl != NULL)
        {
          // get the handle to the selected item
          HTREEITEM ht = (HTREEITEM)::SendMessage(hlistctrl, TVM_GETNEXTITEM, TVGN_CARET, 0) ;

          if (ht != NULL)
          {
            // expand the selected item
            ::SendMessage(hlistctrl, TVM_EXPAND, TVE_EXPAND, (LPARAM)ht) ;
          }
        }
      }

      hchild = GetWindow(hchild, GW_HWNDNEXT) ;
    }
  }

  return 0;
}


bool GetFolder(CString& folderpath, const char* szCaption, HWND hOwner)
{
  bool retVal = false;
  // how it should display the dialog.
  BROWSEINFO bi;
  memset(&bi, 0, sizeof(bi));

  bi.ulFlags   = BIF_NEWDIALOGSTYLE|BIF_RETURNFSANCESTORS|BIF_RETURNONLYFSDIRS; 

  bi.lpfn = BrowseCallbackProc ;
  bi.hwndOwner = hOwner;
  bi.lpszTitle = szCaption;

  // must call this if using BIF_USENEWUI
  ::OleInitialize(NULL);

  // Show the dialog and get the itemIDList for the selected folder.

  LPITEMIDLIST pIDL = ::SHBrowseForFolder(&bi);

  if (pIDL != NULL)
  {
    // Create a buffer to store the path, then get the path.
    char buffer[_MAX_PATH] = {'\0'};
    if(::SHGetPathFromIDList(pIDL, buffer) != 0)
    {
      // Set the string value.
       folderpath = buffer;
       retVal = true;
    }     

    // free the item id list
    CoTaskMemFree(pIDL);
  }

  ::OleUninitialize();

  return retVal;
}

另一种解决方案是使用BFFM_SETEXPANDED消息,如下所示。在此示例中,“C:”文件夹自动展开,然后“新建文件夹”按钮的行为正确。

int CALLBACK BrowseCallbackProc(HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM pData)
{
  if (uMsg == BFFM_INITIALIZED)
  {
    ::SendMessage(hWnd, BFFM_SETEXPANDED, TRUE, (LPARAM)L"C:\\") ;
  }

  return 0;
}