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