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