2 * Copyright 1999 Juergen Schmied
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * - view with root unequal desktop
21 * - show only filesystem objects
27 #include "wine/debug.h"
28 #include "undocshell.h"
31 #include "shell32_main.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
37 static HWND hwndTreeView
;
38 static LPBROWSEINFOW lpBrowseInfo
;
39 static LPITEMIDLIST pidlRet
;
41 static void FillTreeView(LPSHELLFOLDER lpsf
, LPITEMIDLIST lpifq
, HTREEITEM hParent
);
43 static void InitializeTreeView(HWND hwndParent
, LPCITEMIDLIST root
)
45 HIMAGELIST hImageList
;
49 hwndTreeView
= GetDlgItem (hwndParent
, IDD_TREEVIEW
);
50 Shell_GetImageList(NULL
, &hImageList
);
52 TRACE("dlg=%p tree=%p\n", hwndParent
, hwndTreeView
);
54 if (hImageList
&& hwndTreeView
)
55 { TreeView_SetImageList(hwndTreeView
, hImageList
, 0);
58 /* so far, this method doesn't work (still missing the upper level), keep the old way */
60 if (_ILIsDesktop (root
)) {
61 hr
= SHGetDesktopFolder(&lpsf
);
63 IShellFolder
* lpsfdesktop
;
65 hr
= SHGetDesktopFolder(&lpsfdesktop
);
67 hr
= IShellFolder_BindToObject(lpsfdesktop
, root
, 0,(REFIID
)&IID_IShellFolder
,(LPVOID
*)&lpsf
);
68 IShellFolder_Release(lpsfdesktop
);
72 hr
= SHGetDesktopFolder(&lpsf
);
75 if (SUCCEEDED(hr
) && hwndTreeView
)
76 { TreeView_DeleteAllItems(hwndTreeView
);
77 FillTreeView(lpsf
, NULL
, TVI_ROOT
);
81 { IShellFolder_Release(lpsf
);
86 static int GetIcon(LPITEMIDLIST lpi
, UINT uFlags
)
88 SHGetFileInfoW((LPCWSTR
)lpi
, 0 ,&sfi
, sizeof(SHFILEINFOW
), uFlags
);
92 static void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq
, LPTVITEMW lpTV_ITEM
)
93 { TRACE("%p %p\n",lpifq
, lpTV_ITEM
);
95 lpTV_ITEM
->iImage
= GetIcon(lpifq
, SHGFI_PIDL
| SHGFI_SYSICONINDEX
| SHGFI_SMALLICON
);
96 lpTV_ITEM
->iSelectedImage
= GetIcon(lpifq
, SHGFI_PIDL
| SHGFI_SYSICONINDEX
| SHGFI_SMALLICON
| SHGFI_OPENICON
);
103 LPSHELLFOLDER lpsfParent
;
106 } TV_ITEMDATA
, *LPTV_ITEMDATA
;
108 static BOOL
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST lpi
, DWORD dwFlags
, LPWSTR lpFriendlyName
)
113 TRACE("%p %p %lx %p\n", lpsf
, lpi
, dwFlags
, lpFriendlyName
);
114 if (SUCCEEDED(IShellFolder_GetDisplayNameOf(lpsf
, lpi
, dwFlags
, &str
)))
116 if (FAILED(StrRetToStrNW(lpFriendlyName
, MAX_PATH
, &str
, lpi
)))
124 TRACE("-- %s\n", debugstr_w(lpFriendlyName
));
128 static void FillTreeView(IShellFolder
* lpsf
, LPITEMIDLIST pidl
, HTREEITEM hParent
)
131 TVINSERTSTRUCTW tvins
;
134 LPITEMIDLIST pidlTemp
=0;
135 LPTV_ITEMDATA lptvid
=0;
138 WCHAR szBuff
[MAX_PATH
];
139 HWND hwnd
=GetParent(hwndTreeView
);
141 TRACE("%p %p %x\n",lpsf
, pidl
, (INT
)hParent
);
142 SetCapture(GetParent(hwndTreeView
));
143 SetCursor(LoadCursorA(0, IDC_WAITA
));
145 hr
=IShellFolder_EnumObjects(lpsf
, hwnd
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &lpe
);
148 { while (NOERROR
== IEnumIDList_Next(lpe
,1,&pidlTemp
,&ulFetched
))
149 { ULONG ulAttrs
= SFGAO_HASSUBFOLDER
| SFGAO_FOLDER
;
150 IShellFolder_GetAttributesOf(lpsf
, 1, &pidlTemp
, &ulAttrs
);
151 if (ulAttrs
& (SFGAO_HASSUBFOLDER
| SFGAO_FOLDER
))
152 { if (ulAttrs
& SFGAO_FOLDER
)
153 { tvi
.mask
= TVIF_TEXT
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
| TVIF_PARAM
;
155 if (ulAttrs
& SFGAO_HASSUBFOLDER
)
157 tvi
.mask
|= TVIF_CHILDREN
;
160 if (!(lptvid
= (LPTV_ITEMDATA
)SHAlloc(sizeof(TV_ITEMDATA
))))
163 if (!GetName(lpsf
, pidlTemp
, SHGDN_NORMAL
, szBuff
))
166 tvi
.pszText
= szBuff
;
167 tvi
.cchTextMax
= MAX_PATH
;
168 tvi
.lParam
= (LPARAM
)lptvid
;
170 IShellFolder_AddRef(lpsf
);
171 lptvid
->lpsfParent
= lpsf
;
172 lptvid
->lpi
= ILClone(pidlTemp
);
173 lptvid
->lpifq
= ILCombine(pidl
, pidlTemp
);
174 GetNormalAndSelectedIcons(lptvid
->lpifq
, &tvi
);
176 tvins
.DUMMYUNIONNAME
.item
= tvi
;
177 tvins
.hInsertAfter
= hPrev
;
178 tvins
.hParent
= hParent
;
180 hPrev
= (HTREEITEM
)TreeView_InsertItemW(hwndTreeView
, &tvins
);
184 SHFree(pidlTemp
); /* Finally, free the pidl that the shell gave us... */
191 SetCursor(LoadCursorW(0, IDC_ARROWW
));
194 IEnumIDList_Release(lpe
);
199 static LRESULT
MsgNotify(HWND hWnd
, UINT CtlID
, LPNMHDR lpnmh
)
201 NMTREEVIEWW
*pnmtv
= (NMTREEVIEWW
*)lpnmh
;
202 LPTV_ITEMDATA lptvid
; /* Long pointer to TreeView item data */
203 IShellFolder
* lpsf2
=0;
206 TRACE("%p %x %p msg=%x\n", hWnd
, CtlID
, lpnmh
, pnmtv
->hdr
.code
);
208 switch (pnmtv
->hdr
.idFrom
)
210 switch (pnmtv
->hdr
.code
)
211 { case TVN_DELETEITEMA
:
212 case TVN_DELETEITEMW
:
213 { FIXME("TVN_DELETEITEMA/W\n");
214 lptvid
=(LPTV_ITEMDATA
)pnmtv
->itemOld
.lParam
;
215 IShellFolder_Release(lptvid
->lpsfParent
);
217 SHFree(lptvid
->lpifq
);
222 case TVN_ITEMEXPANDINGA
:
223 case TVN_ITEMEXPANDINGW
:
224 { FIXME("TVN_ITEMEXPANDINGA/W\n");
225 if ((pnmtv
->itemNew
.state
& TVIS_EXPANDEDONCE
))
228 lptvid
=(LPTV_ITEMDATA
)pnmtv
->itemNew
.lParam
;
229 if (SUCCEEDED(IShellFolder_BindToObject(lptvid
->lpsfParent
, lptvid
->lpi
,0,(REFIID
)&IID_IShellFolder
,(LPVOID
*)&lpsf2
)))
230 { FillTreeView( lpsf2
, lptvid
->lpifq
, pnmtv
->itemNew
.hItem
);
232 TreeView_SortChildren(hwndTreeView
, pnmtv
->itemNew
.hItem
, FALSE
);
235 case TVN_SELCHANGEDA
:
236 case TVN_SELCHANGEDW
:
237 lptvid
=(LPTV_ITEMDATA
)pnmtv
->itemNew
.lParam
;
238 pidlRet
= lptvid
->lpifq
;
239 if (lpBrowseInfo
->lpfn
)
240 (lpBrowseInfo
->lpfn
)(hWnd
, BFFM_SELCHANGED
, (LPARAM
)pidlRet
, lpBrowseInfo
->lParam
);
244 FIXME("unhandled (%d)\n", pnmtv
->hdr
.code
);
257 /*************************************************************************
258 * BrsFolderDlgProc32 (not an exported API function)
260 static INT_PTR CALLBACK
BrsFolderDlgProc(HWND hWnd
, UINT msg
, WPARAM wParam
,
263 TRACE("hwnd=%p msg=%04x 0x%08x 0x%08lx\n", hWnd
, msg
, wParam
, lParam
);
266 { case WM_INITDIALOG
:
268 lpBrowseInfo
= (LPBROWSEINFOW
) lParam
;
269 if (lpBrowseInfo
->ulFlags
& ~(BIF_STATUSTEXT
))
270 FIXME("flags %x not implemented\n", lpBrowseInfo
->ulFlags
& ~(BIF_STATUSTEXT
));
271 if (lpBrowseInfo
->lpszTitle
) {
272 SetWindowTextW(GetDlgItem(hWnd
, IDD_TITLE
), lpBrowseInfo
->lpszTitle
);
274 ShowWindow(GetDlgItem(hWnd
, IDD_TITLE
), SW_HIDE
);
276 if (!(lpBrowseInfo
->ulFlags
& BIF_STATUSTEXT
))
277 ShowWindow(GetDlgItem(hWnd
, IDD_STATUS
), SW_HIDE
);
279 if (lpBrowseInfo
->pidlRoot
)
280 FIXME("root is desktop\n");
282 InitializeTreeView(hWnd
, lpBrowseInfo
->pidlRoot
);
284 if (lpBrowseInfo
->lpfn
) {
285 (lpBrowseInfo
->lpfn
)(hWnd
, BFFM_INITIALIZED
, 0, lpBrowseInfo
->lParam
);
286 (lpBrowseInfo
->lpfn
)(hWnd
, BFFM_SELCHANGED
, 0/*FIXME*/, lpBrowseInfo
->lParam
);
292 MsgNotify( hWnd
, (UINT
)wParam
, (LPNMHDR
)lParam
);
299 SHGetPathFromIDListW(pidlRet
, lpBrowseInfo
->pszDisplayName
);
300 EndDialog(hWnd
, (DWORD
) ILClone(pidlRet
));
308 case BFFM_SETSTATUSTEXTA
:
309 TRACE("Set status %s\n", debugstr_a((LPSTR
)lParam
));
310 SetWindowTextA(GetDlgItem(hWnd
, IDD_STATUS
), (LPSTR
)lParam
);
312 case BFFM_SETSTATUSTEXTW
:
313 TRACE("Set status %s\n", debugstr_w((LPWSTR
)lParam
));
314 SetWindowTextW(GetDlgItem(hWnd
, IDD_STATUS
), (LPWSTR
)lParam
);
317 TRACE("Enable %ld\n", lParam
);
318 EnableWindow(GetDlgItem(hWnd
, 1), (lParam
)?TRUE
:FALSE
);
320 case BFFM_SETSELECTIONA
:
322 TRACE("Set selection %s\n", debugstr_a((LPSTR
)lParam
));
324 TRACE("Set selection %p\n", (void*)lParam
);
326 case BFFM_SETSELECTIONW
:
328 TRACE("Set selection %s\n", debugstr_w((LPWSTR
)lParam
));
330 TRACE("Set selection %p\n", (void*)lParam
);
336 static WCHAR swBrowseTempName
[] = {'S','H','B','R','S','F','O','R','F','O','L','D','E','R','_','M','S','G','B','O','X',0};
338 /*************************************************************************
339 * SHBrowseForFolderA [SHELL32.@]
340 * SHBrowseForFolder [SHELL32.@]
342 LPITEMIDLIST WINAPI
SHBrowseForFolderA (LPBROWSEINFOA lpbi
)
348 TRACE("(%p{lpszTitle=%s,owner=%p})\n", lpbi
,
349 lpbi
? debugstr_a(lpbi
->lpszTitle
) : NULL
, lpbi
? lpbi
->hwndOwner
: NULL
);
354 bi
.hwndOwner
= lpbi
->hwndOwner
;
355 bi
.pidlRoot
= lpbi
->pidlRoot
;
356 if (lpbi
->pszDisplayName
)
358 len
= MultiByteToWideChar(CP_ACP
, 0, lpbi
->pszDisplayName
, -1, NULL
, 0);
359 bi
.pszDisplayName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
360 MultiByteToWideChar(CP_ACP
, 0, lpbi
->pszDisplayName
, -1, bi
.pszDisplayName
, len
);
363 bi
.pszDisplayName
= NULL
;
367 len
= MultiByteToWideChar(CP_ACP
, 0, lpbi
->lpszTitle
, -1, NULL
, 0);
368 bi
.lpszTitle
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
369 MultiByteToWideChar(CP_ACP
, 0, lpbi
->lpszTitle
, -1, (LPWSTR
)bi
.lpszTitle
, len
);
374 bi
.ulFlags
= lpbi
->ulFlags
;
375 bi
.lpfn
= lpbi
->lpfn
;
376 bi
.lParam
= lpbi
->lParam
;
377 bi
.iImage
= lpbi
->iImage
;
378 lpid
= (LPITEMIDLIST
) DialogBoxParamW(shell32_hInstance
,
379 swBrowseTempName
, lpbi
->hwndOwner
,
380 BrsFolderDlgProc
, (INT
)&bi
);
381 if (bi
.pszDisplayName
)
383 WideCharToMultiByte(CP_ACP
, 0, bi
.pszDisplayName
, -1, lpbi
->pszDisplayName
, MAX_PATH
, 0, NULL
);
384 HeapFree(GetProcessHeap(), 0, bi
.pszDisplayName
);
388 HeapFree(GetProcessHeap(), 0, (LPVOID
)bi
.lpszTitle
);
390 lpbi
->iImage
= bi
.iImage
;
395 /*************************************************************************
396 * SHBrowseForFolderW [SHELL32.@]
398 LPITEMIDLIST WINAPI
SHBrowseForFolderW (LPBROWSEINFOW lpbi
)
400 TRACE("((%p->{lpszTitle=%s,owner=%p})\n", lpbi
,
401 lpbi
? debugstr_w(lpbi
->lpszTitle
) : NULL
, lpbi
? lpbi
->hwndOwner
: 0);
406 return (LPITEMIDLIST
) DialogBoxParamW(shell32_hInstance
,
407 swBrowseTempName
, lpbi
->hwndOwner
,
408 BrsFolderDlgProc
, (INT
)lpbi
);