Виртуальная папка невидима в CFileDialog в Windows 7

------------------------- обновление 5-е ----------------------- --------

            if (fIsFolder)
            {
                dwAttribs |= SFGAO_FOLDER;
            }
            else
            {
                dwAttribs |= SFGAO_SYSTEM;

                dwAttribs |= SFGAO_FILESYSTEM;
            }

            if (nLevel < g_nMaxLevel)
            {
                dwAttribs |= SFGAO_HASSUBFOLDER;

                dwAttribs |= SFGAO_FILESYSANCESTOR;
            }

Теперь эта программа работает нормально в приложении A, диалоговом окне загрузки файла stackru и в обычном проводнике папок.

-------------------------------------------------- --- обновление 4-е --------------------------------------------- -------------- После добавления dwAttribs |= SFGAO_SYSTEM; Теперь, по крайней мере, для приложения A, оно работает, как и ожидалось, в диалоговом окне файла. Но папка по-прежнему не активна в обычном диалоговом окне папки или для CWFileDialog,

            if (fIsFolder)
            {
                dwAttribs |= SFGAO_FOLDER;

                dwAttribs |= SFGAO_FILESYSTEM;

                dwAttribs |= SFGAO_FILESYSANCESTOR;
            }
            else
            {
                dwAttribs |= SFGAO_SYSTEM;// this line of code works better

                dwAttribs |= SFGAO_FILESYSTEM;
            }

----------------------------------- обновление третье ------------- ---------------------------- Это код в ISHellFolder виртуальной папки:

После того, как я отредактирую следующий код, чтобы добавить dwAttribs |= SFGAO_FILESYSTEM;, папка не может быть просмотрена, когда я дважды щелкаю ее в представлении папки. Но его можно открыть, щелкнув левой кнопкой мыши в дереве.

 HRESULT CFolderViewImplFolder::GetAttributesOf(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, ULONG *rgfInOut)
{
// If SFGAO_FILESYSTEM is returned, GetDisplayNameOf(SHGDN_FORPARSING) on that item MUST
// return a filesystem path.
HRESULT hr = E_INVALIDARG;

DWORD dwAttribs = 0;

dwAttribs |= SFGAO_FILESYSTEM;

if (1 == cidl)
{
    int nLevel = 0;
    hr = _GetLevel(apidl[0], &nLevel);
    if (SUCCEEDED(hr))
    {
        BOOL fIsFolder = FALSE;
        hr = _GetFolderness(apidl[0], &fIsFolder);
        if (SUCCEEDED(hr))
        {

            if (fIsFolder)
            {
                dwAttribs |= SFGAO_FOLDER;
            }
            if (nLevel < g_nMaxLevel)
            {
                dwAttribs |= SFGAO_HASSUBFOLDER;
            }

        }
    }
}

*rgfInOut &= dwAttribs;

return hr;
}` 

Или же

DWORD dwAttribs = 0;

if (1 == cidl)
{
    int nLevel = 0;
    hr = _GetLevel(apidl[0], &nLevel);
    if (SUCCEEDED(hr))
    {
        BOOL fIsFolder = FALSE;
        hr = _GetFolderness(apidl[0], &fIsFolder);
        if (SUCCEEDED(hr))
        {

            if (fIsFolder)
            {
                dwAttribs |= SFGAO_FOLDER;

                dwAttribs |= SFGAO_FILESYSTEM;

                dwAttribs |= SFGAO_FILESYSANCESTOR;
            }
            else
            {
                dwAttribs |= SFGAO_SYSTEM;
            }

            if (nLevel < g_nMaxLevel)
            {
                dwAttribs |= SFGAO_HASSUBFOLDER;
            }
        }
    }
 }

*rgfInOut &= dwAttribs;

Другие коды такие же, как в update 2nd, Странная вещь, после того, как я редактирую этот код, приложение A, которое использует CFileDialog нормально (не упаковывать, не устанавливать m_bPickNonFileSysFoldersMode в true) все виртуальные папки могут отображаться нормально, как я и ожидал. Но во всех других приложениях (в том числе использует CWFileDilao какой набор m_bPickNonFileSysFoldersMode Истина по-прежнему не может просмотреть виртуальную папку.

--------------------------------------- обновление 2-е --------- ----------------

Я кодирую простой класс, производный от CFileDialog:

class CWFileDlg : public CFileDialog
{
public:
CWFileDlg(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
    LPCTSTR lpszDefExt = NULL,
    LPCTSTR lpszFileName = NULL,
    DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
    LPCTSTR lpszFilter = NULL,
    CWnd* pParentWnd = NULL,
    DWORD dwSize = 0,
    BOOL bVistaStyle = TRUE);

~CWFileDlg();
};

CWFileDlg::CWFileDlg(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs
                    LPCTSTR lpszDefExt,
                    LPCTSTR lpszFileName,
                    DWORD dwFlags,
                    LPCTSTR lpszFilter,
                    CWnd* pParentWnd,
                    DWORD dwSize,
                    BOOL bVistaStyle) : CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd, dwSize, bVistaStyle)
{
    m_bPickNonFileSysFoldersMode = TRUE;
}

CWFileDlg::~CWFileDlg()
{

}

Тогда я называю это так:

CWFileDlg dlg(TRUE, NULL, 0, OFN_SHAREAWARE | OFN_ENABLESIZING | OFN_ALLOWMULTISELECT, L"all(*.*)|*.*||", this);

BOOL IsPickNonFileSysFoldersMode = dlg.IsPickNonFileSysFoldersMode();
//the value it gets is 1, which is TRUE

INT_PTR result = dlg.DoModal();

Но во всплывающем диалоговом окне виртуальная папка все еще невидима. Древовидное представление для него также невидимо. ------------------------------------------ обновления ------- ---------------------

protected:

BOOL m_bVistaStyle;
BOOL m_bPickFoldersMode;
BOOL m_bPickNonFileSysFoldersMode;
DWORD m_dwCookie;
void* m_pIFileDialog;
void* m_pIFileDialogCustomize;

m_bPickNonFileSysFoldersMode не является публичным типом. Как я могу установить его на TRUE?

Error   1   error C2248: 'CFileDialog::m_bPickNonFileSysFoldersMode' : cannot access protected member declared in class 'CFileDialog'   c:\users\liyuan.liu\documents\dp-dll\testvirtualfolder\browser2\browser2\browser2dlg.cpp    166 1   browser2

Используя пример кода Microsoft Windows, я установил виртуальную папку в Windows 7, используя расширение пространства имен оболочки. Следующий скриншот использует обычный браузер папок, чтобы открыть его:

Затем я написал проект, который может создать файл диалога:

CFileDialog dlg(TRUE, NULL, 0, OFN_SHAREAWARE | OFN_ENABLESIZING | OFN_ALLOWMULTISELECT, L"all(*.*)|*.*||", this);
INT_PTR result = dlg.DoModal();

Однако в файловом браузере виртуальная папка невидима:

Но! Когда я пытался загрузить снимок экрана в Stackru (я использую веб-браузер chrome), диалоговое окно файла, которое используется для выбора файла, может отображать древовидное представление (только древовидное представление) виртуальной папки:

При поиске в Google кажется, что CFileDialog не может поддерживать отображение виртуальной папки, так как она фактически не существует в системе. Любые решения, чтобы решить это? Я тоже пробовал с

bi.pidlRoot = pidlVirtual;
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_RETURNFSANCESTORS | BIF_BROWSEINCLUDEFILES | BIF_BROWSEFILEJUNCTIONS;
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);

Также не работает.

1 ответ

К сожалению, диалоговое окно файла показывает функцию приложения, которое его открывает. Начиная с Vista, это IFileDialog интерфейс, который используется, и он определяет набор параметров через метод IFileDialog::SetOptions.

FOS_FORCEFILESYSTEM Флаг гарантирует, что возвращаемые элементы являются элементами файловой системы (SFGAO_FILESYSTEM), и это зависит от того, как вы написали свое расширение. SFGAO_FILESYSTEM должен звонить в колокол, это один из флагов, которые может вернуть метод IShellFolder::GetAttributesOf. Если то, что вы делаете, действительно виртуально (то есть: если вы не возвращаете этот флаг), они не будут показаны, когда IFileDialog настроен таким образом.

Если вы тестируете свое расширение с помощью различных приложений (блокнот, Word, Excel, браузеры и т. Д.), Вы увидите, что иногда вы видите его, а иногда нет.

Spelunking в код MFC (dlgfile.cpp), вы найдете это:

    // We only expect and handle file system paths (for compatibility with GetOpenFileName functionality), so set the
    // "force file system" flag which enables GetOpenFileName-like download behavior for non file system paths, unless
    // the m_bPickNonFileSysFoldersMode is set to allow picking non-file system folders (like libraries in Windows 7).
    dwFlags |= FOS_FORCEFILESYSTEM;
    if (m_bPickNonFileSysFoldersMode)
    {
        dwFlags &= ~FOS_FORCEFILESYSTEM;
    }

Итак, вам нужно установить m_bPickNonFileSysFoldersMode TRUE для CFileDialog, чтобы показать ваше расширение.

Но это не исправит другие приложения, которые вам не принадлежат, которые используют этот флаг...

Другие вопросы по тегам