————————-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);
Также не работает.
К сожалению, диалоговое окно файла показывает функцию приложения, которое его открывает. Начиная с 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, чтобы показать ваше расширение.
Но это не исправит другие приложения, которые вам не принадлежат, которые используют этот флаг …
Других решений пока нет …