0

我正在使用带有新对话框样式的 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;
    }
4

1 回答 1

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;
}
于 2013-05-13T08:49:06.230 回答