[SHELL32] Implement Explorer background image (Retrial of #801) (#1463)
[reactos.git] / dll / win32 / shell32 / CDefView.cpp
1 /*
2 * ShellView
3 *
4 * Copyright 1998,1999 <juergen.schmied@debitel.net>
5 *
6 * This is the view visualizing the data provided by the shellfolder.
7 * No direct access to data from pidls should be done from here.
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 *
23 * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
24 */
25
26 /*
27 TODO:
28 - Load/Save the view state from/into the stream provided by the ShellBrowser.
29 - When editing starts on item, set edit text to for editing value.
30 - Fix shell view to handle view mode popup exec.
31 - The background context menu should have a pidl just like foreground menus. This
32 causes crashes when dynamic handlers try to use the NULL pidl.
33 - Reorder of columns doesn't work - might be bug in comctl32
34 */
35
36 #include "precomp.h"
37
38 #include <atlwin.h>
39 #include <rosctrls.h>
40
41 WINE_DEFAULT_DEBUG_CHANNEL(shell);
42
43 #undef SV_CLASS_NAME
44
45 static const WCHAR SV_CLASS_NAME[] = {'S', 'H', 'E', 'L', 'L', 'D', 'L', 'L', '_', 'D', 'e', 'f', 'V', 'i', 'e', 'w', 0};
46
47 typedef struct
48 {
49 BOOL bIsAscending;
50 INT nHeaderID;
51 INT nLastHeaderID;
52 } LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;
53
54 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
55
56 /* For the context menu of the def view, the id of the items are based on 1 because we need
57 to call TrackPopupMenu and let it use the 0 value as an indication that the menu was canceled */
58 #define CONTEXT_MENU_BASE_ID 1
59
60 class CDefView :
61 public CWindowImpl<CDefView, CWindow, CControlWinTraits>,
62 public CComObjectRootEx<CComMultiThreadModelNoCS>,
63 public IShellView2,
64 public IFolderView,
65 public IShellFolderView,
66 public IOleCommandTarget,
67 public IDropTarget,
68 public IDropSource,
69 public IViewObject,
70 public IServiceProvider
71 {
72 private:
73 CComPtr<IShellFolder> m_pSFParent;
74 CComPtr<IShellFolder2> m_pSF2Parent;
75 CComPtr<IShellFolderViewCB> m_pShellFolderViewCB;
76 CComPtr<IShellBrowser> m_pShellBrowser;
77 CComPtr<ICommDlgBrowser> m_pCommDlgBrowser;
78 CComPtr<IShellFolderViewDual> m_pShellFolderViewDual;
79 CListView m_ListView;
80 HWND m_hWndParent;
81 FOLDERSETTINGS m_FolderSettings;
82 HMENU m_hMenu; /* Handle to the menu bar of the browser */
83 HMENU m_hMenuArrangeModes; /* Handle to the popup menu with the arrange modes */
84 HMENU m_hMenuViewModes; /* Handle to the popup menu with the view modes */
85 HMENU m_hContextMenu; /* Handle to the open context menu */
86 BOOL m_bmenuBarInitialized;
87 UINT m_uState;
88 UINT m_cidl;
89 PCUITEMID_CHILD *m_apidl;
90 PIDLIST_ABSOLUTE m_pidlParent;
91 LISTVIEW_SORT_INFO m_sortInfo;
92 ULONG m_hNotify; /* Change notification handle */
93 HACCEL m_hAccel;
94 DWORD m_dwAspects;
95 DWORD m_dwAdvf;
96 CComPtr<IAdviseSink> m_pAdvSink;
97 // for drag and drop
98 CComPtr<IDataObject> m_pSourceDataObject;
99 CComPtr<IDropTarget> m_pCurDropTarget; /* The sub-item, which is currently dragged over */
100 CComPtr<IDataObject> m_pCurDataObject; /* The dragged data-object */
101 LONG m_iDragOverItem; /* Dragged over item's index, iff m_pCurDropTarget != NULL */
102 UINT m_cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
103 POINT m_ptLastMousePos; /* Mouse position at last DragOver call */
104 POINT m_ptFirstMousePos; /* Mouse position when the drag operation started */
105 DWORD m_grfKeyState;
106 //
107 CComPtr<IContextMenu> m_pCM;
108
109 BOOL m_isEditing;
110
111 CLSID m_Category;
112 BOOL m_Destroyed;
113 SFVM_CUSTOMVIEWINFO_DATA m_viewinfo_data;
114
115 private:
116 HRESULT _MergeToolbar();
117 BOOL _Sort();
118 HRESULT _DoFolderViewCB(UINT uMsg, WPARAM wParam, LPARAM lParam);
119
120 public:
121 CDefView();
122 ~CDefView();
123 HRESULT WINAPI Initialize(IShellFolder *shellFolder);
124 HRESULT IncludeObject(PCUITEMID_CHILD pidl);
125 HRESULT OnDefaultCommand();
126 HRESULT OnStateChange(UINT uFlags);
127 void UpdateStatusbar();
128 void CheckToolbar();
129 BOOL CreateList();
130 void UpdateListColors();
131 BOOL InitList();
132 HRESULT DefMessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam);
133 static INT CALLBACK ListViewCompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData);
134
135 PCUITEMID_CHILD _PidlByItem(int i);
136 PCUITEMID_CHILD _PidlByItem(LVITEM& lvItem);
137 int LV_FindItemByPidl(PCUITEMID_CHILD pidl);
138 BOOLEAN LV_AddItem(PCUITEMID_CHILD pidl);
139 BOOLEAN LV_DeleteItem(PCUITEMID_CHILD pidl);
140 BOOLEAN LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew);
141 BOOLEAN LV_ProdItem(PCUITEMID_CHILD pidl);
142 static INT CALLBACK fill_list(LPVOID ptr, LPVOID arg);
143 HRESULT FillList();
144 HRESULT FillFileMenu();
145 HRESULT FillEditMenu();
146 HRESULT FillViewMenu();
147 HRESULT FillArrangeAsMenu(HMENU hmenuArrange);
148 HRESULT CheckViewMode(HMENU hmenuView);
149 UINT GetSelections();
150 HRESULT OpenSelectedItems();
151 void OnDeactivate();
152 void DoActivate(UINT uState);
153 HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
154 HRESULT InvokeContextMenuCommand(UINT uCommand);
155 LRESULT OnExplorerCommand(UINT uCommand, BOOL bUseSelection);
156
157 // *** IOleWindow methods ***
158 virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd);
159 virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
160
161 // *** IShellView methods ***
162 virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(MSG *pmsg);
163 virtual HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable);
164 virtual HRESULT STDMETHODCALLTYPE UIActivate(UINT uState);
165 virtual HRESULT STDMETHODCALLTYPE Refresh();
166 virtual HRESULT STDMETHODCALLTYPE CreateViewWindow(IShellView *psvPrevious, LPCFOLDERSETTINGS pfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd);
167 virtual HRESULT STDMETHODCALLTYPE DestroyViewWindow();
168 virtual HRESULT STDMETHODCALLTYPE GetCurrentInfo(LPFOLDERSETTINGS pfs);
169 virtual HRESULT STDMETHODCALLTYPE AddPropertySheetPages(DWORD dwReserved, LPFNSVADDPROPSHEETPAGE pfn, LPARAM lparam);
170 virtual HRESULT STDMETHODCALLTYPE SaveViewState();
171 virtual HRESULT STDMETHODCALLTYPE SelectItem(PCUITEMID_CHILD pidlItem, SVSIF uFlags);
172 virtual HRESULT STDMETHODCALLTYPE GetItemObject(UINT uItem, REFIID riid, void **ppv);
173
174 // *** IShellView2 methods ***
175 virtual HRESULT STDMETHODCALLTYPE GetView(SHELLVIEWID *view_guid, ULONG view_type);
176 virtual HRESULT STDMETHODCALLTYPE CreateViewWindow2(LPSV2CVW2_PARAMS view_params);
177 virtual HRESULT STDMETHODCALLTYPE HandleRename(LPCITEMIDLIST new_pidl);
178 virtual HRESULT STDMETHODCALLTYPE SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point);
179
180 // *** IShellView3 methods ***
181 virtual HRESULT STDMETHODCALLTYPE CreateViewWindow3(IShellBrowser *psb, IShellView *psvPrevious, SV3CVW3_FLAGS view_flags, FOLDERFLAGS mask, FOLDERFLAGS flags, FOLDERVIEWMODE mode, const SHELLVIEWID *view_id, RECT *prcView, HWND *hwnd);
182
183 // *** IFolderView methods ***
184 virtual HRESULT STDMETHODCALLTYPE GetCurrentViewMode(UINT *pViewMode);
185 virtual HRESULT STDMETHODCALLTYPE SetCurrentViewMode(UINT ViewMode);
186 virtual HRESULT STDMETHODCALLTYPE GetFolder(REFIID riid, void **ppv);
187 virtual HRESULT STDMETHODCALLTYPE Item(int iItemIndex, PITEMID_CHILD *ppidl);
188 virtual HRESULT STDMETHODCALLTYPE ItemCount(UINT uFlags, int *pcItems);
189 virtual HRESULT STDMETHODCALLTYPE Items(UINT uFlags, REFIID riid, void **ppv);
190 virtual HRESULT STDMETHODCALLTYPE GetSelectionMarkedItem(int *piItem);
191 virtual HRESULT STDMETHODCALLTYPE GetFocusedItem(int *piItem);
192 virtual HRESULT STDMETHODCALLTYPE GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt);
193 virtual HRESULT STDMETHODCALLTYPE GetSpacing(POINT *ppt);
194 virtual HRESULT STDMETHODCALLTYPE GetDefaultSpacing(POINT *ppt);
195 virtual HRESULT STDMETHODCALLTYPE GetAutoArrange();
196 virtual HRESULT STDMETHODCALLTYPE SelectItem(int iItem, DWORD dwFlags);
197 virtual HRESULT STDMETHODCALLTYPE SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags);
198
199 // *** IShellFolderView methods ***
200 virtual HRESULT STDMETHODCALLTYPE Rearrange(LPARAM sort);
201 virtual HRESULT STDMETHODCALLTYPE GetArrangeParam(LPARAM *sort);
202 virtual HRESULT STDMETHODCALLTYPE ArrangeGrid();
203 virtual HRESULT STDMETHODCALLTYPE AutoArrange();
204 virtual HRESULT STDMETHODCALLTYPE AddObject(PITEMID_CHILD pidl, UINT *item);
205 virtual HRESULT STDMETHODCALLTYPE GetObject(PITEMID_CHILD *pidl, UINT item);
206 virtual HRESULT STDMETHODCALLTYPE RemoveObject(PITEMID_CHILD pidl, UINT *item);
207 virtual HRESULT STDMETHODCALLTYPE GetObjectCount(UINT *count);
208 virtual HRESULT STDMETHODCALLTYPE SetObjectCount(UINT count, UINT flags);
209 virtual HRESULT STDMETHODCALLTYPE UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item);
210 virtual HRESULT STDMETHODCALLTYPE RefreshObject(PITEMID_CHILD pidl, UINT *item);
211 virtual HRESULT STDMETHODCALLTYPE SetRedraw(BOOL redraw);
212 virtual HRESULT STDMETHODCALLTYPE GetSelectedCount(UINT *count);
213 virtual HRESULT STDMETHODCALLTYPE GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items);
214 virtual HRESULT STDMETHODCALLTYPE IsDropOnSource(IDropTarget *drop_target);
215 virtual HRESULT STDMETHODCALLTYPE GetDragPoint(POINT *pt);
216 virtual HRESULT STDMETHODCALLTYPE GetDropPoint(POINT *pt);
217 virtual HRESULT STDMETHODCALLTYPE MoveIcons(IDataObject *obj);
218 virtual HRESULT STDMETHODCALLTYPE SetItemPos(PCUITEMID_CHILD pidl, POINT *pt);
219 virtual HRESULT STDMETHODCALLTYPE IsBkDropTarget(IDropTarget *drop_target);
220 virtual HRESULT STDMETHODCALLTYPE SetClipboard(BOOL move);
221 virtual HRESULT STDMETHODCALLTYPE SetPoints(IDataObject *obj);
222 virtual HRESULT STDMETHODCALLTYPE GetItemSpacing(ITEMSPACING *spacing);
223 virtual HRESULT STDMETHODCALLTYPE SetCallback(IShellFolderViewCB *new_cb, IShellFolderViewCB **old_cb);
224 virtual HRESULT STDMETHODCALLTYPE Select(UINT flags);
225 virtual HRESULT STDMETHODCALLTYPE QuerySupport(UINT *support);
226 virtual HRESULT STDMETHODCALLTYPE SetAutomationObject(IDispatch *disp);
227
228 // *** IOleCommandTarget methods ***
229 virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText);
230 virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
231
232 // *** IDropTarget methods ***
233 virtual HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
234 virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
235 virtual HRESULT STDMETHODCALLTYPE DragLeave();
236 virtual HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
237
238 // *** IDropSource methods ***
239 virtual HRESULT STDMETHODCALLTYPE QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState);
240 virtual HRESULT STDMETHODCALLTYPE GiveFeedback(DWORD dwEffect);
241
242 // *** IViewObject methods ***
243 virtual HRESULT STDMETHODCALLTYPE Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd,
244 HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds,
245 BOOL ( STDMETHODCALLTYPE *pfnContinue )(ULONG_PTR dwContinue), ULONG_PTR dwContinue);
246 virtual HRESULT STDMETHODCALLTYPE GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect,
247 DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE **ppColorSet);
248 virtual HRESULT STDMETHODCALLTYPE Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze);
249 virtual HRESULT STDMETHODCALLTYPE Unfreeze(DWORD dwFreeze);
250 virtual HRESULT STDMETHODCALLTYPE SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink);
251 virtual HRESULT STDMETHODCALLTYPE GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink);
252
253 // *** IServiceProvider methods ***
254 virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
255
256 // Message handlers
257 LRESULT OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
258 LRESULT OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
259 LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
260 LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
261 LRESULT OnPrintClient(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
262 LRESULT OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
263 LRESULT OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
264 LRESULT OnNCCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
265 LRESULT OnNCDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
266 LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
267 LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
268 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
269 LRESULT OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
270 LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
271 LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
272 LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
273 LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
274 LRESULT OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
275 LRESULT OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
276 LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
277 LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
278
279 static ATL::CWndClassInfo& GetWndClassInfo()
280 {
281 static ATL::CWndClassInfo wc =
282 {
283 { sizeof(WNDCLASSEX), CS_PARENTDC, StartWindowProc,
284 0, 0, NULL, NULL,
285 LoadCursor(NULL, IDC_ARROW), NULL, NULL, SV_CLASS_NAME, NULL
286 },
287 NULL, NULL, IDC_ARROW, TRUE, 0, _T("")
288 };
289 return wc;
290 }
291
292 virtual WNDPROC GetWindowProc()
293 {
294 return WindowProc;
295 }
296
297 static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
298 {
299 CDefView *pThis;
300 LRESULT result;
301
302 // Must hold a reference during message handling
303 pThis = reinterpret_cast<CDefView *>(hWnd);
304 pThis->AddRef();
305 result = CWindowImpl<CDefView, CWindow, CControlWinTraits>::WindowProc(hWnd, uMsg, wParam, lParam);
306 pThis->Release();
307 return result;
308 }
309
310 BEGIN_MSG_MAP(CDefView)
311 MESSAGE_HANDLER(WM_SIZE, OnSize)
312 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
313 MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
314 MESSAGE_HANDLER(WM_NCCREATE, OnNCCreate)
315 MESSAGE_HANDLER(WM_NCDESTROY, OnNCDestroy)
316 MESSAGE_HANDLER(WM_CREATE, OnCreate)
317 MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
318 MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
319 MESSAGE_HANDLER(WM_COMMAND, OnCommand)
320 MESSAGE_HANDLER(SHV_CHANGE_NOTIFY, OnChangeNotify)
321 MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
322 MESSAGE_HANDLER(WM_DRAWITEM, OnCustomItem)
323 MESSAGE_HANDLER(WM_MEASUREITEM, OnCustomItem)
324 MESSAGE_HANDLER(WM_SHOWWINDOW, OnShowWindow)
325 MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode)
326 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
327 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
328 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPrintClient)
329 MESSAGE_HANDLER(WM_SYSCOLORCHANGE, OnSysColorChange)
330 MESSAGE_HANDLER(CWM_GETISHELLBROWSER, OnGetShellBrowser)
331 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange)
332 MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
333 END_MSG_MAP()
334
335 BEGIN_COM_MAP(CDefView)
336 // Windows returns E_NOINTERFACE for IOleWindow
337 // COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
338 COM_INTERFACE_ENTRY_IID(IID_IShellView, IShellView)
339 COM_INTERFACE_ENTRY_IID(IID_CDefView, IShellView)
340 COM_INTERFACE_ENTRY_IID(IID_IShellView2, IShellView2)
341 COM_INTERFACE_ENTRY_IID(IID_IFolderView, IFolderView)
342 COM_INTERFACE_ENTRY_IID(IID_IShellFolderView, IShellFolderView)
343 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
344 COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget)
345 COM_INTERFACE_ENTRY_IID(IID_IDropSource, IDropSource)
346 COM_INTERFACE_ENTRY_IID(IID_IViewObject, IViewObject)
347 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
348 END_COM_MAP()
349 };
350
351 /*menu items */
352 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
353 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
354 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
355
356 #define ID_LISTVIEW 1
357
358 /*windowsx.h */
359 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
360 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
361 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
362
363 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
364
365 CDefView::CDefView() :
366 m_ListView(),
367 m_hWndParent(NULL),
368 m_hMenu(NULL),
369 m_hMenuArrangeModes(NULL),
370 m_hMenuViewModes(NULL),
371 m_hContextMenu(NULL),
372 m_bmenuBarInitialized(FALSE),
373 m_uState(0),
374 m_cidl(0),
375 m_apidl(NULL),
376 m_pidlParent(NULL),
377 m_hNotify(0),
378 m_hAccel(NULL),
379 m_dwAspects(0),
380 m_dwAdvf(0),
381 m_iDragOverItem(0),
382 m_cScrollDelay(0),
383 m_isEditing(FALSE),
384 m_Destroyed(FALSE)
385 {
386 ZeroMemory(&m_FolderSettings, sizeof(m_FolderSettings));
387 ZeroMemory(&m_sortInfo, sizeof(m_sortInfo));
388 ZeroMemory(&m_ptLastMousePos, sizeof(m_ptLastMousePos));
389 ZeroMemory(&m_Category, sizeof(m_Category));
390 m_viewinfo_data.clrText = GetSysColor(COLOR_WINDOWTEXT);
391 m_viewinfo_data.clrTextBack = GetSysColor(COLOR_WINDOW);
392 m_viewinfo_data.hbmBack = NULL;
393 }
394
395 CDefView::~CDefView()
396 {
397 TRACE(" destroying IShellView(%p)\n", this);
398
399 if (m_viewinfo_data.hbmBack)
400 {
401 ::DeleteObject(m_viewinfo_data.hbmBack);
402 m_viewinfo_data.hbmBack = NULL;
403 }
404
405 if (m_hWnd)
406 {
407 DestroyViewWindow();
408 }
409
410 SHFree(m_apidl);
411 }
412
413 HRESULT WINAPI CDefView::Initialize(IShellFolder *shellFolder)
414 {
415 m_pSFParent = shellFolder;
416 shellFolder->QueryInterface(IID_PPV_ARG(IShellFolder2, &m_pSF2Parent));
417
418 return S_OK;
419 }
420
421 /**********************************************************
422 *
423 * ##### helperfunctions for communication with ICommDlgBrowser #####
424 */
425 HRESULT CDefView::IncludeObject(PCUITEMID_CHILD pidl)
426 {
427 HRESULT ret = S_OK;
428
429 if (m_pCommDlgBrowser.p != NULL)
430 {
431 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
432 ret = m_pCommDlgBrowser->IncludeObject(this, pidl);
433 TRACE("-- returns 0x%08x\n", ret);
434 }
435
436 return ret;
437 }
438
439 HRESULT CDefView::OnDefaultCommand()
440 {
441 HRESULT ret = S_FALSE;
442
443 if (m_pCommDlgBrowser.p != NULL)
444 {
445 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
446 ret = m_pCommDlgBrowser->OnDefaultCommand(this);
447 TRACE("-- returns 0x%08x\n", ret);
448 }
449
450 return ret;
451 }
452
453 HRESULT CDefView::OnStateChange(UINT uFlags)
454 {
455 HRESULT ret = S_FALSE;
456
457 if (m_pCommDlgBrowser.p != NULL)
458 {
459 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
460 ret = m_pCommDlgBrowser->OnStateChange(this, uFlags);
461 TRACE("--\n");
462 }
463
464 return ret;
465 }
466 /**********************************************************
467 * set the toolbar of the filedialog buttons
468 *
469 * - activates the buttons from the shellbrowser according to
470 * the view state
471 */
472 void CDefView::CheckToolbar()
473 {
474 LRESULT result;
475
476 TRACE("\n");
477
478 if (m_pCommDlgBrowser != NULL)
479 {
480 m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_CHECKBUTTON,
481 FCIDM_TB_SMALLICON, (m_FolderSettings.ViewMode == FVM_LIST) ? TRUE : FALSE, &result);
482 m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_CHECKBUTTON,
483 FCIDM_TB_REPORTVIEW, (m_FolderSettings.ViewMode == FVM_DETAILS) ? TRUE : FALSE, &result);
484 m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON,
485 FCIDM_TB_SMALLICON, TRUE, &result);
486 m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON,
487 FCIDM_TB_REPORTVIEW, TRUE, &result);
488 }
489 }
490
491 void CDefView::UpdateStatusbar()
492 {
493 WCHAR szFormat[MAX_PATH] = {0};
494 WCHAR szObjects[MAX_PATH] = {0};
495 UINT cSelectedItems;
496
497 cSelectedItems = m_ListView.GetSelectedCount();
498 if (cSelectedItems)
499 {
500 LoadStringW(shell32_hInstance, IDS_OBJECTS_SELECTED, szFormat, _countof(szFormat));
501 StringCchPrintfW(szObjects, MAX_PATH, szFormat, cSelectedItems);
502 }
503 else
504 {
505 LoadStringW(shell32_hInstance, IDS_OBJECTS, szFormat, _countof(szFormat));
506 StringCchPrintfW(szObjects, MAX_PATH, szFormat, m_ListView.GetItemCount());
507 }
508 m_pShellBrowser->SetStatusTextSB(szObjects);
509 }
510
511 /**********************************************************
512 *
513 * ##### helperfunctions for initializing the view #####
514 */
515
516 /**********************************************************
517 * ShellView_CreateList()
518 *
519 * - creates the list view window
520 */
521 BOOL CDefView::CreateList()
522 {
523 HRESULT hr;
524 DWORD dwStyle, dwExStyle;
525 UINT ViewMode;
526
527 TRACE("%p\n", this);
528
529 dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
530 LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_AUTOARRANGE;
531 dwExStyle = WS_EX_CLIENTEDGE;
532
533 if (m_FolderSettings.fFlags & FWF_DESKTOP)
534 dwStyle |= LVS_ALIGNLEFT;
535 else
536 dwStyle |= LVS_ALIGNTOP | LVS_SHOWSELALWAYS;
537
538 ViewMode = m_FolderSettings.ViewMode;
539 hr = _DoFolderViewCB(SFVM_DEFVIEWMODE, NULL, (LPARAM)&ViewMode);
540 if (SUCCEEDED(hr))
541 {
542 if (ViewMode >= FVM_FIRST && ViewMode <= FVM_LAST)
543 m_FolderSettings.ViewMode = ViewMode;
544 else
545 ERR("Ignoring invalid ViewMode from SFVM_DEFVIEWMODE: %u (was: %u)\n", ViewMode, m_FolderSettings.ViewMode);
546 }
547
548 switch (m_FolderSettings.ViewMode)
549 {
550 case FVM_ICON:
551 dwStyle |= LVS_ICON;
552 break;
553
554 case FVM_DETAILS:
555 dwStyle |= LVS_REPORT;
556 break;
557
558 case FVM_SMALLICON:
559 dwStyle |= LVS_SMALLICON;
560 break;
561
562 case FVM_LIST:
563 dwStyle |= LVS_LIST;
564 break;
565
566 default:
567 dwStyle |= LVS_LIST;
568 break;
569 }
570
571 if (m_FolderSettings.fFlags & FWF_AUTOARRANGE)
572 dwStyle |= LVS_AUTOARRANGE;
573
574 if (m_FolderSettings.fFlags & FWF_DESKTOP)
575 m_FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
576
577 if (m_FolderSettings.fFlags & FWF_SINGLESEL)
578 dwStyle |= LVS_SINGLESEL;
579
580 if (m_FolderSettings.fFlags & FWF_NOCLIENTEDGE)
581 dwExStyle &= ~WS_EX_CLIENTEDGE;
582
583 RECT rcListView = {0,0,0,0};
584 m_ListView.Create(m_hWnd, rcListView, L"FolderView", dwStyle, dwExStyle, ID_LISTVIEW);
585
586 if (!m_ListView)
587 return FALSE;
588
589 m_sortInfo.bIsAscending = TRUE;
590 m_sortInfo.nHeaderID = -1;
591 m_sortInfo.nLastHeaderID = -1;
592
593 /* UpdateShellSettings(); */
594 return TRUE;
595 }
596
597 void CDefView::UpdateListColors()
598 {
599 if (m_FolderSettings.fFlags & FWF_DESKTOP)
600 {
601 /* Check if drop shadows option is enabled */
602 BOOL bDropShadow = FALSE;
603 DWORD cbDropShadow = sizeof(bDropShadow);
604
605 /*
606 * The desktop ListView always take the default desktop colours, by
607 * remaining transparent and letting user32/win32k paint itself the
608 * desktop background color, if any.
609 */
610 m_ListView.SetBkColor(CLR_NONE);
611
612 SHGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
613 L"ListviewShadow", NULL, &bDropShadow, &cbDropShadow);
614 if (bDropShadow)
615 {
616 /* Set the icon background transparent */
617 m_ListView.SetTextBkColor(CLR_NONE);
618 m_ListView.SetTextColor(RGB(255, 255, 255));
619 m_ListView.SetExtendedListViewStyle(LVS_EX_TRANSPARENTSHADOWTEXT, LVS_EX_TRANSPARENTSHADOWTEXT);
620 }
621 else
622 {
623 /* Set the icon background as the same colour as the desktop */
624 COLORREF crDesktop = GetSysColor(COLOR_DESKTOP);
625 m_ListView.SetTextBkColor(crDesktop);
626 if (GetRValue(crDesktop) + GetGValue(crDesktop) + GetBValue(crDesktop) > 128 * 3)
627 m_ListView.SetTextColor(RGB(0, 0, 0));
628 else
629 m_ListView.SetTextColor(RGB(255, 255, 255));
630 m_ListView.SetExtendedListViewStyle(0, LVS_EX_TRANSPARENTSHADOWTEXT);
631 }
632 }
633 else
634 {
635 // text background color
636 COLORREF clrTextBack = GetSysColor(COLOR_WINDOW);
637 if (m_viewinfo_data.clrTextBack != CLR_INVALID)
638 {
639 clrTextBack = m_viewinfo_data.clrTextBack;
640 }
641 m_ListView.SetTextBkColor(clrTextBack);
642
643 // text color
644 COLORREF clrText = GetSysColor(COLOR_WINDOWTEXT);
645 if (m_viewinfo_data.clrText != CLR_INVALID)
646 {
647 clrText = m_viewinfo_data.clrText;
648 }
649 m_ListView.SetTextColor(clrText);
650
651 // Background is painted by the parent via WM_PRINTCLIENT.
652 m_ListView.SetExtendedListViewStyle(LVS_EX_TRANSPARENTBKGND, LVS_EX_TRANSPARENTBKGND);
653 }
654 }
655
656 /**********************************************************
657 * ShellView_InitList()
658 *
659 * - adds all needed columns to the shellview
660 */
661 BOOL CDefView::InitList()
662 {
663 SHELLDETAILS sd;
664 WCHAR szTemp[50];
665 HIMAGELIST big_icons, small_icons;
666
667 TRACE("%p\n", this);
668
669 m_ListView.DeleteAllItems();
670
671 m_hMenuArrangeModes = CreateMenu();
672
673 if (m_pSF2Parent)
674 {
675 for (int i = 0; 1; i++)
676 {
677 if (FAILED(m_pSF2Parent->GetDetailsOf(NULL, i, &sd)))
678 break;
679 StrRetToStrNW( szTemp, 50, &sd.str, NULL);
680 m_ListView.InsertColumn(i, szTemp, sd.fmt, sd.cxChar * 8);
681
682 InsertMenuW(m_hMenuArrangeModes, -1, MF_STRING, 0x30 + i, szTemp);
683 }
684
685 InsertMenuW(m_hMenuArrangeModes, -1, MF_BYPOSITION | MF_SEPARATOR, 0, 0);
686 }
687 else
688 {
689 FIXME("no m_pSF2Parent\n");
690 }
691
692 Shell_GetImageLists(&big_icons, &small_icons);
693 m_ListView.SetImageList(big_icons, LVSIL_NORMAL);
694 m_ListView.SetImageList(small_icons, LVSIL_SMALL);
695
696 return TRUE;
697 }
698
699 /*************************************************************************
700 * ShellView_ListViewCompareItems
701 *
702 * Compare Function for the Listview (FileOpen Dialog)
703 *
704 * PARAMS
705 * lParam1 [I] the first ItemIdList to compare with
706 * lParam2 [I] the second ItemIdList to compare with
707 * lpData [I] The column ID for the header Ctrl to process
708 *
709 * RETURNS
710 * A negative value if the first item should precede the second,
711 * a positive value if the first item should follow the second,
712 * or zero if the two items are equivalent
713 */
714 INT CALLBACK CDefView::ListViewCompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
715 {
716 PCUIDLIST_RELATIVE pidl1 = reinterpret_cast<PCUIDLIST_RELATIVE>(lParam1);
717 PCUIDLIST_RELATIVE pidl2 = reinterpret_cast<PCUIDLIST_RELATIVE>(lParam2);
718 CDefView *pThis = reinterpret_cast<CDefView*>(lpData);
719
720 HRESULT hres = pThis->m_pSFParent->CompareIDs(pThis->m_sortInfo.nHeaderID, pidl1, pidl2);
721 if (FAILED_UNEXPECTEDLY(hres))
722 return 0;
723
724 SHORT nDiff = HRESULT_CODE(hres);
725 if (!pThis->m_sortInfo.bIsAscending)
726 nDiff = -nDiff;
727 return nDiff;
728 }
729
730 BOOL CDefView::_Sort()
731 {
732 HWND hHeader;
733 HDITEM hColumn;
734
735 if (m_ListView.GetWindowLongPtr(GWL_STYLE) & LVS_NOSORTHEADER)
736 return TRUE;
737
738 hHeader = (HWND)m_ListView.SendMessage(LVM_GETHEADER, 0, 0);
739 ZeroMemory(&hColumn, sizeof(hColumn));
740
741 /* If the sorting column changed, remove the sorting style from the old column */
742 if ( (m_sortInfo.nLastHeaderID != -1) &&
743 (m_sortInfo.nLastHeaderID != m_sortInfo.nHeaderID) )
744 {
745 hColumn.mask = HDI_FORMAT;
746 Header_GetItem(hHeader, m_sortInfo.nLastHeaderID, &hColumn);
747 hColumn.fmt &= ~(HDF_SORTUP | HDF_SORTDOWN);
748 Header_SetItem(hHeader, m_sortInfo.nLastHeaderID, &hColumn);
749 }
750
751 /* Set the sorting style to the new column */
752 hColumn.mask = HDI_FORMAT;
753 Header_GetItem(hHeader, m_sortInfo.nHeaderID, &hColumn);
754
755 hColumn.fmt &= (m_sortInfo.bIsAscending ? ~HDF_SORTDOWN : ~HDF_SORTUP );
756 hColumn.fmt |= (m_sortInfo.bIsAscending ? HDF_SORTUP : HDF_SORTDOWN);
757 Header_SetItem(hHeader, m_sortInfo.nHeaderID, &hColumn);
758
759 /* Sort the list, using the current values of nHeaderID and bIsAscending */
760 m_sortInfo.nLastHeaderID = m_sortInfo.nHeaderID;
761 return m_ListView.SortItems(ListViewCompareItems, this);
762 }
763
764 PCUITEMID_CHILD CDefView::_PidlByItem(int i)
765 {
766 return reinterpret_cast<PCUITEMID_CHILD>(m_ListView.GetItemData(i));
767 }
768
769 PCUITEMID_CHILD CDefView::_PidlByItem(LVITEM& lvItem)
770 {
771 return reinterpret_cast<PCUITEMID_CHILD>(lvItem.lParam);
772 }
773
774 /**********************************************************
775 * LV_FindItemByPidl()
776 */
777 int CDefView::LV_FindItemByPidl(PCUITEMID_CHILD pidl)
778 {
779 int cItems = m_ListView.GetItemCount();
780
781 for (int i = 0; i<cItems; i++)
782 {
783 PCUITEMID_CHILD currentpidl = _PidlByItem(i);
784 HRESULT hr = m_pSFParent->CompareIDs(0, pidl, currentpidl);
785
786 if (SUCCEEDED(hr) && !HRESULT_CODE(hr))
787 {
788 return i;
789 }
790 }
791 return -1;
792 }
793
794 /**********************************************************
795 * LV_AddItem()
796 */
797 BOOLEAN CDefView::LV_AddItem(PCUITEMID_CHILD pidl)
798 {
799 LVITEMW lvItem;
800
801 TRACE("(%p)(pidl=%p)\n", this, pidl);
802
803 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/
804 lvItem.iItem = m_ListView.GetItemCount(); /*add the item to the end of the list*/
805 lvItem.iSubItem = 0;
806 lvItem.lParam = reinterpret_cast<LPARAM>(ILClone(pidl)); /*set the item's data*/
807 lvItem.pszText = LPSTR_TEXTCALLBACKW; /*get text on a callback basis*/
808 lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/
809 lvItem.stateMask = LVIS_CUT;
810
811 if (m_ListView.InsertItem(&lvItem) == -1)
812 return FALSE;
813 else
814 return TRUE;
815 }
816
817 /**********************************************************
818 * LV_DeleteItem()
819 */
820 BOOLEAN CDefView::LV_DeleteItem(PCUITEMID_CHILD pidl)
821 {
822 int nIndex;
823
824 TRACE("(%p)(pidl=%p)\n", this, pidl);
825
826 nIndex = LV_FindItemByPidl(pidl);
827
828 return (-1 == m_ListView.DeleteItem(nIndex)) ? FALSE : TRUE;
829 }
830
831 /**********************************************************
832 * LV_RenameItem()
833 */
834 BOOLEAN CDefView::LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew)
835 {
836 int nItem;
837 LVITEMW lvItem;
838
839 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", this, pidlOld, pidlNew);
840
841 nItem = LV_FindItemByPidl(pidlOld);
842
843 if ( -1 != nItem )
844 {
845 lvItem.mask = LVIF_PARAM; /* only the pidl */
846 lvItem.iItem = nItem;
847 lvItem.iSubItem = 0;
848 m_ListView.GetItem(&lvItem);
849
850 SHFree(reinterpret_cast<LPVOID>(lvItem.lParam));
851 lvItem.mask = LVIF_PARAM|LVIF_IMAGE;
852 lvItem.iItem = nItem;
853 lvItem.iSubItem = 0;
854 lvItem.lParam = reinterpret_cast<LPARAM>(ILClone(pidlNew)); /* set the item's data */
855 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0);
856 m_ListView.SetItem(&lvItem);
857 m_ListView.Update(nItem);
858 return TRUE; /* FIXME: better handling */
859 }
860
861 return FALSE;
862 }
863
864 /**********************************************************
865 * LV_ProdItem()
866 */
867 BOOLEAN CDefView::LV_ProdItem(PCUITEMID_CHILD pidl)
868 {
869 int nItem;
870 LVITEMW lvItem;
871
872 TRACE("(%p)(pidl=%p)\n", this, pidl);
873
874 nItem = LV_FindItemByPidl(pidl);
875
876 if (-1 != nItem)
877 {
878 lvItem.mask = LVIF_IMAGE;
879 lvItem.iItem = nItem;
880 lvItem.iSubItem = 0;
881 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
882 m_ListView.SetItem(&lvItem);
883 m_ListView.Update(nItem);
884 return TRUE;
885 }
886
887 return FALSE;
888 }
889
890 /**********************************************************
891 * ShellView_FillList()
892 *
893 * - gets the objectlist from the shellfolder
894 * - sorts the list
895 * - fills the list into the view
896 */
897 INT CALLBACK CDefView::fill_list(LPVOID ptr, LPVOID arg)
898 {
899 PITEMID_CHILD pidl = static_cast<PITEMID_CHILD>(ptr);
900 CDefView *pThis = static_cast<CDefView *>(arg);
901
902 /* in a commdlg This works as a filemask*/
903 if (pThis->IncludeObject(pidl) == S_OK)
904 pThis->LV_AddItem(pidl);
905
906 SHFree(pidl);
907 return TRUE;
908 }
909
910 HRESULT CDefView::FillList()
911 {
912 CComPtr<IEnumIDList> pEnumIDList;
913 PITEMID_CHILD pidl;
914 DWORD dwFetched;
915 HRESULT hRes;
916 HDPA hdpa;
917 HKEY hKey;
918 DWORD dFlags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS;
919
920 TRACE("%p\n", this);
921
922 /* determine if there is a setting to show all the hidden files/folders */
923 if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
924 {
925 DWORD dataLength, flagVal;
926
927 dataLength = sizeof(flagVal);
928 if (RegQueryValueExW(hKey, L"Hidden", NULL, NULL, (LPBYTE)&flagVal, &dataLength) == ERROR_SUCCESS)
929 {
930 /* if the value is 1, then show all hidden files/folders */
931 if (flagVal == 1)
932 {
933 dFlags |= SHCONTF_INCLUDEHIDDEN;
934 m_ListView.SendMessageW(LVM_SETCALLBACKMASK, LVIS_CUT, 0);
935 }
936 }
937
938 /* close the key */
939 RegCloseKey(hKey);
940 }
941
942 /* get the itemlist from the shfolder */
943 hRes = m_pSFParent->EnumObjects(m_hWnd, dFlags, &pEnumIDList);
944 if (hRes != S_OK)
945 {
946 if (hRes == S_FALSE)
947 return(NOERROR);
948 return(hRes);
949 }
950
951 /* create a pointer array */
952 hdpa = DPA_Create(16);
953 if (!hdpa)
954 {
955 return(E_OUTOFMEMORY);
956 }
957
958 /* copy the items into the array*/
959 while((S_OK == pEnumIDList->Next(1, &pidl, &dwFetched)) && dwFetched)
960 {
961 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
962 {
963 SHFree(pidl);
964 }
965 }
966
967 /*turn the listview's redrawing off*/
968 m_ListView.SetRedraw(FALSE);
969
970 DPA_DestroyCallback( hdpa, fill_list, this);
971
972 /* sort the array */
973 if (m_pSF2Parent)
974 {
975 m_pSF2Parent->GetDefaultColumn(NULL, (ULONG*)&m_sortInfo.nHeaderID, NULL);
976 }
977 else
978 {
979 FIXME("no m_pSF2Parent\n");
980 }
981 m_sortInfo.bIsAscending = TRUE;
982 _Sort();
983
984 if (m_viewinfo_data.hbmBack)
985 {
986 ::DeleteObject(m_viewinfo_data.hbmBack);
987 m_viewinfo_data.hbmBack = NULL;
988 }
989
990 // load custom background image and custom text color
991 m_viewinfo_data.cbSize = sizeof(m_viewinfo_data);
992 _DoFolderViewCB(SFVM_GET_CUSTOMVIEWINFO, 0, (LPARAM)&m_viewinfo_data);
993
994 /*turn the listview's redrawing back on and force it to draw*/
995 m_ListView.SetRedraw(TRUE);
996
997 UpdateListColors();
998
999 if (!(m_FolderSettings.fFlags & FWF_DESKTOP))
1000 {
1001 // redraw now
1002 m_ListView.InvalidateRect(NULL, TRUE);
1003 }
1004
1005 _DoFolderViewCB(SFVM_LISTREFRESHED, NULL, NULL);
1006
1007 return S_OK;
1008 }
1009
1010 LRESULT CDefView::OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1011 {
1012 m_ListView.UpdateWindow();
1013 bHandled = FALSE;
1014 return 0;
1015 }
1016
1017 LRESULT CDefView::OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1018 {
1019 return m_ListView.SendMessageW(uMsg, 0, 0);
1020 }
1021
1022 LRESULT CDefView::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1023 {
1024 if (!m_Destroyed)
1025 {
1026 m_Destroyed = TRUE;
1027 if (m_hMenu)
1028 {
1029 DestroyMenu(m_hMenu);
1030 m_hMenu = NULL;
1031 }
1032 RevokeDragDrop(m_hWnd);
1033 SHChangeNotifyDeregister(m_hNotify);
1034 m_hNotify = NULL;
1035 SHFree(m_pidlParent);
1036 m_pidlParent = NULL;
1037 }
1038 bHandled = FALSE;
1039 return 0;
1040 }
1041
1042 LRESULT CDefView::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1043 {
1044 /* redirect to parent */
1045 if (m_FolderSettings.fFlags & (FWF_DESKTOP | FWF_TRANSPARENT))
1046 return SendMessageW(GetParent(), WM_ERASEBKGND, wParam, lParam);
1047
1048 bHandled = FALSE;
1049 return 0;
1050 }
1051
1052 static VOID
1053 DrawTileBitmap(HDC hDC, LPCRECT prc, HBITMAP hbm, INT nWidth, INT nHeight, INT dx, INT dy)
1054 {
1055 INT x0 = prc->left, y0 = prc->top, x1 = prc->right, y1 = prc->bottom;
1056 x0 += dx;
1057 y0 += dy;
1058
1059 HDC hMemDC = CreateCompatibleDC(hDC);
1060 HGDIOBJ hbmOld = SelectObject(hMemDC, hbm);
1061
1062 for (INT y = y0; y < y1; y += nHeight)
1063 {
1064 for (INT x = x0; x < x1; x += nWidth)
1065 {
1066 BitBlt(hDC, x, y, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY);
1067 }
1068 }
1069
1070 SelectObject(hMemDC, hbmOld);
1071 DeleteDC(hMemDC);
1072 }
1073
1074 LRESULT CDefView::OnPrintClient(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1075 {
1076 HDC hDC = (HDC)wParam;
1077
1078 RECT rc;
1079 ::GetClientRect(m_ListView, &rc);
1080
1081 if (m_viewinfo_data.hbmBack)
1082 {
1083 BITMAP bm;
1084 if (::GetObject(m_viewinfo_data.hbmBack, sizeof(BITMAP), &bm))
1085 {
1086 INT dx = -(::GetScrollPos(m_ListView, SB_HORZ) % bm.bmWidth);
1087 INT dy = -(::GetScrollPos(m_ListView, SB_VERT) % bm.bmHeight);
1088 DrawTileBitmap(hDC, &rc, m_viewinfo_data.hbmBack, bm.bmWidth, bm.bmHeight, dx, dy);
1089 }
1090 }
1091 else
1092 {
1093 FillRect(hDC, &rc, GetSysColorBrush(COLOR_WINDOW));
1094 }
1095
1096 bHandled = TRUE;
1097
1098 return TRUE;
1099 }
1100
1101 LRESULT CDefView::OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1102 {
1103 /* Update desktop labels color */
1104 UpdateListColors();
1105
1106 /* Forward WM_SYSCOLORCHANGE to common controls */
1107 return m_ListView.SendMessageW(uMsg, 0, 0);
1108 }
1109
1110 LRESULT CDefView::OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1111 {
1112 return reinterpret_cast<LRESULT>(m_pShellBrowser.p);
1113 }
1114
1115 LRESULT CDefView::OnNCCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1116 {
1117 this->AddRef();
1118 bHandled = FALSE;
1119 return 0;
1120 }
1121
1122 LRESULT CDefView::OnNCDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1123 {
1124 this->Release();
1125 bHandled = FALSE;
1126 return 0;
1127 }
1128
1129 /**********************************************************
1130 * ShellView_OnCreate()
1131 */
1132 LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1133 {
1134 CComPtr<IDropTarget> pdt;
1135 SHChangeNotifyEntry ntreg;
1136 CComPtr<IPersistFolder2> ppf2;
1137
1138 TRACE("%p\n", this);
1139
1140 if (SUCCEEDED(QueryInterface(IID_PPV_ARG(IDropTarget, &pdt))))
1141 {
1142 if (FAILED(RegisterDragDrop(m_hWnd, pdt)))
1143 ERR("Registering Drag Drop Failed");
1144 }
1145
1146 /* register for receiving notifications */
1147 m_pSFParent->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
1148 if (ppf2)
1149 {
1150 ppf2->GetCurFolder(&m_pidlParent);
1151 ntreg.fRecursive = TRUE;
1152 ntreg.pidl = m_pidlParent;
1153 m_hNotify = SHChangeNotifyRegister(m_hWnd, SHCNRF_InterruptLevel | SHCNRF_ShellLevel, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
1154 }
1155
1156 if (CreateList())
1157 {
1158 if (InitList())
1159 {
1160 FillList();
1161 }
1162 }
1163
1164 /* _DoFolderViewCB(SFVM_GETNOTIFY, ?? ??) */
1165
1166 m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_SHELLVIEW));
1167
1168 UpdateStatusbar();
1169
1170 return S_OK;
1171 }
1172
1173 /**********************************************************
1174 * #### Handling of the menus ####
1175 */
1176
1177 extern "C" DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID);
1178
1179 HMENU GetSubmenuByID(HMENU hmenu, UINT id)
1180 {
1181 MENUITEMINFOW mii = {sizeof(mii), MIIM_SUBMENU};
1182 if (::GetMenuItemInfoW(hmenu, id, FALSE, &mii))
1183 return mii.hSubMenu;
1184
1185 return NULL;
1186 }
1187
1188 /* ReallyGetMenuItemID returns the id of an item even if it opens a submenu,
1189 GetMenuItemID returns -1 if the specified item opens a submenu */
1190 UINT ReallyGetMenuItemID(HMENU hmenu, int i)
1191 {
1192 MENUITEMINFOW mii = {sizeof(mii), MIIM_ID};
1193 if (::GetMenuItemInfoW(hmenu, i, TRUE, &mii))
1194 return mii.wID;
1195
1196 return UINT_MAX;
1197 }
1198
1199 HRESULT CDefView::FillFileMenu()
1200 {
1201 HMENU hFileMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_FILE);
1202 if (!hFileMenu)
1203 return E_FAIL;
1204
1205 /* Cleanup the items added previously */
1206 for (int i = GetMenuItemCount(hFileMenu) - 1; i >= 0; i--)
1207 {
1208 UINT id = GetMenuItemID(hFileMenu, i);
1209 if (id < FCIDM_BROWSERFIRST || id > FCIDM_BROWSERLAST)
1210 DeleteMenu(hFileMenu, i, MF_BYPOSITION);
1211 }
1212
1213 /* Store the context menu in m_pCM and keep it in order to invoke the selected command later on */
1214 HRESULT hr = GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IContextMenu, &m_pCM));
1215 if (FAILED_UNEXPECTEDLY(hr))
1216 return hr;
1217
1218 HMENU hmenu = CreatePopupMenu();
1219
1220 hr = m_pCM->QueryContextMenu(hmenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1221 if (FAILED_UNEXPECTEDLY(hr))
1222 return hr;
1223
1224 // TODO: filter or something
1225
1226 Shell_MergeMenus(hFileMenu, hmenu, 0, 0, 0xFFFF, MM_ADDSEPARATOR | MM_SUBMENUSHAVEIDS);
1227
1228 ::DestroyMenu(hmenu);
1229
1230 return S_OK;
1231 }
1232
1233 HRESULT CDefView::FillEditMenu()
1234 {
1235 HMENU hEditMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_EDIT);
1236 if (!hEditMenu)
1237 return E_FAIL;
1238
1239 HMENU hmenuContents = ::LoadMenuW(shell32_hInstance, L"MENU_003");
1240 if (!hmenuContents)
1241 return E_FAIL;
1242
1243 Shell_MergeMenus(hEditMenu, hmenuContents, 0, 0, 0xFFFF, 0);
1244
1245 ::DestroyMenu(hmenuContents);
1246
1247 return S_OK;
1248 }
1249
1250 HRESULT CDefView::FillViewMenu()
1251 {
1252 HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW);
1253 if (!hViewMenu)
1254 return E_FAIL;
1255
1256 m_hMenuViewModes = ::LoadMenuW(shell32_hInstance, L"MENU_001");
1257 if (!m_hMenuViewModes)
1258 return E_FAIL;
1259
1260 UINT i = SHMenuIndexFromID(hViewMenu, FCIDM_MENU_VIEW_SEP_OPTIONS);
1261 Shell_MergeMenus(hViewMenu, m_hMenuViewModes, i, 0, 0xFFFF, MM_ADDSEPARATOR | MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS);
1262
1263 return S_OK;
1264 }
1265
1266 HRESULT CDefView::FillArrangeAsMenu(HMENU hmenuArrange)
1267 {
1268 /* We only need to fill this once */
1269 if (GetMenuItemID(hmenuArrange, 0) == FCIDM_SHVIEW_AUTOARRANGE)
1270 {
1271 Shell_MergeMenus(hmenuArrange, m_hMenuArrangeModes, 0, 0, 0xFFFF,0);
1272 }
1273
1274 /* Also check the menu item according to which we sort */
1275 CheckMenuRadioItem(hmenuArrange,
1276 0x30,
1277 0x100,
1278 m_sortInfo.nHeaderID + 0x30,
1279 MF_BYCOMMAND);
1280
1281 if (m_FolderSettings.ViewMode == FVM_DETAILS || m_FolderSettings.ViewMode == FVM_LIST)
1282 {
1283 EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_BYCOMMAND | MF_GRAYED);
1284 }
1285 else
1286 {
1287 EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_BYCOMMAND);
1288
1289 if (GetAutoArrange() == S_OK)
1290 CheckMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_CHECKED);
1291 }
1292
1293
1294 return S_OK;
1295 }
1296
1297 HRESULT CDefView::CheckViewMode(HMENU hmenuView)
1298 {
1299 if (m_FolderSettings.ViewMode >= FVM_FIRST && m_FolderSettings.ViewMode <= FVM_LAST)
1300 {
1301 UINT iItemFirst = FCIDM_SHVIEW_BIGICON;
1302 UINT iItemLast = iItemFirst + FVM_LAST - FVM_FIRST;
1303 UINT iItem = iItemFirst + m_FolderSettings.ViewMode - FVM_FIRST;
1304 CheckMenuRadioItem(hmenuView, iItemFirst, iItemLast, iItem, MF_BYCOMMAND);
1305 }
1306
1307 return S_OK;
1308 }
1309
1310 /**********************************************************
1311 * ShellView_GetSelections()
1312 *
1313 * - fills the m_apidl list with the selected objects
1314 *
1315 * RETURNS
1316 * number of selected items
1317 */
1318 UINT CDefView::GetSelections()
1319 {
1320 SHFree(m_apidl);
1321
1322 m_cidl = m_ListView.GetSelectedCount();
1323 m_apidl = static_cast<PCUITEMID_CHILD*>(SHAlloc(m_cidl * sizeof(PCUITEMID_CHILD)));
1324 if (!m_apidl)
1325 {
1326 m_cidl = 0;
1327 return 0;
1328 }
1329
1330 TRACE("-- Items selected =%u\n", m_cidl);
1331
1332 UINT i = 0;
1333 int lvIndex = -1;
1334 while ((lvIndex = m_ListView.GetNextItem(lvIndex, LVNI_SELECTED)) > -1)
1335 {
1336 m_apidl[i] = _PidlByItem(lvIndex);
1337 i++;
1338 if (i == m_cidl)
1339 break;
1340 TRACE("-- selected Item found\n");
1341 }
1342
1343 return m_cidl;
1344 }
1345
1346 HRESULT CDefView::InvokeContextMenuCommand(UINT uCommand)
1347 {
1348 CMINVOKECOMMANDINFO cmi;
1349
1350 ZeroMemory(&cmi, sizeof(cmi));
1351 cmi.cbSize = sizeof(cmi);
1352 cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1353 cmi.hwnd = m_hWnd;
1354
1355 if (GetKeyState(VK_SHIFT) & 0x8000)
1356 cmi.fMask |= CMIC_MASK_SHIFT_DOWN;
1357
1358 if (GetKeyState(VK_CONTROL) & 0x8000)
1359 cmi.fMask |= CMIC_MASK_CONTROL_DOWN;
1360
1361 HRESULT hr = m_pCM->InvokeCommand(&cmi);
1362 if (FAILED_UNEXPECTEDLY(hr))
1363 return hr;
1364
1365 return S_OK;
1366 }
1367
1368 /**********************************************************
1369 * ShellView_OpenSelectedItems()
1370 */
1371 HRESULT CDefView::OpenSelectedItems()
1372 {
1373 HMENU hMenu;
1374 UINT uCommand;
1375 HRESULT hResult;
1376
1377 m_cidl = m_ListView.GetSelectedCount();
1378 if (m_cidl == 0)
1379 return S_OK;
1380
1381 hResult = OnDefaultCommand();
1382 if (hResult == S_OK)
1383 return hResult;
1384
1385 hMenu = CreatePopupMenu();
1386 if (!hMenu)
1387 return E_FAIL;
1388
1389 hResult = GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IContextMenu, &m_pCM));
1390 if (FAILED_UNEXPECTEDLY(hResult))
1391 goto cleanup;
1392
1393 hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_DEFAULTONLY);
1394 if (FAILED_UNEXPECTEDLY(hResult))
1395 goto cleanup;
1396
1397 uCommand = GetMenuDefaultItem(hMenu, FALSE, 0);
1398 if (uCommand == (UINT)-1)
1399 {
1400 hResult = E_FAIL;
1401 goto cleanup;
1402 }
1403
1404 InvokeContextMenuCommand(uCommand);
1405
1406 cleanup:
1407
1408 if (hMenu)
1409 DestroyMenu(hMenu);
1410
1411 if (m_pCM)
1412 {
1413 IUnknown_SetSite(m_pCM, NULL);
1414 m_pCM.Release();
1415 }
1416
1417 return hResult;
1418 }
1419
1420 /**********************************************************
1421 * ShellView_DoContextMenu()
1422 */
1423 LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1424 {
1425 int x, y;
1426 UINT uCommand;
1427 HRESULT hResult;
1428
1429 TRACE("(%p)\n", this);
1430
1431 m_hContextMenu = CreatePopupMenu();
1432 if (!m_hContextMenu)
1433 return E_FAIL;
1434
1435 m_cidl = m_ListView.GetSelectedCount();
1436
1437 hResult = GetItemObject( m_cidl ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
1438 if (FAILED_UNEXPECTEDLY(hResult))
1439 goto cleanup;
1440
1441 /* Use 1 as the first id as we want 0 the mean that the user canceled the menu */
1442 hResult = m_pCM->QueryContextMenu(m_hContextMenu, 0, CONTEXT_MENU_BASE_ID, FCIDM_SHVIEWLAST, CMF_NORMAL);
1443 if (FAILED_UNEXPECTEDLY(hResult))
1444 goto cleanup;
1445
1446 /* There is no position requested, so try to find one */
1447 if (lParam == ~0)
1448 {
1449 int lvIndex;
1450 POINT pt;
1451
1452 /* Do we have a focused item, */
1453 if ((lvIndex = m_ListView.GetNextItem(-1, LVIS_FOCUSED)) < 0)
1454 {
1455 /* or a selected item? */
1456 lvIndex = m_ListView.GetNextItem(-1, LVIS_SELECTED);
1457 }
1458 /* We got something */
1459 if (lvIndex > -1)
1460 {
1461 /* Let's find the center of the icon */
1462 RECT rc = { LVIR_ICON };
1463 m_ListView.SendMessage(LVM_GETITEMRECT, lvIndex, (LPARAM)&rc);
1464 pt.x = (rc.right + rc.left) / 2;
1465 pt.y = (rc.bottom + rc.top) / 2;
1466 }
1467 else
1468 {
1469 /* We have to drop it somewhere.. */
1470 pt.x = pt.y = 0;
1471 }
1472
1473 m_ListView.ClientToScreen(&pt);
1474 x = pt.x;
1475 y = pt.y;
1476 }
1477 else
1478 {
1479 x = GET_X_LPARAM(lParam);
1480 y = GET_Y_LPARAM(lParam);
1481 }
1482
1483 uCommand = TrackPopupMenu(m_hContextMenu,
1484 TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
1485 x, y, 0, m_hWnd, NULL);
1486 if (uCommand == 0)
1487 goto cleanup;
1488
1489 if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK)
1490 goto cleanup;
1491
1492 InvokeContextMenuCommand(uCommand - CONTEXT_MENU_BASE_ID);
1493
1494 cleanup:
1495 if (m_pCM)
1496 {
1497 IUnknown_SetSite(m_pCM, NULL);
1498 m_pCM.Release();
1499 }
1500
1501 if (m_hContextMenu)
1502 {
1503 DestroyMenu(m_hContextMenu);
1504 m_hContextMenu = NULL;
1505 }
1506
1507 return 0;
1508 }
1509
1510 LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
1511 {
1512 HRESULT hResult;
1513 HMENU hMenu;
1514
1515 hMenu = CreatePopupMenu();
1516 if (!hMenu)
1517 return 0;
1518
1519 hResult = GetItemObject( bUseSelection ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
1520 if (FAILED_UNEXPECTEDLY( hResult))
1521 goto cleanup;
1522
1523 hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
1524 if (FAILED_UNEXPECTEDLY( hResult))
1525 goto cleanup;
1526
1527 InvokeContextMenuCommand(uCommand);
1528
1529 cleanup:
1530 if (m_pCM)
1531 {
1532 IUnknown_SetSite(m_pCM, NULL);
1533 m_pCM.Release();
1534 }
1535
1536 if (hMenu)
1537 DestroyMenu(hMenu);
1538
1539 return 0;
1540 }
1541
1542 /**********************************************************
1543 * ##### message handling #####
1544 */
1545
1546 /**********************************************************
1547 * ShellView_OnSize()
1548 */
1549 LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1550 {
1551 WORD wWidth, wHeight;
1552
1553 wWidth = LOWORD(lParam);
1554 wHeight = HIWORD(lParam);
1555
1556 TRACE("%p width=%u height=%u\n", this, wWidth, wHeight);
1557
1558 /* Resize the ListView to fit our window */
1559 if (m_ListView)
1560 {
1561 ::MoveWindow(m_ListView, 0, 0, wWidth, wHeight, TRUE);
1562 }
1563
1564 _DoFolderViewCB(SFVM_SIZE, 0, 0);
1565
1566 return 0;
1567 }
1568
1569 /**********************************************************
1570 * ShellView_OnDeactivate()
1571 *
1572 * NOTES
1573 * internal
1574 */
1575 void CDefView::OnDeactivate()
1576 {
1577 TRACE("%p\n", this);
1578
1579 if (m_uState != SVUIA_DEACTIVATE)
1580 {
1581 // TODO: cleanup menu after deactivation
1582
1583 m_uState = SVUIA_DEACTIVATE;
1584 }
1585 }
1586
1587 void CDefView::DoActivate(UINT uState)
1588 {
1589 TRACE("%p uState=%x\n", this, uState);
1590
1591 /*don't do anything if the state isn't really changing */
1592 if (m_uState == uState)
1593 {
1594 return;
1595 }
1596
1597 if (uState == SVUIA_DEACTIVATE)
1598 {
1599 OnDeactivate();
1600 }
1601 else
1602 {
1603 if(m_hMenu && !m_bmenuBarInitialized)
1604 {
1605 FillEditMenu();
1606 FillViewMenu();
1607 m_pShellBrowser->SetMenuSB(m_hMenu, 0, m_hWnd);
1608 m_bmenuBarInitialized = TRUE;
1609 }
1610
1611 if (SVUIA_ACTIVATE_FOCUS == uState)
1612 {
1613 m_ListView.SetFocus();
1614 }
1615 }
1616
1617 m_uState = uState;
1618 TRACE("--\n");
1619 }
1620
1621 /**********************************************************
1622 * ShellView_OnActivate()
1623 */
1624 LRESULT CDefView::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1625 {
1626 DoActivate(SVUIA_ACTIVATE_FOCUS);
1627 return 0;
1628 }
1629
1630 /**********************************************************
1631 * ShellView_OnSetFocus()
1632 *
1633 */
1634 LRESULT CDefView::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1635 {
1636 TRACE("%p\n", this);
1637
1638 /* Tell the browser one of our windows has received the focus. This
1639 should always be done before merging menus (OnActivate merges the
1640 menus) if one of our windows has the focus.*/
1641
1642 m_pShellBrowser->OnViewWindowActive(this);
1643 DoActivate(SVUIA_ACTIVATE_FOCUS);
1644
1645 /* Set the focus to the listview */
1646 m_ListView.SetFocus();
1647
1648 /* Notify the ICommDlgBrowser interface */
1649 OnStateChange(CDBOSC_SETFOCUS);
1650
1651 return 0;
1652 }
1653
1654 /**********************************************************
1655 * ShellView_OnKillFocus()
1656 */
1657 LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1658 {
1659 TRACE("(%p) stub\n", this);
1660
1661 DoActivate(SVUIA_ACTIVATE_NOFOCUS);
1662 /* Notify the ICommDlgBrowser */
1663 OnStateChange(CDBOSC_KILLFOCUS);
1664
1665 return 0;
1666 }
1667
1668 /**********************************************************
1669 * ShellView_OnCommand()
1670 *
1671 * NOTES
1672 * the CmdID's are the ones from the context menu
1673 */
1674 LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1675 {
1676 DWORD dwCmdID;
1677 DWORD dwCmd;
1678 HWND hwndCmd;
1679 int nCount;
1680
1681 dwCmdID = GET_WM_COMMAND_ID(wParam, lParam);
1682 dwCmd = GET_WM_COMMAND_CMD(wParam, lParam);
1683 hwndCmd = GET_WM_COMMAND_HWND(wParam, lParam);
1684
1685 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n", this, dwCmdID, dwCmd, hwndCmd);
1686
1687 switch (dwCmdID)
1688 {
1689 case FCIDM_SHVIEW_SMALLICON:
1690 m_FolderSettings.ViewMode = FVM_SMALLICON;
1691 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON);
1692 CheckToolbar();
1693 break;
1694
1695 case FCIDM_SHVIEW_BIGICON:
1696 m_FolderSettings.ViewMode = FVM_ICON;
1697 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_ICON);
1698 CheckToolbar();
1699 break;
1700
1701 case FCIDM_SHVIEW_LISTVIEW:
1702 m_FolderSettings.ViewMode = FVM_LIST;
1703 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_LIST);
1704 CheckToolbar();
1705 break;
1706
1707 case FCIDM_SHVIEW_REPORTVIEW:
1708 m_FolderSettings.ViewMode = FVM_DETAILS;
1709 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_REPORT);
1710 CheckToolbar();
1711 break;
1712
1713 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1714 case 0x30:
1715 case 0x31:
1716 case 0x32:
1717 case 0x33:
1718 m_sortInfo.nHeaderID = dwCmdID - 0x30;
1719 m_sortInfo.bIsAscending = TRUE;
1720 _Sort();
1721 break;
1722
1723 case FCIDM_SHVIEW_SNAPTOGRID:
1724 //FIXME
1725 break;
1726 case FCIDM_SHVIEW_AUTOARRANGE:
1727 if (GetAutoArrange() == S_OK)
1728 m_ListView.ModifyStyle(LVS_AUTOARRANGE, 0);
1729 else
1730 AutoArrange();
1731 break;
1732 case FCIDM_SHVIEW_SELECTALL:
1733 m_ListView.SetItemState(-1, LVIS_SELECTED, LVIS_SELECTED);
1734 break;
1735
1736 case FCIDM_SHVIEW_INVERTSELECTION:
1737 nCount = m_ListView.GetItemCount();
1738 for (int i=0; i < nCount; i++)
1739 m_ListView.SetItemState(i, m_ListView.GetItemState(i, LVIS_SELECTED) ? 0 : LVIS_SELECTED, LVIS_SELECTED);
1740 break;
1741
1742 case FCIDM_SHVIEW_REFRESH:
1743 Refresh();
1744 break;
1745
1746 case FCIDM_SHVIEW_DELETE:
1747 case FCIDM_SHVIEW_CUT:
1748 case FCIDM_SHVIEW_COPY:
1749 case FCIDM_SHVIEW_RENAME:
1750 case FCIDM_SHVIEW_PROPERTIES:
1751 return OnExplorerCommand(dwCmdID, TRUE);
1752
1753 case FCIDM_SHVIEW_INSERT:
1754 case FCIDM_SHVIEW_UNDO:
1755 case FCIDM_SHVIEW_INSERTLINK:
1756 case FCIDM_SHVIEW_NEWFOLDER:
1757 return OnExplorerCommand(dwCmdID, FALSE);
1758 default:
1759 /* WM_COMMAND messages from the file menu are routed to the CDefView so as to let m_pCM handle the command */
1760 if (m_pCM && dwCmd == 0)
1761 {
1762 InvokeContextMenuCommand(dwCmdID);
1763 }
1764 }
1765
1766 return 0;
1767 }
1768
1769 /**********************************************************
1770 * ShellView_OnNotify()
1771 */
1772
1773 LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1774 {
1775 UINT CtlID;
1776 LPNMHDR lpnmh;
1777 LPNMLISTVIEW lpnmlv;
1778 NMLVDISPINFOW *lpdi;
1779 PCUITEMID_CHILD pidl;
1780 BOOL unused;
1781
1782 CtlID = wParam;
1783 lpnmh = (LPNMHDR)lParam;
1784 lpnmlv = (LPNMLISTVIEW)lpnmh;
1785 lpdi = (NMLVDISPINFOW *)lpnmh;
1786
1787 TRACE("%p CtlID=%u lpnmh->code=%x\n", this, CtlID, lpnmh->code);
1788
1789 switch (lpnmh->code)
1790 {
1791 case NM_SETFOCUS:
1792 TRACE("-- NM_SETFOCUS %p\n", this);
1793 OnSetFocus(0, 0, 0, unused);
1794 break;
1795
1796 case NM_KILLFOCUS:
1797 TRACE("-- NM_KILLFOCUS %p\n", this);
1798 OnDeactivate();
1799 /* Notify the ICommDlgBrowser interface */
1800 OnStateChange(CDBOSC_KILLFOCUS);
1801 break;
1802
1803 case NM_CUSTOMDRAW:
1804 TRACE("-- NM_CUSTOMDRAW %p\n", this);
1805 return CDRF_DODEFAULT;
1806
1807 case NM_RELEASEDCAPTURE:
1808 TRACE("-- NM_RELEASEDCAPTURE %p\n", this);
1809 break;
1810
1811 case NM_CLICK:
1812 TRACE("-- NM_CLICK %p\n", this);
1813 break;
1814
1815 case NM_RCLICK:
1816 TRACE("-- NM_RCLICK %p\n", this);
1817 break;
1818
1819 case NM_DBLCLK:
1820 TRACE("-- NM_DBLCLK %p\n", this);
1821 OpenSelectedItems();
1822 break;
1823
1824 case NM_RETURN:
1825 TRACE("-- NM_RETURN %p\n", this);
1826 OpenSelectedItems();
1827 break;
1828
1829 case HDN_ENDTRACKW:
1830 TRACE("-- HDN_ENDTRACKW %p\n", this);
1831 /*nColumn1 = m_ListView.GetColumnWidth(0);
1832 nColumn2 = m_ListView.GetColumnWidth(1);*/
1833 break;
1834
1835 case LVN_DELETEITEM:
1836 TRACE("-- LVN_DELETEITEM %p\n", this);
1837
1838 /*delete the pidl because we made a copy of it*/
1839 SHFree(reinterpret_cast<LPVOID>(lpnmlv->lParam));
1840
1841 break;
1842
1843 case LVN_DELETEALLITEMS:
1844 TRACE("-- LVN_DELETEALLITEMS %p\n", this);
1845 return FALSE;
1846
1847 case LVN_INSERTITEM:
1848 TRACE("-- LVN_INSERTITEM (STUB)%p\n", this);
1849 break;
1850
1851 case LVN_ITEMACTIVATE:
1852 TRACE("-- LVN_ITEMACTIVATE %p\n", this);
1853 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1854 break;
1855
1856 case LVN_COLUMNCLICK:
1857 m_sortInfo.nHeaderID = lpnmlv->iSubItem;
1858 if (m_sortInfo.nLastHeaderID == m_sortInfo.nHeaderID)
1859 m_sortInfo.bIsAscending = !m_sortInfo.bIsAscending;
1860 else
1861 m_sortInfo.bIsAscending = TRUE;
1862 _Sort();
1863 break;
1864
1865 case LVN_GETDISPINFOA:
1866 case LVN_GETDISPINFOW:
1867 TRACE("-- LVN_GETDISPINFO %p\n", this);
1868 pidl = _PidlByItem(lpdi->item);
1869
1870 if (lpdi->item.mask & LVIF_TEXT) /* text requested */
1871 {
1872 if (m_pSF2Parent)
1873 {
1874 SHELLDETAILS sd;
1875 if (FAILED_UNEXPECTEDLY(m_pSF2Parent->GetDetailsOf(pidl, lpdi->item.iSubItem, &sd)))
1876 break;
1877
1878 if (lpnmh->code == LVN_GETDISPINFOA)
1879 {
1880 /* shouldn't happen */
1881 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1882 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1883 TRACE("-- text=%s\n", lpdiA->item.pszText);
1884 }
1885 else /* LVN_GETDISPINFOW */
1886 {
1887 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1888 TRACE("-- text=%s\n", debugstr_w(lpdi->item.pszText));
1889 }
1890 }
1891 else
1892 {
1893 FIXME("no m_pSF2Parent\n");
1894 }
1895 }
1896 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1897 {
1898 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
1899 }
1900 if(lpdi->item.mask & LVIF_STATE)
1901 {
1902 ULONG attributes = SFGAO_HIDDEN;
1903 if (SUCCEEDED(m_pSFParent->GetAttributesOf(1, &pidl, &attributes)))
1904 {
1905 if (attributes & SFGAO_HIDDEN)
1906 {
1907 lpdi->item.state |= LVIS_CUT;
1908 }
1909 }
1910 }
1911 lpdi->item.mask |= LVIF_DI_SETITEM;
1912 break;
1913
1914 case LVN_ITEMCHANGED:
1915 TRACE("-- LVN_ITEMCHANGED %p\n", this);
1916 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1917 UpdateStatusbar();
1918 _DoFolderViewCB(SFVM_SELECTIONCHANGED, NULL/* FIXME */, NULL/* FIXME */);
1919 break;
1920
1921 case LVN_BEGINDRAG:
1922 case LVN_BEGINRDRAG:
1923 TRACE("-- LVN_BEGINDRAG\n");
1924
1925 if (GetSelections())
1926 {
1927 CComPtr<IDataObject> pda;
1928 DWORD dwAttributes = SFGAO_CANCOPY | SFGAO_CANLINK;
1929 DWORD dwEffect = DROPEFFECT_MOVE;
1930
1931 if (SUCCEEDED(m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IDataObject, &pda))))
1932 {
1933 LPNMLISTVIEW params = (LPNMLISTVIEW)lParam;
1934
1935 if (SUCCEEDED(m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &dwAttributes)))
1936 {
1937 dwEffect |= dwAttributes & (SFGAO_CANCOPY | SFGAO_CANLINK);
1938 }
1939
1940 CComPtr<IAsyncOperation> piaso;
1941 if (SUCCEEDED(pda->QueryInterface(IID_PPV_ARG(IAsyncOperation, &piaso))))
1942 {
1943 piaso->SetAsyncMode(TRUE);
1944 }
1945
1946 DWORD dwEffect2;
1947
1948 m_pSourceDataObject = pda;
1949 m_ptFirstMousePos = params->ptAction;
1950 ClientToScreen(&m_ptFirstMousePos);
1951
1952 HIMAGELIST big_icons, small_icons;
1953 Shell_GetImageLists(&big_icons, &small_icons);
1954 PCUITEMID_CHILD pidl = _PidlByItem(params->iItem);
1955 int iIcon = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
1956 POINT ptItem;
1957 m_ListView.GetItemPosition(params->iItem, &ptItem);
1958
1959 ImageList_BeginDrag(big_icons, iIcon, params->ptAction.x - ptItem.x, params->ptAction.y - ptItem.y);
1960
1961 DoDragDrop(pda, this, dwEffect, &dwEffect2);
1962
1963 m_pSourceDataObject.Release();
1964 }
1965 }
1966 break;
1967
1968 case LVN_BEGINLABELEDITW:
1969 {
1970 DWORD dwAttr = SFGAO_CANRENAME;
1971 pidl = _PidlByItem(lpdi->item);
1972
1973 TRACE("-- LVN_BEGINLABELEDITW %p\n", this);
1974
1975 m_pSFParent->GetAttributesOf(1, &pidl, &dwAttr);
1976 if (SFGAO_CANRENAME & dwAttr)
1977 {
1978 m_isEditing = TRUE;
1979 return FALSE;
1980 }
1981 return TRUE;
1982 }
1983
1984 case LVN_ENDLABELEDITW:
1985 {
1986 TRACE("-- LVN_ENDLABELEDITW %p\n", this);
1987
1988 m_isEditing = FALSE;
1989
1990 if (lpdi->item.pszText)
1991 {
1992 HRESULT hr;
1993 LVITEMW lvItem;
1994
1995 pidl = _PidlByItem(lpdi->item);
1996 PITEMID_CHILD pidlNew = NULL;
1997 hr = m_pSFParent->SetNameOf(0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidlNew);
1998
1999 if (SUCCEEDED(hr) && pidlNew)
2000 {
2001 lvItem.mask = LVIF_PARAM|LVIF_IMAGE;
2002 lvItem.iItem = lpdi->item.iItem;
2003 lvItem.iSubItem = 0;
2004 lvItem.lParam = reinterpret_cast<LPARAM>(pidlNew);
2005 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0);
2006 m_ListView.SetItem(&lvItem);
2007 m_ListView.Update(lpdi->item.iItem);
2008 return TRUE;
2009 }
2010 }
2011
2012 return FALSE;
2013 }
2014
2015 default:
2016 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh->code);
2017 break;
2018 }
2019
2020 return 0;
2021 }
2022
2023 /*
2024 * This is just a quick hack to make the desktop work correctly.
2025 * ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the way that
2026 * a folder should know if it should update upon a change notification.
2027 * It is exported by merged folders at a minimum.
2028 */
2029 static BOOL ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2)
2030 {
2031 if (!pidl1 || !pidl2)
2032 return FALSE;
2033 if (ILIsParent(pidl1, pidl2, TRUE))
2034 return TRUE;
2035
2036 if (_ILIsDesktop(pidl1))
2037 {
2038 PIDLIST_ABSOLUTE deskpidl;
2039 SHGetFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
2040 if (ILIsParent(deskpidl, pidl2, TRUE))
2041 {
2042 ILFree(deskpidl);
2043 return TRUE;
2044 }
2045 ILFree(deskpidl);
2046 SHGetFolderLocation(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
2047 if (ILIsParent(deskpidl, pidl2, TRUE))
2048 {
2049 ILFree(deskpidl);
2050 return TRUE;
2051 }
2052 ILFree(deskpidl);
2053 }
2054 return FALSE;
2055 }
2056
2057 /**********************************************************
2058 * ShellView_OnChange()
2059 */
2060 LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2061 {
2062 PCIDLIST_ABSOLUTE *Pidls = reinterpret_cast<PCIDLIST_ABSOLUTE*>(wParam);
2063 BOOL bParent0 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[0]);
2064 BOOL bParent1 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[1]);
2065
2066 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam);
2067
2068 switch (lParam &~ SHCNE_INTERRUPT)
2069 {
2070 case SHCNE_MKDIR:
2071 case SHCNE_CREATE:
2072 if (bParent0)
2073 {
2074 if (LV_FindItemByPidl(ILFindLastID(Pidls[0])) == -1)
2075 {
2076 LV_AddItem(ILFindLastID(Pidls[0]));
2077 }
2078 else
2079 {
2080 LV_ProdItem(ILFindLastID(Pidls[0]));
2081 }
2082 }
2083 break;
2084
2085 case SHCNE_RMDIR:
2086 case SHCNE_DELETE:
2087 if (bParent0)
2088 LV_DeleteItem(ILFindLastID(Pidls[0]));
2089 break;
2090
2091 case SHCNE_RENAMEFOLDER:
2092 case SHCNE_RENAMEITEM:
2093 if (bParent0 && bParent1)
2094 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[1]));
2095 else if (bParent0)
2096 LV_DeleteItem(ILFindLastID(Pidls[0]));
2097 else if (bParent1)
2098 LV_AddItem(ILFindLastID(Pidls[1]));
2099 break;
2100
2101 case SHCNE_UPDATEITEM:
2102 if (bParent0)
2103 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0]));
2104 break;
2105
2106 case SHCNE_UPDATEDIR:
2107 Refresh();
2108 break;
2109 }
2110 return TRUE;
2111 }
2112
2113 HRESULT SHGetMenuIdFromMenuMsg(UINT uMsg, LPARAM lParam, UINT *CmdId);
2114 HRESULT SHSetMenuIdInMenuMsg(UINT uMsg, LPARAM lParam, UINT CmdId);
2115
2116 /**********************************************************
2117 * CDefView::OnCustomItem
2118 */
2119 LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2120 {
2121 if (!m_pCM.p)
2122 {
2123 /* no menu */
2124 ERR("no menu!!!\n");
2125 return FALSE;
2126 }
2127
2128 /* The lParam of WM_DRAWITEM WM_MEASUREITEM contain a menu id and this also needs to
2129 be changed to a menu identifier offset */
2130 UINT CmdID;
2131 HRESULT hres = SHGetMenuIdFromMenuMsg(uMsg, lParam, &CmdID);
2132 if (SUCCEEDED(hres))
2133 SHSetMenuIdInMenuMsg(uMsg, lParam, CmdID - CONTEXT_MENU_BASE_ID);
2134
2135 /* Forward the message to the IContextMenu2 */
2136 LRESULT result;
2137 hres = SHForwardContextMenuMsg(m_pCM, uMsg, wParam, lParam, &result, TRUE);
2138
2139 return (SUCCEEDED(hres));
2140 }
2141
2142 LRESULT CDefView::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2143 {
2144 /* Wallpaper setting affects drop shadows effect */
2145 if (wParam == SPI_SETDESKWALLPAPER || wParam == 0)
2146 UpdateListColors();
2147
2148 return S_OK;
2149 }
2150
2151 /**********************************************************
2152 * CDefView::OnInitMenuPopup
2153 */
2154 LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2155 {
2156 HMENU hmenu = (HMENU) wParam;
2157 int nPos = LOWORD(lParam);
2158 UINT menuItemId;
2159
2160 OnCustomItem(uMsg, wParam, lParam, bHandled);
2161
2162 HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW);
2163
2164 /* Lets try to find out what the hell wParam is */
2165 if (hmenu == GetSubMenu(m_hMenu, nPos))
2166 menuItemId = ReallyGetMenuItemID(m_hMenu, nPos);
2167 else if (hViewMenu && hmenu == GetSubMenu(hViewMenu, nPos))
2168 menuItemId = ReallyGetMenuItemID(hViewMenu, nPos);
2169 else if (m_hContextMenu && hmenu == GetSubMenu(m_hContextMenu, nPos))
2170 menuItemId = ReallyGetMenuItemID(m_hContextMenu, nPos);
2171 else
2172 return FALSE;
2173
2174 switch (menuItemId)
2175 {
2176 case FCIDM_MENU_FILE:
2177 FillFileMenu();
2178 break;
2179 case FCIDM_MENU_VIEW:
2180 case FCIDM_SHVIEW_VIEW:
2181 CheckViewMode(hmenu);
2182 break;
2183 case FCIDM_SHVIEW_ARRANGE:
2184 FillArrangeAsMenu(hmenu);
2185 break;
2186 }
2187
2188 return FALSE;
2189 }
2190
2191 /**********************************************************
2192 *
2193 *
2194 * The INTERFACE of the IShellView object
2195 *
2196 *
2197 **********************************************************
2198 */
2199
2200 /**********************************************************
2201 * ShellView_GetWindow
2202 */
2203 HRESULT WINAPI CDefView::GetWindow(HWND *phWnd)
2204 {
2205 TRACE("(%p)\n", this);
2206
2207 *phWnd = m_hWnd;
2208
2209 return S_OK;
2210 }
2211
2212 HRESULT WINAPI CDefView::ContextSensitiveHelp(BOOL fEnterMode)
2213 {
2214 FIXME("(%p) stub\n", this);
2215
2216 return E_NOTIMPL;
2217 }
2218
2219 /**********************************************************
2220 * IShellView_TranslateAccelerator
2221 *
2222 * FIXME:
2223 * use the accel functions
2224 */
2225 HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg)
2226 {
2227 if (m_isEditing)
2228 return S_FALSE;
2229
2230 if (lpmsg->message >= WM_KEYFIRST && lpmsg->message <= WM_KEYLAST)
2231 {
2232 if (::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg) != 0)
2233 return S_OK;
2234
2235 TRACE("-- key=0x%04lx\n", lpmsg->wParam) ;
2236 }
2237
2238 return m_pShellBrowser->TranslateAcceleratorSB(lpmsg, 0);
2239 }
2240
2241 HRESULT WINAPI CDefView::EnableModeless(BOOL fEnable)
2242 {
2243 FIXME("(%p) stub\n", this);
2244
2245 return E_NOTIMPL;
2246 }
2247
2248 HRESULT WINAPI CDefView::UIActivate(UINT uState)
2249 {
2250 // CHAR szName[MAX_PATH];
2251 LRESULT lResult;
2252 int nPartArray[1] = { -1};
2253
2254 TRACE("(%p)->(state=%x) stub\n", this, uState);
2255
2256 /* don't do anything if the state isn't really changing */
2257 if (m_uState == uState)
2258 {
2259 return S_OK;
2260 }
2261
2262 /* OnActivate handles the menu merging and internal state */
2263 DoActivate(uState);
2264
2265 /* only do This if we are active */
2266 if (uState != SVUIA_DEACTIVATE)
2267 {
2268
2269 /*
2270 GetFolderPath is not a method of IShellFolder
2271 IShellFolder_GetFolderPath( m_pSFParent, szName, sizeof(szName) );
2272 */
2273 /* set the number of parts */
2274 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult);
2275
2276 /* set the text for the parts */
2277 /*
2278 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult);
2279 */
2280 }
2281
2282 return S_OK;
2283 }
2284
2285 HRESULT WINAPI CDefView::Refresh()
2286 {
2287 TRACE("(%p)\n", this);
2288
2289 m_ListView.DeleteAllItems();
2290 FillList();
2291
2292 return S_OK;
2293 }
2294
2295 HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd)
2296 {
2297 return CreateViewWindow3(psb, lpPrevView, SV3CVW3_DEFAULT,
2298 (FOLDERFLAGS)lpfs->fFlags, (FOLDERFLAGS)lpfs->fFlags, (FOLDERVIEWMODE)lpfs->ViewMode, NULL, prcView, phWnd);
2299 }
2300
2301 HRESULT WINAPI CDefView::DestroyViewWindow()
2302 {
2303 TRACE("(%p)\n", this);
2304
2305 /* Make absolutely sure all our UI is cleaned up */
2306 UIActivate(SVUIA_DEACTIVATE);
2307
2308 if (m_hAccel)
2309 {
2310 // "Accelerator tables loaded from resources are freed automatically when the application terminates." -- MSDN
2311 m_hAccel = NULL;
2312 }
2313
2314 if (m_hMenuArrangeModes)
2315 {
2316 DestroyMenu(m_hMenuArrangeModes);
2317 m_hMenuArrangeModes = NULL;
2318 }
2319
2320 if (m_hMenuViewModes)
2321 {
2322 DestroyMenu(m_hMenuViewModes);
2323 m_hMenuViewModes = NULL;
2324 }
2325
2326 if (m_hMenu)
2327 {
2328 DestroyMenu(m_hMenu);
2329 m_hMenu = NULL;
2330 }
2331
2332 if (m_ListView)
2333 {
2334 m_ListView.DestroyWindow();
2335 }
2336
2337 if (m_hWnd)
2338 {
2339 DestroyWindow();
2340 }
2341
2342 m_pShellBrowser.Release();
2343 m_pCommDlgBrowser.Release();
2344
2345 return S_OK;
2346 }
2347
2348 HRESULT WINAPI CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
2349 {
2350 TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs,
2351 m_FolderSettings.ViewMode, m_FolderSettings.fFlags);
2352
2353 if (!lpfs)
2354 return E_INVALIDARG;
2355
2356 *lpfs = m_FolderSettings;
2357 return S_OK;
2358 }
2359
2360 HRESULT WINAPI CDefView::AddPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
2361 {
2362 FIXME("(%p) stub\n", this);
2363
2364 return E_NOTIMPL;
2365 }
2366
2367 HRESULT WINAPI CDefView::SaveViewState()
2368 {
2369 FIXME("(%p) stub\n", this);
2370
2371 return S_OK;
2372 }
2373
2374 HRESULT WINAPI CDefView::SelectItem(PCUITEMID_CHILD pidl, UINT uFlags)
2375 {
2376 int i;
2377
2378 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl, uFlags);
2379
2380 i = LV_FindItemByPidl(pidl);
2381 if (i == -1)
2382 return S_OK;
2383
2384 if(uFlags & SVSI_ENSUREVISIBLE)
2385 m_ListView.EnsureVisible(i, FALSE);
2386
2387 LVITEMW lvItem = {0};
2388 lvItem.mask = LVIF_STATE;
2389 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
2390
2391 while (m_ListView.GetItem(&lvItem))
2392 {
2393 if (lvItem.iItem == i)
2394 {
2395 if (uFlags & SVSI_SELECT)
2396 lvItem.state |= LVIS_SELECTED;
2397 else
2398 lvItem.state &= ~LVIS_SELECTED;
2399
2400 if (uFlags & SVSI_FOCUSED)
2401 lvItem.state &= ~LVIS_FOCUSED;
2402 }
2403 else
2404 {
2405 if (uFlags & SVSI_DESELECTOTHERS)
2406 lvItem.state &= ~LVIS_SELECTED;
2407 }
2408
2409 m_ListView.SetItem(&lvItem);
2410 lvItem.iItem++;
2411 }
2412
2413 if((uFlags & SVSI_EDIT) == SVSI_EDIT)
2414 m_ListView.EditLabel(i);
2415
2416 return S_OK;
2417 }
2418
2419 HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
2420 {
2421 HRESULT hr = E_NOINTERFACE;
2422
2423 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem, debugstr_guid(&riid), ppvOut);
2424
2425 *ppvOut = NULL;
2426
2427 switch (uItem)
2428 {
2429 case SVGIO_BACKGROUND:
2430 if (IsEqualIID(riid, IID_IContextMenu))
2431 {
2432 if (!ppvOut)
2433 hr = E_OUTOFMEMORY;
2434
2435 hr = CDefViewBckgrndMenu_CreateInstance(m_pSF2Parent, riid, ppvOut);
2436 if (FAILED_UNEXPECTEDLY(hr))
2437 return hr;
2438
2439 IUnknown_SetSite(*((IUnknown**)ppvOut), (IShellView *)this);
2440 }
2441 else if (IsEqualIID(riid, IID_IDispatch))
2442 {
2443 if (m_pShellFolderViewDual == NULL)
2444 {
2445 hr = CDefViewDual_Constructor(riid, (LPVOID*)&m_pShellFolderViewDual);
2446 if (FAILED_UNEXPECTEDLY(hr))
2447 return hr;
2448 }
2449 hr = m_pShellFolderViewDual->QueryInterface(riid, ppvOut);
2450 }
2451 break;
2452
2453 case SVGIO_SELECTION:
2454 GetSelections();
2455 hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, riid, 0, ppvOut);
2456 if (FAILED_UNEXPECTEDLY(hr))
2457 return hr;
2458
2459 if (IsEqualIID(riid, IID_IContextMenu))
2460 IUnknown_SetSite(*((IUnknown**)ppvOut), (IShellView *)this);
2461
2462 break;
2463 }
2464
2465 TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut);
2466
2467 return hr;
2468 }
2469
2470 HRESULT STDMETHODCALLTYPE CDefView::GetCurrentViewMode(UINT *pViewMode)
2471 {
2472 TRACE("(%p)->(%p), stub\n", this, pViewMode);
2473
2474 if (!pViewMode)
2475 return E_INVALIDARG;
2476
2477 *pViewMode = m_FolderSettings.ViewMode;
2478 return S_OK;
2479 }
2480
2481 HRESULT STDMETHODCALLTYPE CDefView::SetCurrentViewMode(UINT ViewMode)
2482 {
2483 DWORD dwStyle;
2484 TRACE("(%p)->(%u), stub\n", this, ViewMode);
2485
2486 /* It's not redundant to check FVM_AUTO because it's a (UINT)-1 */
2487 if (((INT)ViewMode < FVM_FIRST || (INT)ViewMode > FVM_LAST) && ((INT)ViewMode != FVM_AUTO))
2488 return E_INVALIDARG;
2489
2490 /* Windows before Vista uses LVM_SETVIEW and possibly
2491 LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview,
2492 while later versions seem to accomplish this through other
2493 means. */
2494 switch (ViewMode)
2495 {
2496 case FVM_ICON:
2497 dwStyle = LVS_ICON;
2498 break;
2499 case FVM_DETAILS:
2500 dwStyle = LVS_REPORT;
2501 break;
2502 case FVM_SMALLICON:
2503 dwStyle = LVS_SMALLICON;
2504 break;
2505 case FVM_LIST:
2506 dwStyle = LVS_LIST;
2507 break;
2508 default:
2509 {
2510 FIXME("ViewMode %d not implemented\n", ViewMode);
2511 dwStyle = LVS_LIST;
2512 break;
2513 }
2514 }
2515
2516 m_ListView.ModifyStyle(LVS_TYPEMASK, dwStyle);
2517
2518 /* This will not necessarily be the actual mode set above.
2519 This mimics the behavior of Windows XP. */
2520 m_FolderSettings.ViewMode = ViewMode;
2521
2522 return S_OK;
2523 }
2524
2525 HRESULT STDMETHODCALLTYPE CDefView::GetFolder(REFIID riid, void **ppv)
2526 {
2527 if (m_pSFParent == NULL)
2528 return E_FAIL;
2529
2530 return m_pSFParent->QueryInterface(riid, ppv);
2531 }
2532
2533 HRESULT STDMETHODCALLTYPE CDefView::Item(int iItemIndex, PITEMID_CHILD *ppidl)
2534 {
2535 PCUITEMID_CHILD pidl = _PidlByItem(iItemIndex);
2536 if (pidl)
2537 {
2538 *ppidl = ILClone(pidl);
2539 return S_OK;
2540 }
2541
2542 *ppidl = 0;
2543 return E_INVALIDARG;
2544 }
2545
2546 HRESULT STDMETHODCALLTYPE CDefView::ItemCount(UINT uFlags, int *pcItems)
2547 {
2548 TRACE("(%p)->(%u %p)\n", this, uFlags, pcItems);
2549
2550 if (uFlags != SVGIO_ALLVIEW)
2551 FIXME("some flags unsupported, %x\n", uFlags & ~SVGIO_ALLVIEW);
2552
2553 *pcItems = m_ListView.GetItemCount();
2554
2555 return S_OK;
2556 }
2557
2558 HRESULT STDMETHODCALLTYPE CDefView::Items(UINT uFlags, REFIID riid, void **ppv)
2559 {
2560 return E_NOTIMPL;
2561 }
2562
2563 HRESULT STDMETHODCALLTYPE CDefView::GetSelectionMarkedItem(int *piItem)
2564 {
2565 TRACE("(%p)->(%p)\n", this, piItem);
2566
2567 *piItem = m_ListView.GetSelectionMark();
2568
2569 return S_OK;
2570 }
2571
2572 HRESULT STDMETHODCALLTYPE CDefView::GetFocusedItem(int *piItem)
2573 {
2574 TRACE("(%p)->(%p)\n", this, piItem);
2575
2576 *piItem = m_ListView.GetNextItem(-1, LVNI_FOCUSED);
2577
2578 return S_OK;
2579 }
2580
2581 HRESULT STDMETHODCALLTYPE CDefView::GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt)
2582 {
2583 int lvIndex = LV_FindItemByPidl(pidl);
2584 if (lvIndex == -1 || ppt == NULL)
2585 return E_INVALIDARG;
2586
2587 m_ListView.GetItemPosition(lvIndex, ppt);
2588 return S_OK;
2589 }
2590
2591 HRESULT STDMETHODCALLTYPE CDefView::GetSpacing(POINT *ppt)
2592 {
2593 TRACE("(%p)->(%p)\n", this, ppt);
2594
2595 if (!m_ListView)
2596 return S_FALSE;
2597
2598 if (ppt)
2599 {
2600 SIZE spacing;
2601 m_ListView.GetItemSpacing(spacing);
2602
2603 ppt->x = spacing.cx;
2604 ppt->y = spacing.cy;
2605 }
2606
2607 return S_OK;
2608 }
2609
2610 HRESULT STDMETHODCALLTYPE CDefView::GetDefaultSpacing(POINT *ppt)
2611 {
2612 return E_NOTIMPL;
2613 }
2614
2615 HRESULT STDMETHODCALLTYPE CDefView::GetAutoArrange()
2616 {
2617 return ((m_ListView.GetStyle() & LVS_AUTOARRANGE) ? S_OK : S_FALSE);
2618 }
2619
2620 HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags)
2621 {
2622 LVITEMW lvItem;
2623
2624 TRACE("(%p)->(%d, %x)\n", this, iItem, dwFlags);
2625
2626 lvItem.state = 0;
2627 lvItem.stateMask = LVIS_SELECTED;
2628
2629 if (dwFlags & SVSI_ENSUREVISIBLE)
2630 m_ListView.EnsureVisible(iItem, 0);
2631
2632 /* all items */
2633 if (dwFlags & SVSI_DESELECTOTHERS)
2634 m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
2635
2636 /* this item */
2637 if (dwFlags & SVSI_SELECT)
2638 lvItem.state |= LVIS_SELECTED;
2639
2640 if (dwFlags & SVSI_FOCUSED)
2641 lvItem.stateMask |= LVIS_FOCUSED;
2642
2643 m_ListView.SetItemState(iItem, lvItem.state, lvItem.stateMask);
2644
2645 if ((dwFlags & SVSI_EDIT) == SVSI_EDIT)
2646 m_ListView.EditLabel(iItem);
2647
2648 return S_OK;
2649 }
2650
2651 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags)
2652 {
2653 /* Reset the selection */
2654 m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
2655
2656 int lvIndex;
2657 for (UINT i = 0 ; i < m_cidl; i++)
2658 {
2659 lvIndex = LV_FindItemByPidl(apidl[i]);
2660 if (lvIndex != -1)
2661 {
2662 SelectItem(lvIndex, dwFlags);
2663 m_ListView.SetItemPosition(lvIndex, &apt[i]);
2664 }
2665 }
2666
2667 return S_OK;
2668 }
2669
2670 /**********************************************************
2671 * IShellView2 implementation
2672 */
2673
2674 HRESULT STDMETHODCALLTYPE CDefView::GetView(SHELLVIEWID *view_guid, ULONG view_type)
2675 {
2676 FIXME("(%p)->(%p, %lu) stub\n", this, view_guid, view_type);
2677 return E_NOTIMPL;
2678 }
2679
2680 HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow2(LPSV2CVW2_PARAMS view_params)
2681 {
2682 return CreateViewWindow3(view_params->psbOwner, view_params->psvPrev,
2683 SV3CVW3_DEFAULT, (FOLDERFLAGS)view_params->pfs->fFlags, (FOLDERFLAGS)view_params->pfs->fFlags,
2684 (FOLDERVIEWMODE)view_params->pfs->ViewMode, view_params->pvid, view_params->prcView, &view_params->hwndView);
2685 }
2686
2687 HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow3(IShellBrowser *psb, IShellView *psvPrevious, SV3CVW3_FLAGS view_flags, FOLDERFLAGS mask, FOLDERFLAGS flags, FOLDERVIEWMODE mode, const SHELLVIEWID *view_id, RECT *prcView, HWND *hwnd)
2688 {
2689 OLEMENUGROUPWIDTHS omw = { { 0, 0, 0, 0, 0, 0 } };
2690
2691 *hwnd = NULL;
2692
2693 TRACE("(%p)->(shlview=%p shlbrs=%p rec=%p hwnd=%p vmode=%x flags=%x)\n", this, psvPrevious, psb, prcView, hwnd, mode, flags);
2694 if (prcView != NULL)
2695 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom);
2696
2697 /* Validate the Shell Browser */
2698 if (psb == NULL || m_hWnd)
2699 return E_UNEXPECTED;
2700
2701 if (view_flags != SV3CVW3_DEFAULT)
2702 FIXME("unsupported view flags 0x%08x\n", view_flags);
2703
2704 /* Set up the member variables */
2705 m_pShellBrowser = psb;
2706 m_FolderSettings.ViewMode = mode;
2707 m_FolderSettings.fFlags = mask & flags;
2708
2709 if (view_id)
2710 {
2711 if (IsEqualIID(*view_id, VID_LargeIcons))
2712 m_FolderSettings.ViewMode = FVM_ICON;
2713 else if (IsEqualIID(*view_id, VID_SmallIcons))
2714 m_FolderSettings.ViewMode = FVM_SMALLICON;
2715 else if (IsEqualIID(*view_id, VID_List))
2716 m_FolderSettings.ViewMode = FVM_LIST;
2717 else if (IsEqualIID(*view_id, VID_Details))
2718 m_FolderSettings.ViewMode = FVM_DETAILS;
2719 else if (IsEqualIID(*view_id, VID_Thumbnails))
2720 m_FolderSettings.ViewMode = FVM_THUMBNAIL;
2721 else if (IsEqualIID(*view_id, VID_Tile))
2722 m_FolderSettings.ViewMode = FVM_TILE;
2723 else if (IsEqualIID(*view_id, VID_ThumbStrip))
2724 m_FolderSettings.ViewMode = FVM_THUMBSTRIP;
2725 else
2726 FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_id));
2727 }
2728
2729 /* Get our parent window */
2730 m_pShellBrowser->GetWindow(&m_hWndParent);
2731
2732 /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
2733 m_pCommDlgBrowser = NULL;
2734 if (SUCCEEDED(m_pShellBrowser->QueryInterface(IID_PPV_ARG(ICommDlgBrowser, &m_pCommDlgBrowser))))
2735 {
2736 TRACE("-- CommDlgBrowser\n");
2737 }
2738
2739 Create(m_hWndParent, prcView, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP, 0, 0U);
2740 if (m_hWnd == NULL)
2741 return E_FAIL;
2742
2743 *hwnd = m_hWnd;
2744
2745 CheckToolbar();
2746
2747 if (!*hwnd)
2748 return E_FAIL;
2749
2750 _DoFolderViewCB(SFVM_WINDOWCREATED, (WPARAM)m_hWnd, NULL);
2751
2752 SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
2753 UpdateWindow();
2754
2755 if (!m_hMenu)
2756 {
2757 m_hMenu = CreateMenu();
2758 m_pShellBrowser->InsertMenusSB(m_hMenu, &omw);
2759 TRACE("-- after fnInsertMenusSB\n");
2760 }
2761
2762 _MergeToolbar();
2763
2764 return S_OK;
2765 }
2766
2767 HRESULT STDMETHODCALLTYPE CDefView::HandleRename(LPCITEMIDLIST new_pidl)
2768 {
2769 FIXME("(%p)->(%p) stub\n", this, new_pidl);
2770 return E_NOTIMPL;
2771 }
2772
2773 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point)
2774 {
2775 FIXME("(%p)->(%p, %u, %p) stub\n", this, item, flags, point);
2776 return E_NOTIMPL;
2777 }
2778
2779 /**********************************************************
2780 * IShellFolderView implementation
2781 */
2782 HRESULT STDMETHODCALLTYPE CDefView::Rearrange(LPARAM sort)
2783 {
2784 FIXME("(%p)->(%ld) stub\n", this, sort);
2785 return E_NOTIMPL;
2786 }
2787
2788 HRESULT STDMETHODCALLTYPE CDefView::GetArrangeParam(LPARAM *sort)
2789 {
2790 FIXME("(%p)->(%p) stub\n", this, sort);
2791 return E_NOTIMPL;
2792 }
2793
2794 HRESULT STDMETHODCALLTYPE CDefView::ArrangeGrid()
2795 {
2796 FIXME("(%p) stub\n", this);
2797 return E_NOTIMPL;
2798 }
2799
2800 HRESULT STDMETHODCALLTYPE CDefView::AutoArrange()
2801 {
2802 m_ListView.ModifyStyle(0, LVS_AUTOARRANGE);
2803 m_ListView.Arrange(LVA_DEFAULT);
2804 return S_OK;
2805 }
2806
2807 HRESULT STDMETHODCALLTYPE CDefView::AddObject(PITEMID_CHILD pidl, UINT *item)
2808 {
2809 FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2810 return E_NOTIMPL;
2811 }
2812
2813 HRESULT STDMETHODCALLTYPE CDefView::GetObject(PITEMID_CHILD *pidl, UINT item)
2814 {
2815 TRACE("(%p)->(%p %d)\n", this, pidl, item);
2816 return Item(item, pidl);
2817 }
2818
2819 HRESULT STDMETHODCALLTYPE CDefView::RemoveObject(PITEMID_CHILD pidl, UINT *item)
2820 {
2821
2822 TRACE("(%p)->(%p %p)\n", this, pidl, item);
2823
2824 if (pidl)
2825 {
2826 *item = LV_FindItemByPidl(ILFindLastID(pidl));
2827 m_ListView.DeleteItem(*item);
2828 }
2829 else
2830 {
2831 *item = 0;
2832 m_ListView.DeleteAllItems();
2833 }
2834
2835 return S_OK;
2836 }
2837
2838 HRESULT STDMETHODCALLTYPE CDefView::GetObjectCount(UINT *count)
2839 {
2840 TRACE("(%p)->(%p)\n", this, count);
2841 *count = m_ListView.GetItemCount();
2842 return S_OK;
2843 }
2844
2845 HRESULT STDMETHODCALLTYPE CDefView::SetObjectCount(UINT count, UINT flags)
2846 {
2847 FIXME("(%p)->(%d %x) stub\n", this, count, flags);
2848 return E_NOTIMPL;
2849 }
2850
2851 HRESULT STDMETHODCALLTYPE CDefView::UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item)
2852 {
2853 FIXME("(%p)->(%p %p %p) stub\n", this, pidl_old, pidl_new, item);
2854 return E_NOTIMPL;
2855 }
2856
2857 HRESULT STDMETHODCALLTYPE CDefView::RefreshObject(PITEMID_CHILD pidl, UINT *item)
2858 {
2859 FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2860 return E_NOTIMPL;
2861 }
2862
2863 HRESULT STDMETHODCALLTYPE CDefView::SetRedraw(BOOL redraw)
2864 {
2865 TRACE("(%p)->(%d)\n", this, redraw);
2866 m_ListView.SetRedraw(redraw);
2867 return S_OK;
2868 }
2869
2870 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedCount(UINT *count)
2871 {
2872 FIXME("(%p)->(%p) stub\n", this, count);
2873 return E_NOTIMPL;
2874 }
2875
2876 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items)
2877 {
2878 TRACE("(%p)->(%p %p)\n", this, pidl, items);
2879
2880 *items = GetSelections();
2881
2882 if (*items)
2883 {
2884 *pidl = static_cast<PCUITEMID_CHILD *>(LocalAlloc(0, *items * sizeof(PCUITEMID_CHILD)));
2885 if (!*pidl)
2886 {
2887 return E_OUTOFMEMORY;
2888 }
2889
2890 /* it's documented that caller shouldn't PIDLs, only array itself */
2891 memcpy(*pidl, m_apidl, *items * sizeof(PCUITEMID_CHILD));
2892 }
2893
2894 return S_OK;
2895 }
2896
2897 HRESULT STDMETHODCALLTYPE CDefView::IsDropOnSource(IDropTarget *drop_target)
2898 {
2899 if ((m_iDragOverItem == -1 || m_pCurDropTarget == NULL) &&
2900 (m_pSourceDataObject.p))
2901 {
2902 return S_OK;
2903 }
2904
2905 return S_FALSE;
2906 }
2907
2908 HRESULT STDMETHODCALLTYPE CDefView::GetDragPoint(POINT *pt)
2909 {
2910 if (!pt)
2911 return E_INVALIDARG;
2912
2913 *pt = m_ptFirstMousePos;
2914 return S_OK;
2915 }
2916
2917 HRESULT STDMETHODCALLTYPE CDefView::GetDropPoint(POINT *pt)
2918 {
2919 FIXME("(%p)->(%p) stub\n", this, pt);
2920 return E_NOTIMPL;
2921 }
2922
2923 HRESULT STDMETHODCALLTYPE CDefView::MoveIcons(IDataObject *obj)
2924 {
2925 TRACE("(%p)->(%p)\n", this, obj);
2926 return E_NOTIMPL;
2927 }
2928
2929 HRESULT STDMETHODCALLTYPE CDefView::SetItemPos(PCUITEMID_CHILD pidl, POINT *pt)
2930 {
2931 FIXME("(%p)->(%p %p) stub\n", this, pidl, pt);
2932 return E_NOTIMPL;
2933 }
2934
2935 HRESULT STDMETHODCALLTYPE CDefView::IsBkDropTarget(IDropTarget *drop_target)
2936 {
2937 FIXME("(%p)->(%p) stub\n", this, drop_target);
2938 return E_NOTIMPL;
2939 }
2940
2941 HRESULT STDMETHODCALLTYPE CDefView::SetClipboard(BOOL move)
2942 {
2943 FIXME("(%p)->(%d) stub\n", this, move);
2944 return E_NOTIMPL;
2945 }
2946
2947 HRESULT STDMETHODCALLTYPE CDefView::SetPoints(IDataObject *obj)
2948 {
2949 FIXME("(%p)->(%p) stub\n", this, obj);
2950 return E_NOTIMPL;
2951 }
2952
2953 HRESULT STDMETHODCALLTYPE CDefView::GetItemSpacing(ITEMSPACING *spacing)
2954 {
2955 FIXME("(%p)->(%p) stub\n", this, spacing);
2956 return E_NOTIMPL;
2957 }
2958
2959 HRESULT STDMETHODCALLTYPE CDefView::SetCallback(IShellFolderViewCB *new_cb, IShellFolderViewCB **old_cb)
2960 {
2961 if (old_cb)
2962 *old_cb = m_pShellFolderViewCB.Detach();
2963
2964 m_pShellFolderViewCB = new_cb;
2965 return S_OK;
2966 }
2967
2968 HRESULT STDMETHODCALLTYPE CDefView::Select(UINT flags)
2969 {
2970 FIXME("(%p)->(%d) stub\n", this, flags);
2971 return E_NOTIMPL;
2972 }
2973
2974 HRESULT STDMETHODCALLTYPE CDefView::QuerySupport(UINT *support)
2975 {
2976 TRACE("(%p)->(%p)\n", this, support);
2977 return S_OK;
2978 }
2979
2980 HRESULT STDMETHODCALLTYPE CDefView::SetAutomationObject(IDispatch *disp)
2981 {
2982 FIXME("(%p)->(%p) stub\n", this, disp);
2983 return E_NOTIMPL;
2984 }
2985
2986 /**********************************************************
2987 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2988 */
2989 HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText)
2990 {
2991 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2992 this, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2993
2994 if (!prgCmds)
2995 return E_INVALIDARG;
2996
2997 for (UINT i = 0; i < cCmds; i++)
2998 {
2999 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
3000 prgCmds[i].cmdf = 0;
3001 }
3002
3003 return OLECMDERR_E_UNKNOWNGROUP;
3004 }
3005
3006 /**********************************************************
3007 * ISVOleCmdTarget_Exec (IOleCommandTarget)
3008 *
3009 * nCmdID is the OLECMDID_* enumeration
3010 */
3011 HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
3012 {
3013 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
3014 this, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
3015
3016 if (!pguidCmdGroup)
3017 return OLECMDERR_E_UNKNOWNGROUP;
3018
3019 if (IsEqualCLSID(*pguidCmdGroup, m_Category))
3020 {
3021 if (nCmdID == FCIDM_SHVIEW_AUTOARRANGE)
3022 {
3023 if (V_VT(pvaIn) != VT_INT_PTR)
3024 return OLECMDERR_E_NOTSUPPORTED;
3025
3026 TPMPARAMS params;
3027 params.cbSize = sizeof(params);
3028 params.rcExclude = *(RECT*) V_INTREF(pvaIn);
3029
3030 if (m_hMenuViewModes)
3031 {
3032 /* Duplicate all but the last two items of the view modes menu */
3033 HMENU hmenuViewPopup = CreatePopupMenu();
3034 Shell_MergeMenus(hmenuViewPopup, m_hMenuViewModes, 0, 0, 0xFFFF, 0);
3035 DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION);
3036 DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION);
3037 CheckViewMode(hmenuViewPopup);
3038 TrackPopupMenuEx(hmenuViewPopup, TPM_LEFTALIGN | TPM_TOPALIGN, params.rcExclude.left, params.rcExclude.bottom, m_hWndParent, &params);
3039 ::DestroyMenu(hmenuViewPopup);
3040 }
3041
3042 // pvaOut is VT_I4 with value 0x403 (cmd id of the new mode maybe?)
3043 V_VT(pvaOut) = VT_I4;
3044 V_I4(pvaOut) = 0x403;
3045 }
3046 }
3047
3048 if (IsEqualIID(*pguidCmdGroup, CGID_Explorer) &&
3049 (nCmdID == 0x29) &&
3050 (nCmdexecopt == 4) && pvaOut)
3051 return S_OK;
3052
3053 if (IsEqualIID(*pguidCmdGroup, CGID_ShellDocView) &&
3054 (nCmdID == 9) &&
3055 (nCmdexecopt == 0))
3056 return 1;
3057
3058 return OLECMDERR_E_UNKNOWNGROUP;
3059 }
3060
3061 /**********************************************************
3062 * ISVDropTarget implementation
3063 */
3064
3065 /******************************************************************************
3066 * drag_notify_subitem [Internal]
3067 *
3068 * Figure out the shellfolder object, which is currently under the mouse cursor
3069 * and notify it via the IDropTarget interface.
3070 */
3071
3072 #define SCROLLAREAWIDTH 20
3073
3074 HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
3075 {
3076 LONG lResult;
3077 HRESULT hr;
3078 RECT clientRect;
3079
3080 /* The key state on drop doesn't have MK_LBUTTON or MK_RBUTTON because it
3081 reflects the key state after the user released the button, so we need
3082 to remember the last key state when the button was pressed */
3083 m_grfKeyState = grfKeyState;
3084
3085 /* Map from global to client coordinates and query the index of the listview-item, which is
3086 * currently under the mouse cursor. */
3087 LVHITTESTINFO htinfo = {{pt.x, pt.y}, LVHT_ONITEM};
3088 ScreenToClient(&htinfo.pt);
3089 lResult = m_ListView.HitTest(&htinfo);
3090
3091 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
3092 ::GetClientRect(m_ListView, &clientRect);
3093 if (htinfo.pt.x == m_ptLastMousePos.x && htinfo.pt.y == m_ptLastMousePos.y &&
3094 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
3095 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
3096 {
3097 m_cScrollDelay = (m_cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
3098 if (m_cScrollDelay == 0)
3099 {
3100 /* Mouse did hover another 250 ms over the scroll-area */
3101 if (htinfo.pt.x < SCROLLAREAWIDTH)
3102 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEUP, 0);
3103
3104 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
3105 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEDOWN, 0);
3106
3107 if (htinfo.pt.y < SCROLLAREAWIDTH)
3108 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEUP, 0);
3109
3110 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
3111 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEDOWN, 0);
3112 }
3113 }
3114 else
3115 {
3116 m_cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
3117 }
3118
3119 m_ptLastMousePos = htinfo.pt;
3120
3121 /* We need to check if we drag the selection over itself */
3122 if (lResult != -1 && m_pSourceDataObject.p != NULL)
3123 {
3124 PCUITEMID_CHILD pidl = _PidlByItem(lResult);
3125
3126 for (UINT i = 0; i < m_cidl; i++)
3127 {
3128 if (pidl == m_apidl[i])
3129 {
3130 /* The item that is being draged is hovering itself. */
3131 lResult = -1;
3132 break;
3133 }
3134 }
3135 }
3136
3137 /* If we are still over the previous sub-item, notify it via DragOver and return. */
3138 if (m_pCurDropTarget && lResult == m_iDragOverItem)
3139 return m_pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect);
3140
3141 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
3142 if (m_pCurDropTarget)
3143 {
3144 PCUITEMID_CHILD pidl = _PidlByItem(m_iDragOverItem);
3145 if (pidl)
3146 SelectItem(pidl, 0);
3147
3148 m_pCurDropTarget->DragLeave();
3149 m_pCurDropTarget.Release();
3150 }
3151
3152 m_iDragOverItem = lResult;
3153
3154 if (lResult == -1)
3155 {
3156 /* We are not above one of the listview's subitems. Bind to the parent folder's
3157 * DropTarget interface. */
3158 hr = m_pSFParent->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget,&m_pCurDropTarget));
3159 }
3160 else
3161 {
3162 /* Query the relative PIDL of the shellfolder object represented by the currently
3163 * dragged over listview-item ... */
3164 PCUITEMID_CHILD pidl = _PidlByItem(lResult);
3165
3166 /* ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object */
3167 hr = m_pSFParent->GetUIObjectOf(m_ListView, 1, &pidl, IID_NULL_PPV_ARG(IDropTarget, &m_pCurDropTarget));
3168 }
3169
3170 IUnknown_SetSite(m_pCurDropTarget, (IShellView *)this);
3171
3172 /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */
3173 if (FAILED(hr))
3174 {
3175 *pdwEffect = DROPEFFECT_NONE;
3176 return hr;
3177 }
3178
3179 if (m_iDragOverItem != -1)
3180 {
3181 SelectItem(m_iDragOverItem, SVSI_SELECT);
3182 }
3183
3184 /* Notify the item just entered via DragEnter. */
3185 return m_pCurDropTarget->DragEnter(m_pCurDataObject, grfKeyState, pt, pdwEffect);
3186 }
3187
3188 HRESULT WINAPI CDefView::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
3189 {
3190 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
3191 m_pCurDataObject = pDataObject;
3192
3193 HRESULT hr = drag_notify_subitem(grfKeyState, pt, pdwEffect);
3194 if (SUCCEEDED(hr))
3195 {
3196 POINT ptClient = {pt.x, pt.y};
3197 ScreenToClient(&ptClient);
3198 ImageList_DragEnter(m_hWnd, ptClient.x, ptClient.y);
3199 }
3200
3201 return hr;
3202 }
3203
3204 HRESULT WINAPI CDefView::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
3205 {
3206 POINT ptClient = {pt.x, pt.y};
3207 ScreenToClient(&ptClient);
3208 ImageList_DragMove(ptClient.x, ptClient.y);
3209 return drag_notify_subitem(grfKeyState, pt, pdwEffect);
3210 }
3211
3212 HRESULT WINAPI CDefView::DragLeave()
3213 {
3214 ImageList_DragLeave(m_hWnd);
3215
3216 if (m_pCurDropTarget)
3217 {
3218 m_pCurDropTarget->DragLeave();
3219 m_pCurDropTarget.Release();
3220 }
3221
3222 if (m_pCurDataObject != NULL)
3223 {
3224 m_pCurDataObject.Release();
3225 }
3226
3227 m_iDragOverItem = 0;
3228
3229 return S_OK;
3230 }
3231
3232 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
3233 {
3234 ImageList_DragLeave(m_hWnd);
3235 ImageList_EndDrag();
3236
3237 if ((IsDropOnSource(NULL) == S_OK) &&
3238 (*pdwEffect & DROPEFFECT_MOVE) &&
3239 (m_grfKeyState & MK_LBUTTON))
3240 {
3241 if (m_pCurDropTarget)
3242 {
3243 m_pCurDropTarget->DragLeave();
3244 m_pCurDropTarget.Release();
3245 }
3246
3247 /* Restore the selection */
3248 m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
3249 for (UINT i = 0 ; i < m_cidl; i++)
3250 SelectItem(m_apidl[i], SVSI_SELECT);
3251
3252 /* Reposition the items */
3253 int lvIndex = -1;
3254 while ((lvIndex = m_ListView.GetNextItem(lvIndex, LVNI_SELECTED)) > -1)
3255 {
3256 POINT ptItem;
3257 if (m_ListView.GetItemPosition(lvIndex, &ptItem))
3258 {
3259 ptItem.x += pt.x - m_ptFirstMousePos.x;
3260 ptItem.y += pt.y - m_ptFirstMousePos.y;
3261 m_ListView.SetItemPosition(lvIndex, &ptItem);
3262 }
3263 }
3264 }
3265 else if (m_pCurDropTarget)
3266 {
3267 m_pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect);
3268 m_pCurDropTarget.Release();
3269 }
3270
3271 m_pCurDataObject.Release();
3272 m_iDragOverItem = 0;
3273 return S_OK;
3274 }
3275
3276 /**********************************************************
3277 * ISVDropSource implementation
3278 */
3279
3280 HRESULT WINAPI CDefView::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
3281 {
3282 TRACE("(%p)\n", this);
3283
3284 if (fEscapePressed)
3285 return DRAGDROP_S_CANCEL;
3286 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
3287 return DRAGDROP_S_DROP;
3288 else
3289 return S_OK;
3290 }
3291
3292 HRESULT WINAPI CDefView::GiveFeedback(DWORD dwEffect)
3293 {
3294 TRACE("(%p)\n", this);
3295
3296 return DRAGDROP_S_USEDEFAULTCURSORS;
3297 }
3298
3299 /**********************************************************
3300 * ISVViewObject implementation
3301 */
3302
3303 HRESULT WINAPI CDefView::Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds, BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue), ULONG_PTR dwContinue)
3304 {
3305 FIXME("Stub: this=%p\n", this);
3306
3307 return E_NOTIMPL;
3308 }
3309
3310 HRESULT WINAPI CDefView::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet)
3311 {
3312 FIXME("Stub: this=%p\n", this);
3313
3314 return E_NOTIMPL;
3315 }
3316
3317 HRESULT WINAPI CDefView::Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze)
3318 {
3319 FIXME("Stub: this=%p\n", this);
3320
3321 return E_NOTIMPL;
3322 }
3323
3324 HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze)
3325 {
3326 FIXME("Stub: this=%p\n", this);
3327
3328 return E_NOTIMPL;
3329 }
3330
3331 HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink)
3332 {
3333 FIXME("partial stub: %p 0x%08x 0x%08x %p\n", this, aspects, advf, pAdvSink);
3334
3335 /* FIXME: we set the AdviseSink, but never use it to send any advice */
3336 m_pAdvSink = pAdvSink;
3337 m_dwAspects = aspects;
3338 m_dwAdvf = advf;
3339
3340 return S_OK;
3341 }
3342
3343 HRESULT WINAPI CDefView::GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink)
3344 {
3345 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects, pAdvf, ppAdvSink);
3346
3347 if (ppAdvSink)
3348 {
3349 *ppAdvSink = m_pAdvSink;
3350 m_pAdvSink.p->AddRef();
3351 }
3352
3353 if (pAspects)
3354 *pAspects = m_dwAspects;
3355
3356 if (pAdvf)
3357 *pAdvf = m_dwAdvf;
3358
3359 return S_OK;
3360 }
3361
3362 HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
3363 {
3364 if (IsEqualIID(guidService, SID_IShellBrowser))
3365 return m_pShellBrowser->QueryInterface(riid, ppvObject);
3366 else if(IsEqualIID(guidService, SID_IFolderView))
3367 return QueryInterface(riid, ppvObject);
3368
3369 return E_NOINTERFACE;
3370 }
3371
3372 HRESULT CDefView::_MergeToolbar()
3373 {
3374 CComPtr<IExplorerToolbar> ptb;
3375 HRESULT hr = S_OK;
3376
3377 hr = IUnknown_QueryService(m_pShellBrowser, IID_IExplorerToolbar, IID_PPV_ARG(IExplorerToolbar, &ptb));
3378 if (FAILED(hr))
3379 return hr;
3380
3381 m_Category = CGID_DefViewFrame;
3382
3383 hr = ptb->SetCommandTarget(static_cast<IOleCommandTarget*>(this), &m_Category, 0);
3384 if (FAILED(hr))
3385 return hr;
3386
3387 if (hr == S_FALSE)
3388 return S_OK;
3389
3390 #if 0
3391 hr = ptb->AddButtons(&m_Category, buttonsCount, buttons);
3392 if (FAILED(hr))
3393 return hr;
3394 #endif
3395
3396 return S_OK;
3397 }
3398
3399 // The default processing of IShellFolderView callbacks
3400 HRESULT CDefView::DefMessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
3401 {
3402 // TODO: SFVM_GET_CUSTOMVIEWINFO, SFVM_WINDOWCREATED
3403 TRACE("CDefView::DefMessageSFVCB uMsg=%u\n", uMsg);
3404 return E_NOTIMPL;
3405 }
3406
3407 HRESULT CDefView::_DoFolderViewCB(UINT uMsg, WPARAM wParam, LPARAM lParam)
3408 {
3409 HRESULT hr = E_NOTIMPL;
3410
3411 if (m_pShellFolderViewCB)
3412 {
3413 hr = m_pShellFolderViewCB->MessageSFVCB(uMsg, wParam, lParam);
3414 }
3415
3416 if (hr == E_NOTIMPL)
3417 {
3418 hr = DefMessageSFVCB(uMsg, wParam, lParam);
3419 }
3420
3421 return hr;
3422 }
3423
3424 HRESULT CDefView_CreateInstance(IShellFolder *pFolder, REFIID riid, LPVOID * ppvOut)
3425 {
3426 return ShellObjectCreatorInit<CDefView>(pFolder, riid, ppvOut);
3427 }
3428
3429 HRESULT WINAPI SHCreateShellFolderViewEx(
3430 LPCSFV psvcbi, /* [in] shelltemplate struct */
3431 IShellView **ppsv) /* [out] IShellView pointer */
3432 {
3433 CComPtr<IShellView> psv;
3434 HRESULT hRes;
3435
3436 TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n",
3437 psvcbi->pshf, psvcbi->pidl, psvcbi->pfnCallback,
3438 psvcbi->fvm, psvcbi->psvOuter);
3439
3440 *ppsv = NULL;
3441 hRes = CDefView_CreateInstance(psvcbi->pshf, IID_PPV_ARG(IShellView, &psv));
3442 if (FAILED_UNEXPECTEDLY(hRes))
3443 return hRes;
3444
3445 *ppsv = psv.Detach();
3446 return hRes;
3447 }
3448
3449 HRESULT WINAPI SHCreateShellFolderView(const SFV_CREATE *pcsfv,
3450 IShellView **ppsv)
3451 {
3452 CComPtr<IShellView> psv;
3453 HRESULT hRes;
3454
3455 *ppsv = NULL;
3456 if (!pcsfv || pcsfv->cbSize != sizeof(*pcsfv))
3457 return E_INVALIDARG;
3458
3459 TRACE("sf=%p outer=%p callback=%p\n",
3460 pcsfv->pshf, pcsfv->psvOuter, pcsfv->psfvcb);
3461
3462 hRes = CDefView_CreateInstance(pcsfv->pshf, IID_PPV_ARG(IShellView, &psv));
3463 if (FAILED(hRes))
3464 return hRes;
3465
3466 if (pcsfv->psfvcb)
3467 {
3468 CComPtr<IShellFolderView> sfv;
3469 if (SUCCEEDED(psv->QueryInterface(IID_PPV_ARG(IShellFolderView, &sfv))))
3470 {
3471 sfv->SetCallback(pcsfv->psfvcb, NULL);
3472 }
3473 }
3474
3475 *ppsv = psv.Detach();
3476 return hRes;
3477 }