Michael Jung : shell32: Support BFFM_SETSELECTION[AW]
and BFFM_SETEXPANDED for SHBrowseForFolder.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed May 10 05:22:32 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: b3e6faa7840d0f235db13fd452136294bd42045b
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=b3e6faa7840d0f235db13fd452136294bd42045b
Author: Michael Jung <mjung at iss.tu-darmstadt.de>
Date: Tue May 9 22:24:58 2006 +0200
shell32: Support BFFM_SETSELECTION[AW] and BFFM_SETEXPANDED for SHBrowseForFolder.
---
dlls/shell32/brsfolder.c | 124 ++++++++++++++++++++++++++++++++++++++++------
dlls/shell32/pidl.h | 8 +++
2 files changed, 117 insertions(+), 15 deletions(-)
diff --git a/dlls/shell32/brsfolder.c b/dlls/shell32/brsfolder.c
index 6d5afe1..150b661 100644
--- a/dlls/shell32/brsfolder.c
+++ b/dlls/shell32/brsfolder.c
@@ -540,6 +540,112 @@ static BOOL BrsFolder_OnCommand( browse_
return FALSE;
}
+static BOOL BrsFolder_OnSetExpanded(browse_info *info, LPVOID selection,
+ BOOL is_str, HTREEITEM *pItem)
+{
+ LPITEMIDLIST pidlSelection = (LPITEMIDLIST)selection;
+ LPCITEMIDLIST pidlCurrent, pidlRoot;
+ TVITEMEXW item;
+ BOOL bResult = FALSE;
+
+ /* If 'selection' is a string, convert to a Shell ID List. */
+ if (is_str) {
+ IShellFolder *psfDesktop;
+ HRESULT hr;
+
+ hr = SHGetDesktopFolder(&psfDesktop);
+ if (FAILED(hr))
+ goto done;
+
+ hr = IShellFolder_ParseDisplayName(psfDesktop, NULL, NULL,
+ (LPOLESTR)selection, NULL, &pidlSelection, NULL);
+ IShellFolder_Release(psfDesktop);
+ if (FAILED(hr))
+ goto done;
+ }
+
+ /* Move pidlCurrent behind the SHITEMIDs in pidlSelection, which are the root of
+ * the sub-tree currently displayed. */
+ pidlRoot = info->lpBrowseInfo->pidlRoot;
+ pidlCurrent = pidlSelection;
+ while (!_ILIsEmpty(pidlRoot) && _ILIsEqualSimple(pidlRoot, pidlCurrent)) {
+ pidlRoot = ILGetNext(pidlRoot);
+ pidlCurrent = ILGetNext(pidlCurrent);
+ }
+
+ /* The given ID List is not part of the SHBrowseForFolder's current sub-tree. */
+ if (!_ILIsEmpty(pidlRoot))
+ goto done;
+
+ /* Initialize item to point to the first child of the root folder. */
+ memset(&item, 0, sizeof(item));
+ item.mask = TVIF_PARAM;
+ item.hItem = TreeView_GetRoot(info->hwndTreeView);
+ if (item.hItem)
+ item.hItem = TreeView_GetChild(info->hwndTreeView, item.hItem);
+
+ /* Walk the tree along the nodes corresponding to the remaining ITEMIDLIST */
+ while (item.hItem && !_ILIsEmpty(pidlCurrent)) {
+ LPTV_ITEMDATA pItemData;
+
+ TreeView_GetItemW(info->hwndTreeView, &item);
+ pItemData = (LPTV_ITEMDATA)item.lParam;
+
+ if (_ILIsEqualSimple(pItemData->lpi, pidlCurrent)) {
+ pidlCurrent = ILGetNext(pidlCurrent);
+ if (!_ILIsEmpty(pidlCurrent)) {
+ /* Only expand current node and move on to it's first child,
+ * if we didn't already reach the last SHITEMID */
+ TreeView_Expand(info->hwndTreeView, item.hItem, TVE_EXPAND);
+ item.hItem = TreeView_GetChild(info->hwndTreeView, item.hItem);
+ }
+ } else {
+ item.hItem = TreeView_GetNextSibling(info->hwndTreeView, item.hItem);
+ }
+ }
+
+ if (_ILIsEmpty(pidlCurrent) && item.hItem)
+ bResult = TRUE;
+
+done:
+ if (pidlSelection && pidlSelection != (LPITEMIDLIST)selection)
+ ILFree(pidlSelection);
+
+ if (pItem)
+ *pItem = item.hItem;
+
+ return bResult;
+}
+
+static BOOL BrsFolder_OnSetSelectionW(browse_info *info, LPVOID selection, BOOL is_str) {
+ HTREEITEM hItem;
+ BOOL bResult;
+
+ bResult = BrsFolder_OnSetExpanded(info, selection, is_str, &hItem);
+ if (bResult)
+ TreeView_Select(info->hwndTreeView, hItem, TVGN_CARET);
+ return bResult;
+}
+
+static BOOL BrsFolder_OnSetSelectionA(browse_info *info, LPVOID selection, BOOL is_str) {
+ LPWSTR selectionW = NULL;
+ BOOL result = FALSE;
+ int length;
+
+ if (!is_str)
+ return BrsFolder_OnSetSelectionW(info, selection, is_str);
+
+ if ((length = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)selection, -1, NULL, 0)) &&
+ (selectionW = HeapAlloc(GetProcessHeap(), 0, length)) &&
+ MultiByteToWideChar(CP_ACP, 0, (LPCSTR)selection, -1, selectionW, length))
+ {
+ result = BrsFolder_OnSetSelectionW(info, selectionW, is_str);
+ }
+
+ HeapFree(GetProcessHeap(), 0, selectionW);
+ return result;
+}
+
/*************************************************************************
* BrsFolderDlgProc32 (not an exported API function)
*/
@@ -584,25 +690,13 @@ static INT_PTR CALLBACK BrsFolderDlgProc
break;
case BFFM_SETSELECTIONA:
- if (wParam)
- FIXME("Set selection %s\n", debugstr_a((LPSTR)lParam));
- else
- FIXME("Set selection %p\n", (void*)lParam);
- break;
+ return BrsFolder_OnSetSelectionA(info, (LPVOID)lParam, (BOOL)wParam);
case BFFM_SETSELECTIONW:
- if (wParam)
- FIXME("Set selection %s\n", debugstr_w((LPWSTR)lParam));
- else
- FIXME("Set selection %p\n", (void*)lParam);
- break;
+ return BrsFolder_OnSetSelectionW(info, (LPVOID)lParam, (BOOL)wParam);
case BFFM_SETEXPANDED: /* unicode only */
- if (wParam)
- FIXME("Set expanded %s\n", debugstr_w((LPWSTR)lParam));
- else
- FIXME("Set expanded %p\n", (void*)lParam);
- break;
+ return BrsFolder_OnSetExpanded(info, (LPVOID)lParam, (BOOL)wParam, NULL);
}
return FALSE;
}
diff --git a/dlls/shell32/pidl.h b/dlls/shell32/pidl.h
index e80ceaa..d033987 100644
--- a/dlls/shell32/pidl.h
+++ b/dlls/shell32/pidl.h
@@ -209,6 +209,14 @@ BOOL _ILIsValue (LPCITEMIDLIST pidl);
BOOL _ILIsSpecialFolder (LPCITEMIDLIST pidl);
BOOL _ILIsPidlSimple (LPCITEMIDLIST pidl);
BOOL _ILIsCPanelStruct (LPCITEMIDLIST pidl);
+static inline
+BOOL _ILIsEqualSimple (LPCITEMIDLIST pidlA, LPCITEMIDLIST pidlB)
+{
+ return (pidlA->mkid.cb > 0 && !memcmp(pidlA, pidlB, pidlA->mkid.cb)) ||
+ (!pidlA->mkid.cb && !pidlB->mkid.cb);
+}
+static inline
+BOOL _ILIsEmpty (LPCITEMIDLIST pidl) { return _ILIsDesktop(pidl); }
/*
* simple pidls
More information about the wine-cvs
mailing list