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 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "wine/debug.h"
30 #include "undocshell.h"
33 #include "shell32_main.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
39 static HWND hwndTreeView
;
40 static LPBROWSEINFOW lpBrowseInfo
;
41 static LPITEMIDLIST pidlRet
;
43 static void FillTreeView(LPSHELLFOLDER lpsf
, LPITEMIDLIST lpifq
, HTREEITEM hParent
);
45 static void InitializeTreeView(HWND hwndParent
, LPCITEMIDLIST root
)
47 HIMAGELIST hImageList
;
51 hwndTreeView
= GetDlgItem (hwndParent
, IDD_TREEVIEW
);
52 Shell_GetImageList(NULL
, &hImageList
);
54 TRACE("dlg=%p tree=%p\n", hwndParent
, hwndTreeView
);
56 if (hImageList
&& hwndTreeView
)
57 { TreeView_SetImageList(hwndTreeView
, hImageList
, 0);
60 /* so far, this method doesn't work (still missing the upper level), keep the old way */
62 if (_ILIsDesktop (root
)) {
63 hr
= SHGetDesktopFolder(&lpsf
);
65 IShellFolder
* lpsfdesktop
;
67 hr
= SHGetDesktopFolder(&lpsfdesktop
);
69 hr
= IShellFolder_BindToObject(lpsfdesktop
, root
, 0,(REFIID
)&IID_IShellFolder
,(LPVOID
*)&lpsf
);
70 IShellFolder_Release(lpsfdesktop
);
74 hr
= SHGetDesktopFolder(&lpsf
);
77 if (SUCCEEDED(hr
) && hwndTreeView
)
78 { TreeView_DeleteAllItems(hwndTreeView
);
79 FillTreeView(lpsf
, NULL
, TVI_ROOT
);
83 { IShellFolder_Release(lpsf
);
88 static int GetIcon(LPITEMIDLIST lpi
, UINT uFlags
)
90 SHGetFileInfoW((LPCWSTR
)lpi
, 0 ,&sfi
, sizeof(SHFILEINFOW
), uFlags
);
94 static void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq
, LPTVITEMW lpTV_ITEM
)
95 { TRACE("%p %p\n",lpifq
, lpTV_ITEM
);
97 lpTV_ITEM
->iImage
= GetIcon(lpifq
, SHGFI_PIDL
| SHGFI_SYSICONINDEX
| SHGFI_SMALLICON
);
98 lpTV_ITEM
->iSelectedImage
= GetIcon(lpifq
, SHGFI_PIDL
| SHGFI_SYSICONINDEX
| SHGFI_SMALLICON
| SHGFI_OPENICON
);
105 LPSHELLFOLDER lpsfParent
;
108 } TV_ITEMDATA
, *LPTV_ITEMDATA
;
110 static BOOL
GetName(LPSHELLFOLDER lpsf
, LPITEMIDLIST lpi
, DWORD dwFlags
, LPWSTR lpFriendlyName
)
115 TRACE("%p %p %lx %p\n", lpsf
, lpi
, dwFlags
, lpFriendlyName
);
116 if (SUCCEEDED(IShellFolder_GetDisplayNameOf(lpsf
, lpi
, dwFlags
, &str
)))
118 if (FAILED(StrRetToStrNW(lpFriendlyName
, MAX_PATH
, &str
, lpi
)))
126 TRACE("-- %s\n", debugstr_w(lpFriendlyName
));
130 static void FillTreeView(IShellFolder
* lpsf
, LPITEMIDLIST pidl
, HTREEITEM hParent
)
133 TVINSERTSTRUCTW tvins
;
136 LPITEMIDLIST pidlTemp
=0;
137 LPTV_ITEMDATA lptvid
=0;
140 WCHAR szBuff
[MAX_PATH
];
141 HWND hwnd
=GetParent(hwndTreeView
);
143 TRACE("%p %p %x\n",lpsf
, pidl
, (INT
)hParent
);
144 SetCapture(GetParent(hwndTreeView
));
145 SetCursor(LoadCursorA(0, IDC_WAITA
));
147 hr
=IShellFolder_EnumObjects(lpsf
, hwnd
, SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
, &lpe
);
150 { while (NOERROR
== IEnumIDList_Next(lpe
,1,&pidlTemp
,&ulFetched
))
151 { ULONG ulAttrs
= SFGAO_HASSUBFOLDER
| SFGAO_FOLDER
;
152 IShellFolder_GetAttributesOf(lpsf
, 1, &pidlTemp
, &ulAttrs
);
153 if (ulAttrs
& (SFGAO_HASSUBFOLDER
| SFGAO_FOLDER
))
154 { if (ulAttrs
& SFGAO_FOLDER
)
155 { tvi
.mask
= TVIF_TEXT
| TVIF_IMAGE
| TVIF_SELECTEDIMAGE
| TVIF_PARAM
;
157 if (ulAttrs
& SFGAO_HASSUBFOLDER
)
159 tvi
.mask
|= TVIF_CHILDREN
;
162 if (!(lptvid
= (LPTV_ITEMDATA
)SHAlloc(sizeof(TV_ITEMDATA
))))
165 if (!GetName(lpsf
, pidlTemp
, SHGDN_NORMAL
, szBuff
))
168 tvi
.pszText
= szBuff
;
169 tvi
.cchTextMax
= MAX_PATH
;
170 tvi
.lParam
= (LPARAM
)lptvid
;
172 IShellFolder_AddRef(lpsf
);
173 lptvid
->lpsfParent
= lpsf
;
174 lptvid
->lpi
= ILClone(pidlTemp
);
175 lptvid
->lpifq
= ILCombine(pidl
, pidlTemp
);
176 GetNormalAndSelectedIcons(lptvid
->lpifq
, &tvi
);
178 tvins
.DUMMYUNIONNAME
.item
= tvi
;
179 tvins
.hInsertAfter
= hPrev
;
180 tvins
.hParent
= hParent
;
182 hPrev
= (HTREEITEM
)TreeView_InsertItemW(hwndTreeView
, &tvins
);
186 SHFree(pidlTemp
); /* Finally, free the pidl that the shell gave us... */
193 SetCursor(LoadCursorW(0, IDC_ARROWW
));
196 IEnumIDList_Release(lpe
);
201 static LRESULT
MsgNotify(HWND hWnd
, UINT CtlID
, LPNMHDR lpnmh
)
203 NMTREEVIEWW
*pnmtv
= (NMTREEVIEWW
*)lpnmh
;
204 LPTV_ITEMDATA lptvid
; /* Long pointer to TreeView item data */
205 IShellFolder
* lpsf2
=0;
208 TRACE("%p %x %p msg=%x\n", hWnd
, CtlID
, lpnmh
, pnmtv
->hdr
.code
);
210 switch (pnmtv
->hdr
.idFrom
)
212 switch (pnmtv
->hdr
.code
)
213 { case TVN_DELETEITEMA
:
214 case TVN_DELETEITEMW
:
215 { FIXME("TVN_DELETEITEMA/W\n");
216 lptvid
=(LPTV_ITEMDATA
)pnmtv
->itemOld
.lParam
;
217 IShellFolder_Release(lptvid
->lpsfParent
);
219 SHFree(lptvid
->lpifq
);
224 case TVN_ITEMEXPANDINGA
:
225 case TVN_ITEMEXPANDINGW
:
226 { FIXME("TVN_ITEMEXPANDINGA/W\n");
227 if ((pnmtv
->itemNew
.state
& TVIS_EXPANDEDONCE
))
230 lptvid
=(LPTV_ITEMDATA
)pnmtv
->itemNew
.lParam
;
231 if (SUCCEEDED(IShellFolder_BindToObject(lptvid
->lpsfParent
, lptvid
->lpi
,0,(REFIID
)&IID_IShellFolder
,(LPVOID
*)&lpsf2
)))
232 { FillTreeView( lpsf2
, lptvid
->lpifq
, pnmtv
->itemNew
.hItem
);
234 TreeView_SortChildren(hwndTreeView
, pnmtv
->itemNew
.hItem
, FALSE
);
237 case TVN_SELCHANGEDA
:
238 case TVN_SELCHANGEDW
:
239 lptvid
=(LPTV_ITEMDATA
)pnmtv
->itemNew
.lParam
;
240 pidlRet
= lptvid
->lpifq
;
241 if (lpBrowseInfo
->lpfn
)
242 (lpBrowseInfo
->lpfn
)(hWnd
, BFFM_SELCHANGED
, (LPARAM
)pidlRet
, lpBrowseInfo
->lParam
);
246 FIXME("unhandled (%d)\n", pnmtv
->hdr
.code
);
259 /*************************************************************************
260 * BrsFolderDlgProc32 (not an exported API function)
262 static INT_PTR CALLBACK
BrsFolderDlgProc(HWND hWnd
, UINT msg
, WPARAM wParam
,
265 TRACE("hwnd=%p msg=%04x 0x%08x 0x%08lx\n", hWnd
, msg
, wParam
, lParam
);
268 { case WM_INITDIALOG
:
270 lpBrowseInfo
= (LPBROWSEINFOW
) lParam
;
271 if (lpBrowseInfo
->ulFlags
& ~(BIF_STATUSTEXT
))
272 FIXME("flags %x not implemented\n", lpBrowseInfo
->ulFlags
& ~(BIF_STATUSTEXT
));
273 if (lpBrowseInfo
->lpszTitle
) {
274 SetWindowTextW(GetDlgItem(hWnd
, IDD_TITLE
), lpBrowseInfo
->lpszTitle
);
276 ShowWindow(GetDlgItem(hWnd
, IDD_TITLE
), SW_HIDE
);
278 if (!(lpBrowseInfo
->ulFlags
& BIF_STATUSTEXT
))
279 ShowWindow(GetDlgItem(hWnd
, IDD_STATUS
), SW_HIDE
);
281 if (lpBrowseInfo
->pidlRoot
)
282 FIXME("root is desktop\n");
284 InitializeTreeView(hWnd
, lpBrowseInfo
->pidlRoot
);
286 if (lpBrowseInfo
->lpfn
) {
287 (lpBrowseInfo
->lpfn
)(hWnd
, BFFM_INITIALIZED
, 0, lpBrowseInfo
->lParam
);
288 (lpBrowseInfo
->lpfn
)(hWnd
, BFFM_SELCHANGED
, 0/*FIXME*/, lpBrowseInfo
->lParam
);
294 MsgNotify( hWnd
, (UINT
)wParam
, (LPNMHDR
)lParam
);
301 SHGetPathFromIDListW(pidlRet
, lpBrowseInfo
->pszDisplayName
);
302 EndDialog(hWnd
, (DWORD
) ILClone(pidlRet
));
310 case BFFM_SETSTATUSTEXTA
:
311 TRACE("Set status %s\n", debugstr_a((LPSTR
)lParam
));
312 SetWindowTextA(GetDlgItem(hWnd
, IDD_STATUS
), (LPSTR
)lParam
);
314 case BFFM_SETSTATUSTEXTW
:
315 TRACE("Set status %s\n", debugstr_w((LPWSTR
)lParam
));
316 SetWindowTextW(GetDlgItem(hWnd
, IDD_STATUS
), (LPWSTR
)lParam
);
319 TRACE("Enable %ld\n", lParam
);
320 EnableWindow(GetDlgItem(hWnd
, 1), (lParam
)?TRUE
:FALSE
);
322 case BFFM_SETSELECTIONA
:
324 TRACE("Set selection %s\n", debugstr_a((LPSTR
)lParam
));
326 TRACE("Set selection %p\n", (void*)lParam
);
328 case BFFM_SETSELECTIONW
:
330 TRACE("Set selection %s\n", debugstr_w((LPWSTR
)lParam
));
332 TRACE("Set selection %p\n", (void*)lParam
);
338 static WCHAR swBrowseTempName
[] = {'S','H','B','R','S','F','O','R','F','O','L','D','E','R','_','M','S','G','B','O','X',0};
340 /*************************************************************************
341 * SHBrowseForFolderA [SHELL32.@]
342 * SHBrowseForFolder [SHELL32.@]
344 LPITEMIDLIST WINAPI
SHBrowseForFolderA (LPBROWSEINFOA lpbi
)
350 TRACE("(%p{lpszTitle=%s,owner=%p})\n", lpbi
,
351 lpbi
? debugstr_a(lpbi
->lpszTitle
) : NULL
, lpbi
? lpbi
->hwndOwner
: NULL
);
356 bi
.hwndOwner
= lpbi
->hwndOwner
;
357 bi
.pidlRoot
= lpbi
->pidlRoot
;
358 if (lpbi
->pszDisplayName
)
360 len
= MultiByteToWideChar(CP_ACP
, 0, lpbi
->pszDisplayName
, -1, NULL
, 0);
361 bi
.pszDisplayName
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
362 MultiByteToWideChar(CP_ACP
, 0, lpbi
->pszDisplayName
, -1, bi
.pszDisplayName
, len
);
365 bi
.pszDisplayName
= NULL
;
369 len
= MultiByteToWideChar(CP_ACP
, 0, lpbi
->lpszTitle
, -1, NULL
, 0);
370 bi
.lpszTitle
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
371 MultiByteToWideChar(CP_ACP
, 0, lpbi
->lpszTitle
, -1, (LPWSTR
)bi
.lpszTitle
, len
);
376 bi
.ulFlags
= lpbi
->ulFlags
;
377 bi
.lpfn
= lpbi
->lpfn
;
378 bi
.lParam
= lpbi
->lParam
;
379 bi
.iImage
= lpbi
->iImage
;
380 lpid
= (LPITEMIDLIST
) DialogBoxParamW(shell32_hInstance
,
381 swBrowseTempName
, lpbi
->hwndOwner
,
382 BrsFolderDlgProc
, (INT
)&bi
);
383 if (bi
.pszDisplayName
)
385 WideCharToMultiByte(CP_ACP
, 0, bi
.pszDisplayName
, -1, lpbi
->pszDisplayName
, MAX_PATH
, 0, NULL
);
386 HeapFree(GetProcessHeap(), 0, bi
.pszDisplayName
);
390 HeapFree(GetProcessHeap(), 0, (LPVOID
)bi
.lpszTitle
);
392 lpbi
->iImage
= bi
.iImage
;
397 /*************************************************************************
398 * SHBrowseForFolderW [SHELL32.@]
400 LPITEMIDLIST WINAPI
SHBrowseForFolderW (LPBROWSEINFOW lpbi
)
402 TRACE("((%p->{lpszTitle=%s,owner=%p})\n", lpbi
,
403 lpbi
? debugstr_w(lpbi
->lpszTitle
) : NULL
, lpbi
? lpbi
->hwndOwner
: 0);
408 return (LPITEMIDLIST
) DialogBoxParamW(shell32_hInstance
,
409 swBrowseTempName
, lpbi
->hwndOwner
,
410 BrsFolderDlgProc
, (INT
)lpbi
);