виртуальная папка невидима в 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, диалоговом окне загрузки файла stackoverflow и в обычном проводнике папок.

——————————————————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();

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

введите описание изображения здесь

Но! Когда я пытался загрузить снимок экрана в StackOverflow (я использую веб-браузер 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, чтобы показать ваше расширение.

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

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]