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