[SHELL32][SHLWAPI][BROWSEUI][EXPLORER] Save folder view state (#7127)

Saves/restores the Listview icon mode, columns and sort info per-folder.
This commit is contained in:
Whindmar Saksit 2024-07-19 14:40:20 +02:00 committed by GitHub
parent fa95a96e9b
commit 802dc9714b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 365 additions and 48 deletions

View file

@ -26,7 +26,6 @@
/*
TODO:
- Load/Save the view state from/into the stream provided by the ShellBrowser unless FWF_NOBROWSERVIEWSTATE is set.
- When editing starts on item, set edit text to for editing value.
- Fix shell view to handle view mode popup exec.
- The background context menu should have a pidl just like foreground menus. This
@ -60,8 +59,18 @@ enum {
typedef struct
{
BOOL bIsAscending;
INT8 Direction;
bool bLoadedFromViewState;
bool bColumnIsFolderColumn;
UINT8 Reserved; // Unused
INT ListColumn;
enum { UNSPECIFIEDCOLUMN = -1 };
void Reset()
{
*(UINT*)this = 0;
ListColumn = UNSPECIFIEDCOLUMN;
}
} LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;
#define SHV_CHANGE_NOTIFY (WM_USER + 0x1111)
@ -71,6 +80,25 @@ typedef struct
// to call TrackPopupMenu and let it use the 0 value as an indication that the menu was canceled
#define CONTEXT_MENU_BASE_ID 1
struct PERSISTCOLUMNS
{
enum { MAXCOUNT = 100 };
static const UINT SIG = ('R' << 0) | ('O' << 8) | ('S' << 16) | (('c') << 24);
UINT Signature;
UINT Count;
UINT Columns[MAXCOUNT];
};
struct PERSISTCLASSICVIEWSTATE
{
static const UINT SIG = ('R' << 0) | ('O' << 8) | ('S' << 16) | (('c' ^ 'v' ^ 's') << 24);
UINT Signature;
WORD SortColId;
INT8 SortDir;
static const UINT VALIDFWF = FWF_AUTOARRANGE | FWF_SNAPTOGRID | FWF_NOGROUPING; // Note: The desktop applies FWF_NOICONS when appropriate
FOLDERSETTINGS FolderSettings;
};
static UINT
GetContextMenuFlags(IShellBrowser *pSB, SFGAOF sfgao)
{
@ -215,6 +243,7 @@ private:
UINT m_cidl;
PCUITEMID_CHILD *m_apidl;
PIDLIST_ABSOLUTE m_pidlParent;
HDPA m_LoadColumnsList;
HDPA m_ListToFolderColMap;
LISTVIEW_SORT_INFO m_sortInfo;
ULONG m_hNotify; // Change notification handle
@ -274,8 +303,8 @@ public:
HRESULT MapListColumnToFolderColumn(UINT ListCol);
HRESULT GetDetailsByFolderColumn(PCUITEMID_CHILD pidl, UINT FoldCol, SHELLDETAILS &sd);
HRESULT GetDetailsByListColumn(PCUITEMID_CHILD pidl, UINT ListCol, SHELLDETAILS &sd);
HRESULT LoadColumn(UINT FoldCol, UINT ListCol, BOOL Insert);
HRESULT LoadColumns(UINT *pColList = NULL, UINT ColListCount = 0);
HRESULT LoadColumn(UINT FoldCol, UINT ListCol, BOOL Insert, UINT ForceWidth = 0);
HRESULT LoadColumns(SIZE_T *pColList = NULL, UINT ColListCount = 0);
void ColumnListChanged();
PCUITEMID_CHILD _PidlByItem(int i);
PCUITEMID_CHILD _PidlByItem(LVITEM& lvItem);
@ -301,6 +330,11 @@ public:
HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
HRESULT InvokeContextMenuCommand(CComPtr<IContextMenu>& pCM, LPCSTR lpVerb, POINT* pt = NULL);
LRESULT OnExplorerCommand(UINT uCommand, BOOL bUseSelection);
FOLDERVIEWMODE GetDefaultViewMode();
HRESULT GetDefaultViewStream(DWORD Stgm, IStream **ppStream);
HRESULT LoadViewState();
HRESULT SaveViewState(IStream *pStream);
void UpdateFolderViewFlags();
// *** IOleWindow methods ***
STDMETHOD(GetWindow)(HWND *lphwnd) override;
@ -529,6 +563,7 @@ CDefView::CDefView() :
m_cidl(0),
m_apidl(NULL),
m_pidlParent(NULL),
m_LoadColumnsList(NULL),
m_hNotify(0),
m_hAccel(NULL),
m_dwAspects(0),
@ -541,13 +576,13 @@ CDefView::CDefView() :
m_Destroyed(FALSE)
{
ZeroMemory(&m_FolderSettings, sizeof(m_FolderSettings));
ZeroMemory(&m_sortInfo, sizeof(m_sortInfo));
ZeroMemory(&m_ptLastMousePos, sizeof(m_ptLastMousePos));
ZeroMemory(&m_Category, sizeof(m_Category));
m_viewinfo_data.clrText = GetSysColor(COLOR_WINDOWTEXT);
m_viewinfo_data.clrTextBack = GetSysColor(COLOR_WINDOW);
m_viewinfo_data.hbmBack = NULL;
m_sortInfo.Reset();
m_ListToFolderColMap = DPA_Create(0);
m_hMyComputerIcon = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_COMPUTER_DESKTOP));
}
@ -570,6 +605,7 @@ CDefView::~CDefView()
}
SHFree(m_apidl);
DPA_Destroy(m_LoadColumnsList);
DPA_Destroy(m_ListToFolderColMap);
}
@ -757,20 +793,21 @@ BOOL CDefView::CreateList()
TRACE("%p\n", this);
dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_AUTOARRANGE; // FIXME: Why is LVS_AUTOARRANGE here?
dwExStyle = WS_EX_CLIENTEDGE;
ListExStyle = 0;
LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_AUTOARRANGE; // FIXME: Remove LVS_AUTOARRANGE when the view is able to save ItemPos
dwExStyle = (m_FolderSettings.fFlags & FWF_NOCLIENTEDGE) ? 0 : WS_EX_CLIENTEDGE;
ListExStyle = LVS_EX_INFOTIP | LVS_EX_LABELTIP;
if (m_FolderSettings.fFlags & FWF_DESKTOP)
{
m_FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
dwStyle |= LVS_ALIGNLEFT;
// LVS_EX_REGIONAL?
}
else
{
dwStyle |= LVS_SHOWSELALWAYS; // MSDN says FWF_SHOWSELALWAYS is deprecated, always turn on for folders
dwStyle |= (m_FolderSettings.fFlags & FWF_ALIGNLEFT) ? LVS_ALIGNLEFT : LVS_ALIGNTOP;
ListExStyle = LVS_EX_DOUBLEBUFFER;
ListExStyle |= LVS_EX_DOUBLEBUFFER;
}
ViewMode = m_FolderSettings.ViewMode;
@ -839,9 +876,6 @@ BOOL CDefView::CreateList()
m_ListView.SetExtendedListViewStyle(ListExStyle);
m_sortInfo.bIsAscending = TRUE;
m_sortInfo.ListColumn = -1;
/* UpdateShellSettings(); */
return TRUE;
}
@ -916,7 +950,16 @@ BOOL CDefView::InitList()
m_ListView.SetImageList(small_icons, LVSIL_SMALL);
m_hMenuArrangeModes = CreateMenu();
LoadColumns();
SIZE_T *pColumns = m_LoadColumnsList ? (SIZE_T*)DPA_GetPtrPtr(m_LoadColumnsList) : NULL;
UINT ColumnCount = pColumns ? DPA_GetPtrCount(m_LoadColumnsList) : 0;
LoadColumns(pColumns, ColumnCount);
if (m_sortInfo.bColumnIsFolderColumn)
{
m_sortInfo.bColumnIsFolderColumn = FALSE;
HRESULT hr = MapFolderColumnToListColumn(m_sortInfo.ListColumn);
m_sortInfo.ListColumn = SUCCEEDED(hr) ? hr : 0;
}
return TRUE;
}
@ -998,7 +1041,7 @@ HRESULT CDefView::GetDetailsByListColumn(PCUITEMID_CHILD pidl, UINT ListCol, SHE
return hr;
}
HRESULT CDefView::LoadColumn(UINT FoldCol, UINT ListCol, BOOL Insert)
HRESULT CDefView::LoadColumn(UINT FoldCol, UINT ListCol, BOOL Insert, UINT ForceWidth)
{
WCHAR buf[MAX_PATH];
SHELLDETAILS sd;
@ -1020,7 +1063,7 @@ HRESULT CDefView::LoadColumn(UINT FoldCol, UINT ListCol, BOOL Insert)
lvc.mask = LVCF_TEXT | LVCF_FMT | LVCF_WIDTH | LVCF_SUBITEM;
lvc.pszText = buf;
lvc.fmt = sd.fmt;
lvc.cx = sd.cxChar * chavewidth; // FIXME: DPI?
lvc.cx = ForceWidth ? ForceWidth : (sd.cxChar * chavewidth); // FIXME: DPI?
lvc.iSubItem = FoldCol; // Used by MapFolderColumnToListColumn & MapListColumnToFolderColumn
if ((int)ListCol == -1)
{
@ -1035,11 +1078,11 @@ HRESULT CDefView::LoadColumn(UINT FoldCol, UINT ListCol, BOOL Insert)
return S_OK;
}
HRESULT CDefView::LoadColumns(UINT *pColList, UINT ColListCount)
HRESULT CDefView::LoadColumns(SIZE_T *pColList, UINT ColListCount)
{
HWND hWndHdr = ListView_GetHeader(m_ListView.m_hWnd);
UINT newColCount = 0, oldColCount = Header_GetItemCount(hWndHdr);
UINT foldCol, i;
UINT width = 0, foldCol, i;
HRESULT hr = S_FALSE;
m_ListView.SetRedraw(FALSE);
@ -1052,7 +1095,8 @@ HRESULT CDefView::LoadColumns(UINT *pColList, UINT ColListCount)
{
if (i >= ColListCount)
break;
foldCol = pColList[i++];
width = HIWORD(pColList[i]);
foldCol = LOWORD(pColList[i++]);
}
SHCOLSTATEF state = 0;
@ -1074,7 +1118,7 @@ HRESULT CDefView::LoadColumns(UINT *pColList, UINT ColListCount)
bool insert = newColCount >= oldColCount;
UINT listCol = insert ? -1 : newColCount;
hr = LoadColumn(foldCol, listCol, insert);
hr = LoadColumn(foldCol, listCol, insert, width);
if (FAILED(hr))
{
if (!pColList)
@ -1091,6 +1135,11 @@ HRESULT CDefView::LoadColumns(UINT *pColList, UINT ColListCount)
m_ListView.SetRedraw(TRUE);
ColumnListChanged();
assert(SUCCEEDED(MapFolderColumnToListColumn(0))); // We don't allow turning off the Name column
if (m_LoadColumnsList)
{
DPA_Destroy(m_LoadColumnsList);
m_LoadColumnsList = NULL;
}
return hr;
}
@ -1170,9 +1219,7 @@ INT CALLBACK CDefView::ListViewCompareItems(LPARAM lParam1, LPARAM lParam2, LPAR
return 0;
SHORT nDiff = HRESULT_CODE(hres);
if (!pThis->m_sortInfo.bIsAscending)
nDiff = -nDiff;
return nDiff;
return nDiff * pThis->m_sortInfo.Direction;
}
BOOL CDefView::_Sort(int Col)
@ -1180,6 +1227,7 @@ BOOL CDefView::_Sort(int Col)
HWND hHeader;
HDITEM hColumn;
int prevCol = m_sortInfo.ListColumn;
m_sortInfo.bLoadedFromViewState = FALSE;
// FIXME: Is this correct? Who sets this style?
// And if it is set, should it also block sorting using the menu?
@ -1197,11 +1245,13 @@ BOOL CDefView::_Sort(int Col)
}
if (prevCol == Col)
m_sortInfo.bIsAscending = !m_sortInfo.bIsAscending;
m_sortInfo.Direction *= -1;
else
m_sortInfo.bIsAscending = TRUE;
m_sortInfo.Direction = 0;
m_sortInfo.ListColumn = Col;
}
if (!m_sortInfo.Direction)
m_sortInfo.Direction += 1;
/* If the sorting column changed, remove the sorting style from the old column */
if (prevCol != -1 && prevCol != m_sortInfo.ListColumn)
@ -1215,11 +1265,12 @@ BOOL CDefView::_Sort(int Col)
/* Set the sorting style on the new column */
hColumn.mask = HDI_FORMAT;
Header_GetItem(hHeader, m_sortInfo.ListColumn, &hColumn);
hColumn.fmt &= (m_sortInfo.bIsAscending ? ~HDF_SORTDOWN : ~HDF_SORTUP );
hColumn.fmt |= (m_sortInfo.bIsAscending ? HDF_SORTUP : HDF_SORTDOWN);
hColumn.fmt &= ~(HDF_SORTDOWN | HDF_SORTUP);
hColumn.fmt |= (m_sortInfo.Direction > 0 ? HDF_SORTUP : HDF_SORTDOWN);
Header_SetItem(hHeader, m_sortInfo.ListColumn, &hColumn);
/* Sort the list, using the current values of ListColumn and bIsAscending */
ASSERT(m_sortInfo.Direction == 1 || m_sortInfo.Direction == -1);
return m_ListView.SortItems(ListViewCompareItems, this);
}
@ -1453,9 +1504,9 @@ HRESULT CDefView::FillList(BOOL IsRefreshCommand)
/* sort the array */
int sortCol = -1;
if (!IsRefreshCommand) // Are we loading for the first time?
if (!IsRefreshCommand && !m_sortInfo.bLoadedFromViewState) // Are we loading for the first time?
{
m_sortInfo.bIsAscending = TRUE;
m_sortInfo.Direction = 0;
sortCol = 0; // In case the folder does not know/care
if (m_pSF2Parent)
{
@ -3073,11 +3124,190 @@ HRESULT WINAPI CDefView::AddPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEE
return S_OK;
}
static HRESULT Read(IStream *pS, LPVOID buffer, ULONG cb)
{
ULONG read;
HRESULT hr = pS->Read(buffer, cb, &read);
return FAILED(hr) ? hr : (cb == read ? S_OK : HResultFromWin32(ERROR_MORE_DATA));
}
static DWORD ReadDWORD(IPropertyBag *pPB, LPCWSTR name, DWORD def)
{
DWORD value;
HRESULT hr = SHPropertyBag_ReadDWORD(pPB, name, &value);
return SUCCEEDED(hr) ? value : def;
}
HRESULT CDefView::GetDefaultViewStream(DWORD Stgm, IStream **ppStream)
{
CLSID clsid;
HRESULT hr = IUnknown_GetClassID(m_pSFParent, &clsid);
if (SUCCEEDED(hr))
{
WCHAR path[MAX_PATH], name[39];
wsprintfW(path, L"%s\\%s", REGSTR_PATH_EXPLORER, L"Streams\\Default");
StringFromGUID2(clsid, name, 39);
*ppStream = SHOpenRegStream2W(HKEY_CURRENT_USER, path, name, Stgm);
hr = *ppStream ? S_OK : E_FAIL;
}
return hr;
}
static HRESULT LoadColumnsStream(PERSISTCOLUMNS &cols, IStream *pS)
{
HRESULT hr = Read(pS, &cols, FIELD_OFFSET(PERSISTCOLUMNS, Columns));
if (FAILED(hr))
return hr;
if (cols.Signature != PERSISTCOLUMNS::SIG || cols.Count > cols.MAXCOUNT)
return HResultFromWin32(ERROR_INVALID_DATA);
return Read(pS, &cols.Columns, sizeof(*cols.Columns) * cols.Count);
}
HRESULT CDefView::LoadViewState()
{
PERSISTCLASSICVIEWSTATE cvs;
PERSISTCOLUMNS cols;
CComPtr<IStream> pS;
CComPtr<IPropertyBag> pPB;
bool fallback = false;
HRESULT hrColumns = E_FAIL;
HRESULT hr = IUnknown_QueryServicePropertyBag(m_pShellBrowser, SHGVSPB_FOLDER, IID_PPV_ARG(IPropertyBag, &pPB));
if (SUCCEEDED(hr))
{
DWORD data;
if (FAILED(hr = SHPropertyBag_ReadDWORD(pPB, L"Mode", &data)))
goto loadfallback;
cvs.FolderSettings.ViewMode = data;
cvs.FolderSettings.fFlags = ReadDWORD(pPB, L"FFlags", FWF_NOGROUPING);
data = ReadDWORD(pPB, L"Sort", ~0ul);
cvs.SortColId = data != ~0ul ? (WORD)data : LISTVIEW_SORT_INFO::UNSPECIFIEDCOLUMN;
cvs.SortDir = (INT8)ReadDWORD(pPB, L"SortDir", 1);
if (SUCCEEDED(hrColumns = SHPropertyBag_ReadStream(pPB, L"ColInfo", &pS)))
hrColumns = LoadColumnsStream(cols, pS);
}
else
{
if (FAILED(hr = (m_pShellBrowser ? m_pShellBrowser->GetViewStateStream(STGM_READ, &pS) : E_UNEXPECTED)))
{
loadfallback:
hr = GetDefaultViewStream(STGM_READ, &pS);
fallback = true;
}
if (FAILED(hr) || FAILED(hr = Read(pS, &cvs, sizeof(cvs))))
return hr;
if (cvs.Signature != cvs.SIG)
return HResultFromWin32(ERROR_INVALID_DATA);
hrColumns = LoadColumnsStream(cols, pS);
}
m_FolderSettings.ViewMode = cvs.FolderSettings.ViewMode;
m_FolderSettings.fFlags &= ~cvs.VALIDFWF;
m_FolderSettings.fFlags |= cvs.FolderSettings.fFlags & cvs.VALIDFWF;
if (SUCCEEDED(hrColumns))
{
BOOL failed = FALSE;
if ((m_LoadColumnsList = DPA_Create(cols.Count)) != NULL)
{
for (UINT i = 0; i < cols.Count; ++i)
{
failed |= !DPA_SetPtr(m_LoadColumnsList, i, UlongToPtr(cols.Columns[i]));
}
}
if (failed || !cols.Count)
{
DPA_Destroy(m_LoadColumnsList);
m_LoadColumnsList = NULL;
}
}
m_sortInfo.bLoadedFromViewState = !fallback && m_LoadColumnsList && cvs.SortColId != LISTVIEW_SORT_INFO::UNSPECIFIEDCOLUMN;
m_sortInfo.bColumnIsFolderColumn = TRUE;
m_sortInfo.Direction = cvs.SortDir > 0 ? 1 : -1;
m_sortInfo.ListColumn = cvs.SortColId;
return hr;
}
HRESULT CDefView::SaveViewState(IStream *pStream)
{
int sortcol = MapListColumnToFolderColumn(m_sortInfo.ListColumn);
PERSISTCLASSICVIEWSTATE cvs;
cvs.SortColId = sortcol >= 0 ? (WORD)sortcol : 0;
cvs.SortDir = m_sortInfo.Direction;
PERSISTCOLUMNS cols;
cols.Signature = PERSISTCOLUMNS::SIG;
cols.Count = 0;
LVCOLUMN lvc;
lvc.mask = LVCF_WIDTH | LVCF_SUBITEM;
for (UINT i = 0, j = 0; i < PERSISTCOLUMNS::MAXCOUNT && ListView_GetColumn(m_ListView, j, &lvc); ++j)
{
HRESULT hr = MapListColumnToFolderColumn(lvc.iSubItem);
if (SUCCEEDED(hr))
{
cols.Columns[i] = MAKELONG(hr, lvc.cx);
cols.Count = ++i;
}
}
UINT cbColumns = FIELD_OFFSET(PERSISTCOLUMNS, Columns) + (sizeof(*cols.Columns) * cols.Count);
UpdateFolderViewFlags();
IPropertyBag *pPB;
HRESULT hr = S_OK;
if (pStream)
{
pStream->AddRef();
goto stream;
}
hr = IUnknown_QueryServicePropertyBag(m_pShellBrowser, SHGVSPB_FOLDER, IID_PPV_ARG(IPropertyBag, &pPB));
if (SUCCEEDED(hr))
{
UINT uViewMode;
GetCurrentViewMode(&uViewMode);
hr = SHPropertyBag_WriteDWORD(pPB, L"Mode", uViewMode);
SHPropertyBag_WriteDWORD(pPB, L"FFlags", m_FolderSettings.fFlags);
SHPropertyBag_WriteDWORD(pPB, L"Sort", cvs.SortColId);
SHPropertyBag_WriteDWORD(pPB, L"SortDir", cvs.SortDir);
pStream = cols.Count ? SHCreateMemStream((LPBYTE)&cols, cbColumns) : NULL;
if (!pStream || FAILED(SHPropertyBag_WriteStream(pPB, L"ColInfo", pStream)))
SHPropertyBag_Delete(pPB, L"ColInfo");
#if 0 // TODO
WCHAR name[MAX_PATH];
memcpy(name, L"ItemPos", sizeof(L"ItemPos"));
if (SHGetPerScreenResName(name + 7, _countof(name) - 7, 0))
{
if (GetAutoArrange() == S_FALSE)
// TODO: Save listview item positions
else
SHPropertyBag_Delete(pPB, name);
}
#endif
pPB->Release();
}
else if (SUCCEEDED(hr = (m_pShellBrowser ? m_pShellBrowser->GetViewStateStream(STGM_WRITE, &pStream) : E_UNEXPECTED)))
{
stream:
ULONG written;
cvs.Signature = cvs.SIG;
cvs.FolderSettings = m_FolderSettings;
hr = pStream->Write(&cvs, sizeof(cvs), &written);
if (SUCCEEDED(hr))
hr = pStream->Write(&cols, cbColumns, &written);
}
if (pStream)
pStream->Release();
return hr;
}
HRESULT WINAPI CDefView::SaveViewState()
{
FIXME("(%p) stub\n", this);
if (!(m_FolderSettings.fFlags & FWF_NOBROWSERVIEWSTATE))
return SaveViewState(NULL);
return S_FALSE;
}
return S_OK;
#define UPDATEFOLDERVIEWFLAGS(bits, bit, set) ( (bits) = ((bits) & ~(bit)) | ((set) ? (bit) : 0) )
void CDefView::UpdateFolderViewFlags()
{
UPDATEFOLDERVIEWFLAGS(m_FolderSettings.fFlags, FWF_AUTOARRANGE, GetAutoArrange() == S_OK);
UPDATEFOLDERVIEWFLAGS(m_FolderSettings.fFlags, FWF_SNAPTOGRID, _GetSnapToGrid() == S_OK);
UPDATEFOLDERVIEWFLAGS(m_FolderSettings.fFlags, FWF_NOGROUPING, !ListView_IsGroupViewEnabled(m_ListView.m_hWnd));
}
HRESULT WINAPI CDefView::SelectItem(PCUITEMID_CHILD pidl, UINT uFlags)
@ -3186,6 +3416,15 @@ HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
return hr;
}
FOLDERVIEWMODE CDefView::GetDefaultViewMode()
{
FOLDERVIEWMODE mode = ((m_FolderSettings.fFlags & FWF_DESKTOP) || !IsOS(OS_SERVERADMINUI)) ? FVM_ICON : FVM_DETAILS;
FOLDERVIEWMODE temp;
if (SUCCEEDED(_DoFolderViewCB(SFVM_DEFVIEWMODE, 0, (LPARAM)&temp)) && temp >= FVM_FIRST && temp <= FVM_LAST)
mode = temp;
return mode;
}
HRESULT STDMETHODCALLTYPE CDefView::GetCurrentViewMode(UINT *pViewMode)
{
TRACE("(%p)->(%p), stub\n", this, pViewMode);
@ -3422,6 +3661,8 @@ HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow2(LPSV2CVW2_PARAMS view_para
HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow3(IShellBrowser *psb, IShellView *psvPrevious, SV3CVW3_FLAGS view_flags, FOLDERFLAGS mask, FOLDERFLAGS flags, FOLDERVIEWMODE mode, const SHELLVIEWID *view_id, const RECT *prcView, HWND *hwnd)
{
OLEMENUGROUPWIDTHS omw = { { 0, 0, 0, 0, 0, 0 } };
const UINT SUPPORTED_SV3CVW3 = SV3CVW3_FORCEVIEWMODE | SV3CVW3_FORCEFOLDERFLAGS;
const UINT IGNORE_FWF = FWF_OWNERDATA; // FIXME: Support this
*hwnd = NULL;
@ -3433,13 +3674,16 @@ HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow3(IShellBrowser *psb, IShell
if (psb == NULL || m_hWnd)
return E_UNEXPECTED;
if (view_flags != SV3CVW3_DEFAULT)
FIXME("unsupported view flags 0x%08x\n", view_flags);
if (view_flags & ~SUPPORTED_SV3CVW3)
FIXME("unsupported view flags 0x%08x\n", view_flags & ~SUPPORTED_SV3CVW3);
if (mode == FVM_AUTO)
mode = GetDefaultViewMode();
/* Set up the member variables */
m_pShellBrowser = psb;
m_FolderSettings.ViewMode = mode;
m_FolderSettings.fFlags = mask & flags;
m_FolderSettings.fFlags = (mask & flags) & ~IGNORE_FWF;
if (view_id)
{
@ -3460,6 +3704,7 @@ HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow3(IShellBrowser *psb, IShell
else
FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_id));
}
const UINT requestedViewMode = m_FolderSettings.ViewMode;
/* Get our parent window */
m_pShellBrowser->GetWindow(&m_hWndParent);
@ -3471,6 +3716,12 @@ HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow3(IShellBrowser *psb, IShell
TRACE("-- CommDlgBrowser\n");
}
LoadViewState();
if (view_flags & SV3CVW3_FORCEVIEWMODE)
m_FolderSettings.ViewMode = requestedViewMode;
if (view_flags & SV3CVW3_FORCEFOLDERFLAGS)
m_FolderSettings.fFlags = (mask & flags) & ~IGNORE_FWF;
RECT rcView = *prcView;
Create(m_hWndParent, rcView, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP, 0, 0U);
if (m_hWnd == NULL)
@ -3800,17 +4051,20 @@ HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCm
if (IsEqualIID(*pguidCmdGroup, CGID_DefView))
{
CComPtr<IStream> pStream;
WCHAR SubKey[MAX_PATH];
switch (nCmdID)
{
case DVCMDID_SET_DEFAULTFOLDER_SETTINGS:
SHDeleteKey(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\ShellNoRoam\\Bags");
FIXME("Save current as default\n");
if (SUCCEEDED(GetDefaultViewStream(STGM_WRITE, &pStream)))
SaveViewState(pStream);
break;
case DVCMDID_RESET_DEFAULTFOLDER_SETTINGS:
wsprintfW(SubKey, L"%s\\%s", REGSTR_PATH_EXPLORER, L"Streams\\Default");
SHDeleteKey(HKEY_CURRENT_USER, SubKey);
SHDeleteKey(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\ShellNoRoam\\Bags");
m_FolderSettings.fFlags |= FWF_NOBROWSERVIEWSTATE; // Don't let this folder save itself
break;
}
}