d28068b36ad989453b3cd6f0557593b6df9fc954
[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 return m_pCM->InvokeCommand(&cmi);
1216 }
1217
1218 /**********************************************************
1219 * ShellView_OpenSelectedItems()
1220 */
1221 HRESULT CDefView::OpenSelectedItems()
1222 {
1223 HMENU hMenu;
1224 UINT uCommand;
1225 HRESULT hResult;
1226
1227 m_cidl = m_ListView.GetSelectedCount();
1228 if (m_cidl == 0)
1229 return S_OK;
1230
1231 hResult = OnDefaultCommand();
1232 if (hResult == S_OK)
1233 return hResult;
1234
1235 hMenu = CreatePopupMenu();
1236 if (!hMenu)
1237 return E_FAIL;
1238
1239 hResult = GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IContextMenu, &m_pCM));
1240 if (FAILED(hResult))
1241 goto cleanup;
1242
1243 IUnknown_SetSite(m_pCM, (IShellView *)this);
1244
1245 hResult = m_pCM->QueryContextMenu(hMenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY);
1246 if (FAILED(hResult))
1247 goto cleanup;
1248
1249 uCommand = GetMenuDefaultItem(hMenu, FALSE, 0);
1250 if (uCommand == (UINT)-1)
1251 {
1252 hResult = E_FAIL;
1253 goto cleanup;
1254 }
1255
1256 InvokeContextMenuCommand(uCommand);
1257
1258 cleanup:
1259
1260 if (hMenu)
1261 DestroyMenu(hMenu);
1262
1263 if (m_pCM)
1264 {
1265 IUnknown_SetSite(m_pCM, NULL);
1266 m_pCM.Release();
1267 }
1268
1269 return hResult;
1270 }
1271
1272 /**********************************************************
1273 * ShellView_DoContextMenu()
1274 */
1275 LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1276 {
1277 WORD x, y;
1278 UINT uCommand;
1279 HRESULT hResult;
1280
1281 x = LOWORD(lParam);
1282 y = HIWORD(lParam);
1283
1284 TRACE("(%p)->(0x%08x 0x%08x) stub\n", this, x, y);
1285
1286 m_hContextMenu = CreatePopupMenu();
1287 if (!m_hContextMenu)
1288 return E_FAIL;
1289
1290 m_cidl = m_ListView.GetSelectedCount();
1291
1292 hResult = GetItemObject( m_cidl ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
1293 if (FAILED( hResult))
1294 goto cleanup;
1295
1296 IUnknown_SetSite(m_pCM, (IShellView *)this);
1297
1298 hResult = m_pCM->QueryContextMenu(m_hContextMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
1299 if (FAILED( hResult))
1300 goto cleanup;
1301
1302 uCommand = TrackPopupMenu(m_hContextMenu,
1303 TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
1304 x, y, 0, m_hWnd, NULL);
1305 if (uCommand == 0)
1306 goto cleanup;
1307
1308 if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK)
1309 goto cleanup;
1310
1311 InvokeContextMenuCommand(uCommand);
1312
1313 cleanup:
1314 if (m_pCM)
1315 {
1316 IUnknown_SetSite(m_pCM, NULL);
1317 m_pCM.Release();
1318 }
1319
1320 if (m_hContextMenu)
1321 {
1322 DestroyMenu(m_hContextMenu);
1323 m_hContextMenu = NULL;
1324 }
1325
1326 return 0;
1327 }
1328
1329 LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
1330 {
1331 HRESULT hResult;
1332 HMENU hMenu;
1333
1334 hMenu = CreatePopupMenu();
1335 if (!hMenu)
1336 return 0;
1337
1338 hResult = GetItemObject( bUseSelection ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
1339 if (FAILED( hResult))
1340 goto cleanup;
1341
1342 IUnknown_SetSite(m_pCM, (IShellView *)this);
1343
1344 hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
1345 if (FAILED( hResult))
1346 goto cleanup;
1347
1348 InvokeContextMenuCommand(uCommand);
1349
1350 cleanup:
1351 if (m_pCM)
1352 {
1353 IUnknown_SetSite(m_pCM, NULL);
1354 m_pCM.Release();
1355 }
1356
1357 if (hMenu)
1358 DestroyMenu(hMenu);
1359
1360 return 0;
1361 }
1362
1363 /**********************************************************
1364 * ##### message handling #####
1365 */
1366
1367 /**********************************************************
1368 * ShellView_OnSize()
1369 */
1370 LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1371 {
1372 WORD wWidth, wHeight;
1373
1374 wWidth = LOWORD(lParam);
1375 wHeight = HIWORD(lParam);
1376
1377 TRACE("%p width=%u height=%u\n", this, wWidth, wHeight);
1378
1379 /* Resize the ListView to fit our window */
1380 if (m_ListView)
1381 {
1382 ::MoveWindow(m_ListView, 0, 0, wWidth, wHeight, TRUE);
1383 }
1384
1385 return 0;
1386 }
1387
1388 /**********************************************************
1389 * ShellView_OnDeactivate()
1390 *
1391 * NOTES
1392 * internal
1393 */
1394 void CDefView::OnDeactivate()
1395 {
1396 TRACE("%p\n", this);
1397
1398 if (m_uState != SVUIA_DEACTIVATE)
1399 {
1400 // TODO: cleanup menu after deactivation
1401
1402 m_uState = SVUIA_DEACTIVATE;
1403 }
1404 }
1405
1406 void CDefView::DoActivate(UINT uState)
1407 {
1408 TRACE("%p uState=%x\n", this, uState);
1409
1410 /*don't do anything if the state isn't really changing */
1411 if (m_uState == uState)
1412 {
1413 return;
1414 }
1415
1416 if (uState == SVUIA_DEACTIVATE)
1417 {
1418 OnDeactivate();
1419 }
1420 else
1421 {
1422 if(m_hMenu && !m_bmenuBarInitialized)
1423 {
1424 FillEditMenu();
1425 FillViewMenu();
1426 m_pShellBrowser->SetMenuSB(m_hMenu, 0, m_hWnd);
1427 m_bmenuBarInitialized = TRUE;
1428 }
1429
1430 if (SVUIA_ACTIVATE_FOCUS == uState)
1431 {
1432 m_ListView.SetFocus();
1433 }
1434 }
1435
1436 m_uState = uState;
1437 TRACE("--\n");
1438 }
1439
1440 /**********************************************************
1441 * ShellView_OnActivate()
1442 */
1443 LRESULT CDefView::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1444 {
1445 DoActivate(SVUIA_ACTIVATE_FOCUS);
1446 return 0;
1447 }
1448
1449 /**********************************************************
1450 * ShellView_OnSetFocus()
1451 *
1452 */
1453 LRESULT CDefView::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1454 {
1455 TRACE("%p\n", this);
1456
1457 /* Tell the browser one of our windows has received the focus. This
1458 should always be done before merging menus (OnActivate merges the
1459 menus) if one of our windows has the focus.*/
1460
1461 m_pShellBrowser->OnViewWindowActive(this);
1462 DoActivate(SVUIA_ACTIVATE_FOCUS);
1463
1464 /* Set the focus to the listview */
1465 m_ListView.SetFocus();
1466
1467 /* Notify the ICommDlgBrowser interface */
1468 OnStateChange(CDBOSC_SETFOCUS);
1469
1470 return 0;
1471 }
1472
1473 /**********************************************************
1474 * ShellView_OnKillFocus()
1475 */
1476 LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1477 {
1478 TRACE("(%p) stub\n", this);
1479
1480 DoActivate(SVUIA_ACTIVATE_NOFOCUS);
1481 /* Notify the ICommDlgBrowser */
1482 OnStateChange(CDBOSC_KILLFOCUS);
1483
1484 return 0;
1485 }
1486
1487 /**********************************************************
1488 * ShellView_OnCommand()
1489 *
1490 * NOTES
1491 * the CmdID's are the ones from the context menu
1492 */
1493 LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1494 {
1495 DWORD dwCmdID;
1496 DWORD dwCmd;
1497 HWND hwndCmd;
1498 int nCount;
1499
1500 dwCmdID = GET_WM_COMMAND_ID(wParam, lParam);
1501 dwCmd = GET_WM_COMMAND_CMD(wParam, lParam);
1502 hwndCmd = GET_WM_COMMAND_HWND(wParam, lParam);
1503
1504 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n", this, dwCmdID, dwCmd, hwndCmd);
1505
1506 switch (dwCmdID)
1507 {
1508 case FCIDM_SHVIEW_SMALLICON:
1509 m_FolderSettings.ViewMode = FVM_SMALLICON;
1510 SetStyle (LVS_SMALLICON, LVS_TYPEMASK);
1511 CheckToolbar();
1512 break;
1513
1514 case FCIDM_SHVIEW_BIGICON:
1515 m_FolderSettings.ViewMode = FVM_ICON;
1516 SetStyle (LVS_ICON, LVS_TYPEMASK);
1517 CheckToolbar();
1518 break;
1519
1520 case FCIDM_SHVIEW_LISTVIEW:
1521 m_FolderSettings.ViewMode = FVM_LIST;
1522 SetStyle (LVS_LIST, LVS_TYPEMASK);
1523 CheckToolbar();
1524 break;
1525
1526 case FCIDM_SHVIEW_REPORTVIEW:
1527 m_FolderSettings.ViewMode = FVM_DETAILS;
1528 SetStyle (LVS_REPORT, LVS_TYPEMASK);
1529 CheckToolbar();
1530 break;
1531
1532 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1533 case 0x30:
1534 case 0x31:
1535 case 0x32:
1536 case 0x33:
1537 m_sortInfo.nHeaderID = dwCmdID - 0x30;
1538 m_sortInfo.bIsAscending = TRUE;
1539 m_sortInfo.nLastHeaderID = m_sortInfo.nHeaderID;
1540 m_ListView.SortItems(ListViewCompareItems, this);
1541 break;
1542
1543 case FCIDM_SHVIEW_SNAPTOGRID:
1544 case FCIDM_SHVIEW_AUTOARRANGE:
1545 //FIXME
1546 break;
1547 case FCIDM_SHVIEW_SELECTALL:
1548 m_ListView.SetItemState(-1, LVIS_SELECTED, LVIS_SELECTED);
1549 break;
1550
1551 case FCIDM_SHVIEW_INVERTSELECTION:
1552 nCount = m_ListView.GetItemCount();
1553 for (int i=0; i < nCount; i++)
1554 m_ListView.SetItemState(i, m_ListView.GetItemState(i, LVIS_SELECTED) ? 0 : LVIS_SELECTED, LVIS_SELECTED);
1555 break;
1556
1557 case FCIDM_SHVIEW_REFRESH:
1558 Refresh();
1559 break;
1560
1561 case FCIDM_SHVIEW_DELETE:
1562 case FCIDM_SHVIEW_CUT:
1563 case FCIDM_SHVIEW_COPY:
1564 case FCIDM_SHVIEW_RENAME:
1565 return OnExplorerCommand(dwCmdID, TRUE);
1566
1567 case FCIDM_SHVIEW_INSERT:
1568 case FCIDM_SHVIEW_UNDO:
1569 case FCIDM_SHVIEW_INSERTLINK:
1570 case FCIDM_SHVIEW_NEWFOLDER:
1571 return OnExplorerCommand(dwCmdID, FALSE);
1572 default:
1573 /* WM_COMMAND messages from the file menu are routed to the CDefView so as to let m_pCM handle the command */
1574 if (m_pCM)
1575 {
1576 InvokeContextMenuCommand(dwCmdID);
1577 }
1578 }
1579
1580 return 0;
1581 }
1582
1583 /**********************************************************
1584 * ShellView_OnNotify()
1585 */
1586
1587 LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1588 {
1589 UINT CtlID;
1590 LPNMHDR lpnmh;
1591 LPNMLISTVIEW lpnmlv;
1592 NMLVDISPINFOW *lpdi;
1593 PCUITEMID_CHILD pidl;
1594 BOOL unused;
1595
1596 CtlID = wParam;
1597 lpnmh = (LPNMHDR)lParam;
1598 lpnmlv = (LPNMLISTVIEW)lpnmh;
1599 lpdi = (NMLVDISPINFOW *)lpnmh;
1600
1601 TRACE("%p CtlID=%u lpnmh->code=%x\n", this, CtlID, lpnmh->code);
1602
1603 switch (lpnmh->code)
1604 {
1605 case NM_SETFOCUS:
1606 TRACE("-- NM_SETFOCUS %p\n", this);
1607 OnSetFocus(0, 0, 0, unused);
1608 break;
1609
1610 case NM_KILLFOCUS:
1611 TRACE("-- NM_KILLFOCUS %p\n", this);
1612 OnDeactivate();
1613 /* Notify the ICommDlgBrowser interface */
1614 OnStateChange(CDBOSC_KILLFOCUS);
1615 break;
1616
1617 case NM_CUSTOMDRAW:
1618 TRACE("-- NM_CUSTOMDRAW %p\n", this);
1619 return CDRF_DODEFAULT;
1620
1621 case NM_RELEASEDCAPTURE:
1622 TRACE("-- NM_RELEASEDCAPTURE %p\n", this);
1623 break;
1624
1625 case NM_CLICK:
1626 TRACE("-- NM_CLICK %p\n", this);
1627 break;
1628
1629 case NM_RCLICK:
1630 TRACE("-- NM_RCLICK %p\n", this);
1631 break;
1632
1633 case NM_DBLCLK:
1634 TRACE("-- NM_DBLCLK %p\n", this);
1635 OpenSelectedItems();
1636 break;
1637
1638 case NM_RETURN:
1639 TRACE("-- NM_RETURN %p\n", this);
1640 OpenSelectedItems();
1641 break;
1642
1643 case HDN_ENDTRACKW:
1644 TRACE("-- HDN_ENDTRACKW %p\n", this);
1645 /*nColumn1 = m_ListView.GetColumnWidth(0);
1646 nColumn2 = m_ListView.GetColumnWidth(1);*/
1647 break;
1648
1649 case LVN_DELETEITEM:
1650 TRACE("-- LVN_DELETEITEM %p\n", this);
1651
1652 /*delete the pidl because we made a copy of it*/
1653 SHFree(reinterpret_cast<LPVOID>(lpnmlv->lParam));
1654
1655 break;
1656
1657 case LVN_DELETEALLITEMS:
1658 TRACE("-- LVN_DELETEALLITEMS %p\n", this);
1659 return FALSE;
1660
1661 case LVN_INSERTITEM:
1662 TRACE("-- LVN_INSERTITEM (STUB)%p\n", this);
1663 break;
1664
1665 case LVN_ITEMACTIVATE:
1666 TRACE("-- LVN_ITEMACTIVATE %p\n", this);
1667 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1668 break;
1669
1670 case LVN_COLUMNCLICK:
1671 m_sortInfo.nHeaderID = lpnmlv->iSubItem;
1672 if (m_sortInfo.nLastHeaderID == m_sortInfo.nHeaderID)
1673 m_sortInfo.bIsAscending = !m_sortInfo.bIsAscending;
1674 else
1675 m_sortInfo.bIsAscending = TRUE;
1676 m_sortInfo.nLastHeaderID = m_sortInfo.nHeaderID;
1677
1678 m_ListView.SortItems(ListViewCompareItems, this);
1679 break;
1680
1681 case LVN_GETDISPINFOA:
1682 case LVN_GETDISPINFOW:
1683 TRACE("-- LVN_GETDISPINFO %p\n", this);
1684 pidl = _PidlByItem(lpdi->item);
1685
1686 if (lpdi->item.mask & LVIF_TEXT) /* text requested */
1687 {
1688 if (m_pSF2Parent)
1689 {
1690 SHELLDETAILS sd;
1691 if (FAILED(m_pSF2Parent->GetDetailsOf(pidl, lpdi->item.iSubItem, &sd)))
1692 {
1693 FIXME("failed to get details\n");
1694 break;
1695 }
1696
1697 if (lpnmh->code == LVN_GETDISPINFOA)
1698 {
1699 /* shouldn't happen */
1700 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1701 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1702 TRACE("-- text=%s\n", lpdiA->item.pszText);
1703 }
1704 else /* LVN_GETDISPINFOW */
1705 {
1706 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1707 TRACE("-- text=%s\n", debugstr_w(lpdi->item.pszText));
1708 }
1709 }
1710 else
1711 {
1712 FIXME("no m_pSF2Parent\n");
1713 }
1714 }
1715 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1716 {
1717 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
1718 }
1719 if(lpdi->item.mask & LVIF_STATE)
1720 {
1721 ULONG attributes = SFGAO_HIDDEN;
1722 if (SUCCEEDED(m_pSFParent->GetAttributesOf(1, &pidl, &attributes)))
1723 {
1724 if (attributes & SFGAO_HIDDEN)
1725 {
1726 lpdi->item.state |= LVIS_CUT;
1727 }
1728 }
1729 }
1730 lpdi->item.mask |= LVIF_DI_SETITEM;
1731 break;
1732
1733 case LVN_ITEMCHANGED:
1734 TRACE("-- LVN_ITEMCHANGED %p\n", this);
1735 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1736 UpdateStatusbar();
1737 break;
1738
1739 case LVN_BEGINDRAG:
1740 case LVN_BEGINRDRAG:
1741 TRACE("-- LVN_BEGINDRAG\n");
1742
1743 if (GetSelections())
1744 {
1745 CComPtr<IDataObject> pda;
1746 DWORD dwAttributes = SFGAO_CANLINK;
1747 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1748
1749 if (SUCCEEDED(m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IDataObject, &pda))))
1750 {
1751 if (SUCCEEDED(m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &dwAttributes)))
1752 {
1753 if (dwAttributes & SFGAO_CANLINK)
1754 {
1755 dwEffect |= DROPEFFECT_LINK;
1756 }
1757 }
1758
1759 CComPtr<IAsyncOperation> piaso;
1760 if (SUCCEEDED(pda->QueryInterface(IID_PPV_ARG(IAsyncOperation, &piaso))))
1761 {
1762 piaso->SetAsyncMode(TRUE);
1763 }
1764
1765 DWORD dwEffect2;
1766
1767 m_pSourceDataObject = pda;
1768
1769 DoDragDrop(pda, this, dwEffect, &dwEffect2);
1770
1771 m_pSourceDataObject.Release();
1772 }
1773 }
1774 break;
1775
1776 case LVN_BEGINLABELEDITW:
1777 {
1778 DWORD dwAttr = SFGAO_CANRENAME;
1779 pidl = _PidlByItem(lpdi->item);
1780
1781 TRACE("-- LVN_BEGINLABELEDITW %p\n", this);
1782
1783 m_pSFParent->GetAttributesOf(1, &pidl, &dwAttr);
1784 if (SFGAO_CANRENAME & dwAttr)
1785 {
1786 m_isEditing = TRUE;
1787 return FALSE;
1788 }
1789 return TRUE;
1790 }
1791
1792 case LVN_ENDLABELEDITW:
1793 {
1794 TRACE("-- LVN_ENDLABELEDITW %p\n", this);
1795
1796 m_isEditing = FALSE;
1797
1798 if (lpdi->item.pszText)
1799 {
1800 HRESULT hr;
1801 LVITEMW lvItem;
1802
1803 pidl = _PidlByItem(lpdi->item);
1804 PITEMID_CHILD pidlNew;
1805 hr = m_pSFParent->SetNameOf(0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidlNew);
1806
1807 if (SUCCEEDED(hr) && pidlNew)
1808 {
1809 lvItem.mask = LVIF_PARAM|LVIF_IMAGE;
1810 lvItem.iItem = lpdi->item.iItem;
1811 lvItem.iSubItem = 0;
1812 lvItem.lParam = reinterpret_cast<LPARAM>(pidlNew);
1813 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0);
1814 m_ListView.SetItem(&lvItem);
1815 m_ListView.Update(lpdi->item.iItem);
1816 return TRUE;
1817 }
1818 }
1819
1820 return FALSE;
1821 }
1822
1823 default:
1824 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh->code);
1825 break;
1826 }
1827
1828 return 0;
1829 }
1830
1831 /*
1832 * This is just a quick hack to make the desktop work correctly.
1833 * ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the way that
1834 * a folder should know if it should update upon a change notification.
1835 * It is exported by merged folders at a minimum.
1836 */
1837 static BOOL ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2)
1838 {
1839 if (!pidl1 || !pidl2)
1840 return FALSE;
1841 if (ILIsParent(pidl1, pidl2, TRUE))
1842 return TRUE;
1843
1844 if (_ILIsDesktop(pidl1))
1845 {
1846 PIDLIST_ABSOLUTE deskpidl;
1847 SHGetFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
1848 if (ILIsParent(deskpidl, pidl2, TRUE))
1849 {
1850 ILFree(deskpidl);
1851 return TRUE;
1852 }
1853 ILFree(deskpidl);
1854 SHGetFolderLocation(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
1855 if (ILIsParent(deskpidl, pidl2, TRUE))
1856 {
1857 ILFree(deskpidl);
1858 return TRUE;
1859 }
1860 ILFree(deskpidl);
1861 }
1862 return FALSE;
1863 }
1864
1865 /**********************************************************
1866 * ShellView_OnChange()
1867 */
1868 LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1869 {
1870 PCIDLIST_ABSOLUTE *Pidls = reinterpret_cast<PCIDLIST_ABSOLUTE*>(wParam);
1871 BOOL bParent0 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[0]);
1872 BOOL bParent1 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[1]);
1873
1874 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam);
1875
1876 switch (lParam &~ SHCNE_INTERRUPT)
1877 {
1878 case SHCNE_MKDIR:
1879 case SHCNE_CREATE:
1880 if (bParent0)
1881 {
1882 if (LV_FindItemByPidl(ILFindLastID(Pidls[0])) == -1)
1883 {
1884 LV_AddItem(ILFindLastID(Pidls[0]));
1885 }
1886 else
1887 {
1888 LV_ProdItem(ILFindLastID(Pidls[0]));
1889 }
1890 }
1891 break;
1892
1893 case SHCNE_RMDIR:
1894 case SHCNE_DELETE:
1895 if (bParent0)
1896 LV_DeleteItem(ILFindLastID(Pidls[0]));
1897 break;
1898
1899 case SHCNE_RENAMEFOLDER:
1900 case SHCNE_RENAMEITEM:
1901 if (bParent0 && bParent1)
1902 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[1]));
1903 else if (bParent0)
1904 LV_DeleteItem(ILFindLastID(Pidls[0]));
1905 else if (bParent1)
1906 LV_AddItem(ILFindLastID(Pidls[1]));
1907 break;
1908
1909 case SHCNE_UPDATEITEM:
1910 if (bParent0)
1911 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0]));
1912 break;
1913
1914 case SHCNE_UPDATEDIR:
1915 Refresh();
1916 break;
1917 }
1918 return TRUE;
1919 }
1920
1921 /**********************************************************
1922 * CDefView::OnCustomItem
1923 */
1924 LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1925 {
1926 if (!m_pCM.p)
1927 {
1928 /* no menu */
1929 ERR("no menu!!!\n");
1930 return FALSE;
1931 }
1932
1933 LRESULT result;
1934 HRESULT hres = SHForwardContextMenuMsg(m_pCM, uMsg, wParam, lParam, &result, TRUE);
1935 if (SUCCEEDED(hres))
1936 return TRUE;
1937 else
1938 return FALSE;
1939 }
1940
1941 LRESULT CDefView::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1942 {
1943 /* Wallpaper setting affects drop shadows effect */
1944 if (wParam == SPI_SETDESKWALLPAPER || wParam == 0)
1945 UpdateListColors();
1946
1947 return S_OK;
1948 }
1949
1950 /**********************************************************
1951 * CDefView::OnInitMenuPopup
1952 */
1953 LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1954 {
1955 HMENU hmenu = (HMENU) wParam;
1956 int nPos = LOWORD(lParam);
1957 UINT menuItemId;
1958
1959 OnCustomItem(uMsg, wParam, lParam, bHandled);
1960
1961 HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW);
1962
1963 /* Lets try to find out what the hell wParam is */
1964 if (hmenu == GetSubMenu(m_hMenu, nPos))
1965 menuItemId = ReallyGetMenuItemID(m_hMenu, nPos);
1966 else if (hViewMenu && hmenu == GetSubMenu(hViewMenu, nPos))
1967 menuItemId = ReallyGetMenuItemID(hViewMenu, nPos);
1968 else if (m_hContextMenu && hmenu == GetSubMenu(m_hContextMenu, nPos))
1969 menuItemId = ReallyGetMenuItemID(m_hContextMenu, nPos);
1970 else
1971 return FALSE;
1972
1973 switch (menuItemId)
1974 {
1975 case FCIDM_MENU_FILE:
1976 FillFileMenu();
1977 break;
1978 case FCIDM_MENU_VIEW:
1979 case FCIDM_SHVIEW_VIEW:
1980 CheckViewMode(hmenu);
1981 break;
1982 case FCIDM_SHVIEW_ARRANGE:
1983 FillArrangeAsMenu(hmenu);
1984 break;
1985 }
1986
1987 return FALSE;
1988 }
1989
1990 /**********************************************************
1991 *
1992 *
1993 * The INTERFACE of the IShellView object
1994 *
1995 *
1996 **********************************************************
1997 */
1998
1999 /**********************************************************
2000 * ShellView_GetWindow
2001 */
2002 HRESULT WINAPI CDefView::GetWindow(HWND *phWnd)
2003 {
2004 TRACE("(%p)\n", this);
2005
2006 *phWnd = m_hWnd;
2007
2008 return S_OK;
2009 }
2010
2011 HRESULT WINAPI CDefView::ContextSensitiveHelp(BOOL fEnterMode)
2012 {
2013 FIXME("(%p) stub\n", this);
2014
2015 return E_NOTIMPL;
2016 }
2017
2018 /**********************************************************
2019 * IShellView_TranslateAccelerator
2020 *
2021 * FIXME:
2022 * use the accel functions
2023 */
2024 HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg)
2025 {
2026 if (m_isEditing)
2027 return S_FALSE;
2028
2029 if (lpmsg->message >= WM_KEYFIRST && lpmsg->message <= WM_KEYLAST)
2030 {
2031 if (::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg) != 0)
2032 return S_OK;
2033
2034 TRACE("-- key=0x04%lx\n", lpmsg->wParam) ;
2035 }
2036
2037 return m_pShellBrowser->TranslateAcceleratorSB(lpmsg, 0);
2038 }
2039
2040 HRESULT WINAPI CDefView::EnableModeless(BOOL fEnable)
2041 {
2042 FIXME("(%p) stub\n", this);
2043
2044 return E_NOTIMPL;
2045 }
2046
2047 HRESULT WINAPI CDefView::UIActivate(UINT uState)
2048 {
2049 // CHAR szName[MAX_PATH];
2050 LRESULT lResult;
2051 int nPartArray[1] = { -1};
2052
2053 TRACE("(%p)->(state=%x) stub\n", this, uState);
2054
2055 /* don't do anything if the state isn't really changing */
2056 if (m_uState == uState)
2057 {
2058 return S_OK;
2059 }
2060
2061 /* OnActivate handles the menu merging and internal state */
2062 DoActivate(uState);
2063
2064 /* only do This if we are active */
2065 if (uState != SVUIA_DEACTIVATE)
2066 {
2067
2068 /*
2069 GetFolderPath is not a method of IShellFolder
2070 IShellFolder_GetFolderPath( m_pSFParent, szName, sizeof(szName) );
2071 */
2072 /* set the number of parts */
2073 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult);
2074
2075 /* set the text for the parts */
2076 /*
2077 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult);
2078 */
2079 }
2080
2081 return S_OK;
2082 }
2083
2084 HRESULT WINAPI CDefView::Refresh()
2085 {
2086 TRACE("(%p)\n", this);
2087
2088 m_ListView.DeleteAllItems();
2089 FillList();
2090
2091 return S_OK;
2092 }
2093
2094 HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd)
2095 {
2096 return CreateViewWindow3(psb, lpPrevView, SV3CVW3_DEFAULT,
2097 (FOLDERFLAGS)lpfs->fFlags, (FOLDERFLAGS)lpfs->fFlags, (FOLDERVIEWMODE)lpfs->ViewMode, NULL, prcView, phWnd);
2098 }
2099
2100 HRESULT WINAPI CDefView::DestroyViewWindow()
2101 {
2102 TRACE("(%p)\n", this);
2103
2104 /* Make absolutely sure all our UI is cleaned up */
2105 UIActivate(SVUIA_DEACTIVATE);
2106
2107 if (m_hAccel)
2108 {
2109 // "Accelerator tables loaded from resources are freed automatically when the application terminates." -- MSDN
2110 m_hAccel = NULL;
2111 }
2112
2113 if (m_hMenuViewModes)
2114 {
2115 DestroyMenu(m_hMenuViewModes);
2116 m_hMenuViewModes = NULL;
2117 }
2118
2119 if (m_hMenu)
2120 {
2121 DestroyMenu(m_hMenu);
2122 m_hMenu = NULL;
2123 }
2124
2125 if (m_ListView)
2126 {
2127 m_ListView.DestroyWindow();
2128 }
2129
2130 if (m_hWnd)
2131 {
2132 DestroyWindow();
2133 }
2134
2135 m_pShellBrowser.Release();
2136 m_pCommDlgBrowser.Release();
2137
2138 return S_OK;
2139 }
2140
2141 HRESULT WINAPI CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
2142 {
2143 TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs,
2144 m_FolderSettings.ViewMode, m_FolderSettings.fFlags);
2145
2146 if (!lpfs)
2147 return E_INVALIDARG;
2148
2149 *lpfs = m_FolderSettings;
2150 return S_OK;
2151 }
2152
2153 HRESULT WINAPI CDefView::AddPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
2154 {
2155 FIXME("(%p) stub\n", this);
2156
2157 return E_NOTIMPL;
2158 }
2159
2160 HRESULT WINAPI CDefView::SaveViewState()
2161 {
2162 FIXME("(%p) stub\n", this);
2163
2164 return S_OK;
2165 }
2166
2167 HRESULT WINAPI CDefView::SelectItem(PCUITEMID_CHILD pidl, UINT uFlags)
2168 {
2169 int i;
2170
2171 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl, uFlags);
2172
2173 i = LV_FindItemByPidl(pidl);
2174 if (i == -1)
2175 return S_OK;
2176
2177 if(uFlags & SVSI_ENSUREVISIBLE)
2178 m_ListView.EnsureVisible(i, FALSE);
2179
2180 LVITEMW lvItem = {0};
2181 lvItem.mask = LVIF_STATE;
2182 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
2183
2184 while (m_ListView.GetItem(&lvItem))
2185 {
2186 if (lvItem.iItem == i)
2187 {
2188 if (uFlags & SVSI_SELECT)
2189 lvItem.state |= LVIS_SELECTED;
2190 else
2191 lvItem.state &= ~LVIS_SELECTED;
2192
2193 if (uFlags & SVSI_FOCUSED)
2194 lvItem.state &= ~LVIS_FOCUSED;
2195 }
2196 else
2197 {
2198 if (uFlags & SVSI_DESELECTOTHERS)
2199 lvItem.state &= ~LVIS_SELECTED;
2200 }
2201
2202 m_ListView.SetItem(&lvItem);
2203 lvItem.iItem++;
2204 }
2205
2206 if(uFlags & SVSI_EDIT)
2207 m_ListView.EditLabel(i);
2208
2209 return S_OK;
2210 }
2211
2212 HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
2213 {
2214 HRESULT hr = E_NOINTERFACE;
2215
2216 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem, debugstr_guid(&riid), ppvOut);
2217
2218 *ppvOut = NULL;
2219
2220 switch (uItem)
2221 {
2222 case SVGIO_BACKGROUND:
2223 if (IsEqualIID(riid, IID_IContextMenu))
2224 {
2225 //*ppvOut = ISvBgCm_Constructor(m_pSFParent, FALSE);
2226 if (!ppvOut)
2227 hr = E_OUTOFMEMORY;
2228
2229 IContextMenu* pcm;
2230 hr = CDefFolderMenu_Create2(NULL, NULL, 0, NULL, m_pSFParent, NULL, 0, NULL, &pcm);
2231 if (FAILED(hr))
2232 return hr;
2233 *ppvOut = pcm;
2234 }
2235 else if (IsEqualIID(riid, IID_IDispatch))
2236 {
2237 if (m_pShellFolderViewDual == NULL)
2238 {
2239 hr = CDefViewDual_Constructor(riid, (LPVOID*)&m_pShellFolderViewDual);
2240 if (FAILED_UNEXPECTEDLY(hr))
2241 {
2242 return hr;
2243 }
2244 }
2245 hr = m_pShellFolderViewDual->QueryInterface(riid, ppvOut);
2246 }
2247 break;
2248
2249 case SVGIO_SELECTION:
2250 GetSelections();
2251 hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, riid, 0, ppvOut);
2252 break;
2253 }
2254
2255 TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut);
2256
2257 return hr;
2258 }
2259
2260 HRESULT STDMETHODCALLTYPE CDefView::GetCurrentViewMode(UINT *pViewMode)
2261 {
2262 TRACE("(%p)->(%p), stub\n", this, pViewMode);
2263
2264 if (!pViewMode)
2265 return E_INVALIDARG;
2266
2267 *pViewMode = m_FolderSettings.ViewMode;
2268 return S_OK;
2269 }
2270
2271 HRESULT STDMETHODCALLTYPE CDefView::SetCurrentViewMode(UINT ViewMode)
2272 {
2273 DWORD dwStyle;
2274 TRACE("(%p)->(%u), stub\n", this, ViewMode);
2275
2276 /* It's not redundant to check FVM_AUTO because it's a (UINT)-1 */
2277 if (((INT)ViewMode < FVM_FIRST || (INT)ViewMode > FVM_LAST) && ((INT)ViewMode != FVM_AUTO))
2278 return E_INVALIDARG;
2279
2280 /* Windows before Vista uses LVM_SETVIEW and possibly
2281 LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview,
2282 while later versions seem to accomplish this through other
2283 means. */
2284 switch (ViewMode)
2285 {
2286 case FVM_ICON:
2287 dwStyle = LVS_ICON;
2288 break;
2289 case FVM_DETAILS:
2290 dwStyle = LVS_REPORT;
2291 break;
2292 case FVM_SMALLICON:
2293 dwStyle = LVS_SMALLICON;
2294 break;
2295 case FVM_LIST:
2296 dwStyle = LVS_LIST;
2297 break;
2298 default:
2299 {
2300 FIXME("ViewMode %d not implemented\n", ViewMode);
2301 dwStyle = LVS_LIST;
2302 break;
2303 }
2304 }
2305
2306 SetStyle(dwStyle, LVS_TYPEMASK);
2307
2308 /* This will not necessarily be the actual mode set above.
2309 This mimics the behavior of Windows XP. */
2310 m_FolderSettings.ViewMode = ViewMode;
2311
2312 return S_OK;
2313 }
2314
2315 HRESULT STDMETHODCALLTYPE CDefView::GetFolder(REFIID riid, void **ppv)
2316 {
2317 if (m_pSFParent == NULL)
2318 return E_FAIL;
2319
2320 return m_pSFParent->QueryInterface(riid, ppv);
2321 }
2322
2323 HRESULT STDMETHODCALLTYPE CDefView::Item(int iItemIndex, PITEMID_CHILD *ppidl)
2324 {
2325 PCUITEMID_CHILD pidl = _PidlByItem(iItemIndex);
2326 if (pidl)
2327 {
2328 *ppidl = ILClone(pidl);
2329 return S_OK;
2330 }
2331
2332 *ppidl = 0;
2333 return E_INVALIDARG;
2334 }
2335
2336 HRESULT STDMETHODCALLTYPE CDefView::ItemCount(UINT uFlags, int *pcItems)
2337 {
2338 TRACE("(%p)->(%u %p)\n", this, uFlags, pcItems);
2339
2340 if (uFlags != SVGIO_ALLVIEW)
2341 FIXME("some flags unsupported, %x\n", uFlags & ~SVGIO_ALLVIEW);
2342
2343 *pcItems = m_ListView.GetItemCount();
2344
2345 return S_OK;
2346 }
2347
2348 HRESULT STDMETHODCALLTYPE CDefView::Items(UINT uFlags, REFIID riid, void **ppv)
2349 {
2350 return E_NOTIMPL;
2351 }
2352
2353 HRESULT STDMETHODCALLTYPE CDefView::GetSelectionMarkedItem(int *piItem)
2354 {
2355 TRACE("(%p)->(%p)\n", this, piItem);
2356
2357 *piItem = m_ListView.GetSelectionMark();
2358
2359 return S_OK;
2360 }
2361
2362 HRESULT STDMETHODCALLTYPE CDefView::GetFocusedItem(int *piItem)
2363 {
2364 TRACE("(%p)->(%p)\n", this, piItem);
2365
2366 *piItem = m_ListView.GetNextItem(-1, LVNI_FOCUSED);
2367
2368 return S_OK;
2369 }
2370
2371 HRESULT STDMETHODCALLTYPE CDefView::GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt)
2372 {
2373 return E_NOTIMPL;
2374 }
2375
2376 HRESULT STDMETHODCALLTYPE CDefView::GetSpacing(POINT *ppt)
2377 {
2378 TRACE("(%p)->(%p)\n", this, ppt);
2379
2380 if (!m_ListView)
2381 return S_FALSE;
2382
2383 if (ppt)
2384 {
2385 SIZE spacing;
2386 m_ListView.GetItemSpacing(spacing);
2387
2388 ppt->x = spacing.cx;
2389 ppt->y = spacing.cy;
2390 }
2391
2392 return S_OK;
2393 }
2394
2395 HRESULT STDMETHODCALLTYPE CDefView::GetDefaultSpacing(POINT *ppt)
2396 {
2397 return E_NOTIMPL;
2398 }
2399
2400 HRESULT STDMETHODCALLTYPE CDefView::GetAutoArrange()
2401 {
2402 return E_NOTIMPL;
2403 }
2404
2405 HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags)
2406 {
2407 LVITEMW lvItem;
2408
2409 TRACE("(%p)->(%d, %x)\n", this, iItem, dwFlags);
2410
2411 lvItem.state = 0;
2412 lvItem.stateMask = LVIS_SELECTED;
2413
2414 if (dwFlags & SVSI_ENSUREVISIBLE)
2415 m_ListView.EnsureVisible(iItem, 0);
2416
2417 /* all items */
2418 if (dwFlags & SVSI_DESELECTOTHERS)
2419 m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
2420
2421 /* this item */
2422 if (dwFlags & SVSI_SELECT)
2423 lvItem.state |= LVIS_SELECTED;
2424
2425 if (dwFlags & SVSI_FOCUSED)
2426 lvItem.stateMask |= LVIS_FOCUSED;
2427
2428 m_ListView.SetItemState(iItem, lvItem.state, lvItem.stateMask);
2429
2430 if (dwFlags & SVSI_EDIT)
2431 m_ListView.EditLabel(iItem);
2432
2433 return S_OK;
2434 }
2435
2436 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags)
2437 {
2438 return E_NOTIMPL;
2439 }
2440
2441 /**********************************************************
2442 * IShellView2 implementation
2443 */
2444
2445 HRESULT STDMETHODCALLTYPE CDefView::GetView(SHELLVIEWID *view_guid, ULONG view_type)
2446 {
2447 FIXME("(%p)->(%p, %lu) stub\n", this, view_guid, view_type);
2448 return E_NOTIMPL;
2449 }
2450
2451 HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow2(LPSV2CVW2_PARAMS view_params)
2452 {
2453 return CreateViewWindow3(view_params->psbOwner, view_params->psvPrev,
2454 SV3CVW3_DEFAULT, (FOLDERFLAGS)view_params->pfs->fFlags, (FOLDERFLAGS)view_params->pfs->fFlags,
2455 (FOLDERVIEWMODE)view_params->pfs->ViewMode, view_params->pvid, view_params->prcView, &view_params->hwndView);
2456 }
2457
2458 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)
2459 {
2460 OLEMENUGROUPWIDTHS omw = { { 0, 0, 0, 0, 0, 0 } };
2461
2462 *hwnd = NULL;
2463
2464 TRACE("(%p)->(shlview=%p shlbrs=%p rec=%p hwnd=%p vmode=%x flags=%x)\n", this, psvPrevious, psb, prcView, hwnd, mode, flags);
2465 if (prcView != NULL)
2466 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom);
2467
2468 /* Validate the Shell Browser */
2469 if (psb == NULL || m_hWnd)
2470 return E_UNEXPECTED;
2471
2472 if (view_flags != SV3CVW3_DEFAULT)
2473 FIXME("unsupported view flags 0x%08x\n", view_flags);
2474
2475 /* Set up the member variables */
2476 m_pShellBrowser = psb;
2477 m_FolderSettings.ViewMode = mode;
2478 m_FolderSettings.fFlags = mask & flags;
2479
2480 if (view_id)
2481 {
2482 if (IsEqualIID(*view_id, VID_LargeIcons))
2483 m_FolderSettings.ViewMode = FVM_ICON;
2484 else if (IsEqualIID(*view_id, VID_SmallIcons))
2485 m_FolderSettings.ViewMode = FVM_SMALLICON;
2486 else if (IsEqualIID(*view_id, VID_List))
2487 m_FolderSettings.ViewMode = FVM_LIST;
2488 else if (IsEqualIID(*view_id, VID_Details))
2489 m_FolderSettings.ViewMode = FVM_DETAILS;
2490 else if (IsEqualIID(*view_id, VID_Thumbnails))
2491 m_FolderSettings.ViewMode = FVM_THUMBNAIL;
2492 else if (IsEqualIID(*view_id, VID_Tile))
2493 m_FolderSettings.ViewMode = FVM_TILE;
2494 else if (IsEqualIID(*view_id, VID_ThumbStrip))
2495 m_FolderSettings.ViewMode = FVM_THUMBSTRIP;
2496 else
2497 FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_id));
2498 }
2499
2500 /* Get our parent window */
2501 m_pShellBrowser->GetWindow(&m_hWndParent);
2502
2503 /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
2504 m_pCommDlgBrowser = NULL;
2505 if (SUCCEEDED(m_pShellBrowser->QueryInterface(IID_PPV_ARG(ICommDlgBrowser, &m_pCommDlgBrowser))))
2506 {
2507 TRACE("-- CommDlgBrowser\n");
2508 }
2509
2510 Create(m_hWndParent, prcView, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP, 0, 0U);
2511 if (m_hWnd == NULL)
2512 return E_FAIL;
2513
2514 *hwnd = m_hWnd;
2515
2516 CheckToolbar();
2517
2518 if (!*hwnd)
2519 return E_FAIL;
2520
2521 SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
2522 UpdateWindow();
2523
2524 if (!m_hMenu)
2525 {
2526 m_hMenu = CreateMenu();
2527 m_pShellBrowser->InsertMenusSB(m_hMenu, &omw);
2528 TRACE("-- after fnInsertMenusSB\n");
2529 }
2530
2531 _MergeToolbar();
2532
2533 return S_OK;
2534 }
2535
2536 HRESULT STDMETHODCALLTYPE CDefView::HandleRename(LPCITEMIDLIST new_pidl)
2537 {
2538 FIXME("(%p)->(%p) stub\n", this, new_pidl);
2539 return E_NOTIMPL;
2540 }
2541
2542 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point)
2543 {
2544 FIXME("(%p)->(%p, %u, %p) stub\n", this, item, flags, point);
2545 return E_NOTIMPL;
2546 }
2547
2548 /**********************************************************
2549 * IShellFolderView implementation
2550 */
2551 HRESULT STDMETHODCALLTYPE CDefView::Rearrange(LPARAM sort)
2552 {
2553 FIXME("(%p)->(%ld) stub\n", this, sort);
2554 return E_NOTIMPL;
2555 }
2556
2557 HRESULT STDMETHODCALLTYPE CDefView::GetArrangeParam(LPARAM *sort)
2558 {
2559 FIXME("(%p)->(%p) stub\n", this, sort);
2560 return E_NOTIMPL;
2561 }
2562
2563 HRESULT STDMETHODCALLTYPE CDefView::ArrangeGrid()
2564 {
2565 FIXME("(%p) stub\n", this);
2566 return E_NOTIMPL;
2567 }
2568
2569 HRESULT STDMETHODCALLTYPE CDefView::AutoArrange()
2570 {
2571 FIXME("(%p) stub\n", this);
2572 return E_NOTIMPL;
2573 }
2574
2575 HRESULT STDMETHODCALLTYPE CDefView::AddObject(PITEMID_CHILD pidl, UINT *item)
2576 {
2577 FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2578 return E_NOTIMPL;
2579 }
2580
2581 HRESULT STDMETHODCALLTYPE CDefView::GetObject(PITEMID_CHILD *pidl, UINT item)
2582 {
2583 TRACE("(%p)->(%p %d)\n", this, pidl, item);
2584 return Item(item, pidl);
2585 }
2586
2587 HRESULT STDMETHODCALLTYPE CDefView::RemoveObject(PITEMID_CHILD pidl, UINT *item)
2588 {
2589
2590 TRACE("(%p)->(%p %p)\n", this, pidl, item);
2591
2592 if (pidl)
2593 {
2594 *item = LV_FindItemByPidl(ILFindLastID(pidl));
2595 m_ListView.DeleteItem(*item);
2596 }
2597 else
2598 {
2599 *item = 0;
2600 m_ListView.DeleteAllItems();
2601 }
2602
2603 return S_OK;
2604 }
2605
2606 HRESULT STDMETHODCALLTYPE CDefView::GetObjectCount(UINT *count)
2607 {
2608 TRACE("(%p)->(%p)\n", this, count);
2609 *count = m_ListView.GetItemCount();
2610 return S_OK;
2611 }
2612
2613 HRESULT STDMETHODCALLTYPE CDefView::SetObjectCount(UINT count, UINT flags)
2614 {
2615 FIXME("(%p)->(%d %x) stub\n", this, count, flags);
2616 return E_NOTIMPL;
2617 }
2618
2619 HRESULT STDMETHODCALLTYPE CDefView::UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item)
2620 {
2621 FIXME("(%p)->(%p %p %p) stub\n", this, pidl_old, pidl_new, item);
2622 return E_NOTIMPL;
2623 }
2624
2625 HRESULT STDMETHODCALLTYPE CDefView::RefreshObject(PITEMID_CHILD pidl, UINT *item)
2626 {
2627 FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2628 return E_NOTIMPL;
2629 }
2630
2631 HRESULT STDMETHODCALLTYPE CDefView::SetRedraw(BOOL redraw)
2632 {
2633 TRACE("(%p)->(%d)\n", this, redraw);
2634 m_ListView.SetRedraw(redraw);
2635 return S_OK;
2636 }
2637
2638 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedCount(UINT *count)
2639 {
2640 FIXME("(%p)->(%p) stub\n", this, count);
2641 return E_NOTIMPL;
2642 }
2643
2644 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items)
2645 {
2646 TRACE("(%p)->(%p %p)\n", this, pidl, items);
2647
2648 *items = GetSelections();
2649
2650 if (*items)
2651 {
2652 *pidl = static_cast<PCUITEMID_CHILD *>(LocalAlloc(0, *items * sizeof(PCUITEMID_CHILD)));
2653 if (!*pidl)
2654 {
2655 return E_OUTOFMEMORY;
2656 }
2657
2658 /* it's documented that caller shouldn't PIDLs, only array itself */
2659 memcpy(*pidl, m_apidl, *items * sizeof(PCUITEMID_CHILD));
2660 }
2661
2662 return S_OK;
2663 }
2664
2665 HRESULT STDMETHODCALLTYPE CDefView::IsDropOnSource(IDropTarget *drop_target)
2666 {
2667 FIXME("(%p)->(%p) stub\n", this, drop_target);
2668 return E_NOTIMPL;
2669 }
2670
2671 HRESULT STDMETHODCALLTYPE CDefView::GetDragPoint(POINT *pt)
2672 {
2673 FIXME("(%p)->(%p) stub\n", this, pt);
2674 return E_NOTIMPL;
2675 }
2676
2677 HRESULT STDMETHODCALLTYPE CDefView::GetDropPoint(POINT *pt)
2678 {
2679 FIXME("(%p)->(%p) stub\n", this, pt);
2680 return E_NOTIMPL;
2681 }
2682
2683 HRESULT STDMETHODCALLTYPE CDefView::MoveIcons(IDataObject *obj)
2684 {
2685 TRACE("(%p)->(%p)\n", this, obj);
2686 return E_NOTIMPL;
2687 }
2688
2689 HRESULT STDMETHODCALLTYPE CDefView::SetItemPos(PCUITEMID_CHILD pidl, POINT *pt)
2690 {
2691 FIXME("(%p)->(%p %p) stub\n", this, pidl, pt);
2692 return E_NOTIMPL;
2693 }
2694
2695 HRESULT STDMETHODCALLTYPE CDefView::IsBkDropTarget(IDropTarget *drop_target)
2696 {
2697 FIXME("(%p)->(%p) stub\n", this, drop_target);
2698 return E_NOTIMPL;
2699 }
2700
2701 HRESULT STDMETHODCALLTYPE CDefView::SetClipboard(BOOL move)
2702 {
2703 FIXME("(%p)->(%d) stub\n", this, move);
2704 return E_NOTIMPL;
2705 }
2706
2707 HRESULT STDMETHODCALLTYPE CDefView::SetPoints(IDataObject *obj)
2708 {
2709 FIXME("(%p)->(%p) stub\n", this, obj);
2710 return E_NOTIMPL;
2711 }
2712
2713 HRESULT STDMETHODCALLTYPE CDefView::GetItemSpacing(ITEMSPACING *spacing)
2714 {
2715 FIXME("(%p)->(%p) stub\n", this, spacing);
2716 return E_NOTIMPL;
2717 }
2718
2719 HRESULT STDMETHODCALLTYPE CDefView::SetCallback(IShellFolderViewCB *new_cb, IShellFolderViewCB **old_cb)
2720 {
2721 FIXME("(%p)->(%p %p) stub\n", this, new_cb, old_cb);
2722 return E_NOTIMPL;
2723 }
2724
2725 HRESULT STDMETHODCALLTYPE CDefView::Select(UINT flags)
2726 {
2727 FIXME("(%p)->(%d) stub\n", this, flags);
2728 return E_NOTIMPL;
2729 }
2730
2731 HRESULT STDMETHODCALLTYPE CDefView::QuerySupport(UINT *support)
2732 {
2733 TRACE("(%p)->(%p)\n", this, support);
2734 return S_OK;
2735 }
2736
2737 HRESULT STDMETHODCALLTYPE CDefView::SetAutomationObject(IDispatch *disp)
2738 {
2739 FIXME("(%p)->(%p) stub\n", this, disp);
2740 return E_NOTIMPL;
2741 }
2742
2743 /**********************************************************
2744 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2745 */
2746 HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText)
2747 {
2748 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2749 this, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2750
2751 if (!prgCmds)
2752 return E_INVALIDARG;
2753
2754 for (UINT i = 0; i < cCmds; i++)
2755 {
2756 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2757 prgCmds[i].cmdf = 0;
2758 }
2759
2760 return OLECMDERR_E_UNKNOWNGROUP;
2761 }
2762
2763 /**********************************************************
2764 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2765 *
2766 * nCmdID is the OLECMDID_* enumeration
2767 */
2768 HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
2769 {
2770 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2771 this, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2772
2773 if (!pguidCmdGroup)
2774 return OLECMDERR_E_UNKNOWNGROUP;
2775
2776 if (IsEqualCLSID(*pguidCmdGroup, m_Category))
2777 {
2778 if (nCmdID == FCIDM_SHVIEW_AUTOARRANGE)
2779 {
2780 if (V_VT(pvaIn) != VT_INT_PTR)
2781 return OLECMDERR_E_NOTSUPPORTED;
2782
2783 TPMPARAMS params;
2784 params.cbSize = sizeof(params);
2785 params.rcExclude = *(RECT*) V_INTREF(pvaIn);
2786
2787 if (m_hMenuViewModes)
2788 {
2789 /* Duplicate all but the last two items of the view modes menu */
2790 HMENU hmenuViewPopup = CreatePopupMenu();
2791 Shell_MergeMenus(hmenuViewPopup, m_hMenuViewModes, 0, 0, 0xFFFF, 0);
2792 DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION);
2793 DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION);
2794 CheckViewMode(hmenuViewPopup);
2795 TrackPopupMenuEx(hmenuViewPopup, TPM_LEFTALIGN | TPM_TOPALIGN, params.rcExclude.left, params.rcExclude.bottom, m_hWndParent, &params);
2796 ::DestroyMenu(hmenuViewPopup);
2797 }
2798
2799 // pvaOut is VT_I4 with value 0x403 (cmd id of the new mode maybe?)
2800 V_VT(pvaOut) = VT_I4;
2801 V_I4(pvaOut) = 0x403;
2802 }
2803 }
2804
2805 if (IsEqualIID(*pguidCmdGroup, CGID_Explorer) &&
2806 (nCmdID == 0x29) &&
2807 (nCmdexecopt == 4) && pvaOut)
2808 return S_OK;
2809
2810 if (IsEqualIID(*pguidCmdGroup, CGID_ShellDocView) &&
2811 (nCmdID == 9) &&
2812 (nCmdexecopt == 0))
2813 return 1;
2814
2815 return OLECMDERR_E_UNKNOWNGROUP;
2816 }
2817
2818 /**********************************************************
2819 * ISVDropTarget implementation
2820 */
2821
2822 /******************************************************************************
2823 * drag_notify_subitem [Internal]
2824 *
2825 * Figure out the shellfolder object, which is currently under the mouse cursor
2826 * and notify it via the IDropTarget interface.
2827 */
2828
2829 #define SCROLLAREAWIDTH 20
2830
2831 HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2832 {
2833 LVHITTESTINFO htinfo;
2834 LONG lResult;
2835 HRESULT hr;
2836 RECT clientRect;
2837
2838 /* Map from global to client coordinates and query the index of the listview-item, which is
2839 * currently under the mouse cursor. */
2840 htinfo.pt.x = pt.x;
2841 htinfo.pt.y = pt.y;
2842 htinfo.flags = LVHT_ONITEM;
2843 ::ScreenToClient(m_ListView, &htinfo.pt);
2844 lResult = m_ListView.HitTest(&htinfo);
2845
2846 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2847 ::GetClientRect(m_ListView, &clientRect);
2848 if (htinfo.pt.x == m_ptLastMousePos.x && htinfo.pt.y == m_ptLastMousePos.y &&
2849 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2850 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2851 {
2852 m_cScrollDelay = (m_cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2853 if (m_cScrollDelay == 0)
2854 {
2855 /* Mouse did hover another 250 ms over the scroll-area */
2856 if (htinfo.pt.x < SCROLLAREAWIDTH)
2857 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEUP, 0);
2858
2859 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2860 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEDOWN, 0);
2861
2862 if (htinfo.pt.y < SCROLLAREAWIDTH)
2863 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEUP, 0);
2864
2865 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2866 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEDOWN, 0);
2867 }
2868 }
2869 else
2870 {
2871 m_cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2872 }
2873
2874 m_ptLastMousePos = htinfo.pt;
2875
2876 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2877 if (m_pCurDropTarget && lResult == m_iDragOverItem)
2878 return m_pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect);
2879
2880 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2881 if (m_pCurDropTarget)
2882 {
2883 m_pCurDropTarget->DragLeave();
2884 m_pCurDropTarget.Release();
2885 }
2886
2887 m_iDragOverItem = lResult;
2888 if (lResult == -1)
2889 {
2890 /* We are not above one of the listview's subitems. Bind to the parent folder's
2891 * DropTarget interface. */
2892 hr = m_pSFParent->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget,&m_pCurDropTarget));
2893 }
2894 else
2895 {
2896 /* Query the relative PIDL of the shellfolder object represented by the currently
2897 * dragged over listview-item ... */
2898 PCUITEMID_CHILD pidl = _PidlByItem(lResult);
2899
2900 /* ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2901 hr = m_pSFParent->GetUIObjectOf(m_ListView, 1, &pidl, IID_NULL_PPV_ARG(IDropTarget, &m_pCurDropTarget));
2902 }
2903
2904 /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */
2905 if (FAILED(hr))
2906 return hr;
2907
2908 /* Notify the item just entered via DragEnter. */
2909 return m_pCurDropTarget->DragEnter(m_pCurDataObject, grfKeyState, pt, pdwEffect);
2910 }
2911
2912 HRESULT WINAPI CDefView::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2913 {
2914 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2915 m_pCurDataObject = pDataObject;
2916 pDataObject->AddRef();
2917
2918 return drag_notify_subitem(grfKeyState, pt, pdwEffect);
2919 }
2920
2921 HRESULT WINAPI CDefView::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2922 {
2923 return drag_notify_subitem(grfKeyState, pt, pdwEffect);
2924 }
2925
2926 HRESULT WINAPI CDefView::DragLeave()
2927 {
2928 if (m_pCurDropTarget)
2929 {
2930 m_pCurDropTarget->DragLeave();
2931 m_pCurDropTarget.Release();
2932 }
2933
2934 if (m_pCurDataObject != NULL)
2935 {
2936 m_pCurDataObject.Release();
2937 }
2938
2939 m_iDragOverItem = 0;
2940
2941 return S_OK;
2942 }
2943
2944 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2945 {
2946 ERR("GetKeyState(VK_LBUTTON): %d\n", GetKeyState(VK_LBUTTON));
2947
2948 if ((m_iDragOverItem == -1) &&
2949 (*pdwEffect & DROPEFFECT_MOVE) &&
2950 (GetKeyState(VK_LBUTTON) != 0) &&
2951 (m_pSourceDataObject.p) &&
2952 (SHIsSameObject(pDataObject, m_pSourceDataObject)))
2953 {
2954 ERR("Should implement moving items here!\n");
2955
2956 if (m_pCurDropTarget)
2957 {
2958 m_pCurDropTarget->DragLeave();
2959 m_pCurDropTarget.Release();
2960 }
2961 }
2962 else if (m_pCurDropTarget)
2963 {
2964 m_pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect);
2965 m_pCurDropTarget.Release();
2966 }
2967
2968 m_pCurDataObject.Release();
2969 m_iDragOverItem = 0;
2970 return S_OK;
2971 }
2972
2973 /**********************************************************
2974 * ISVDropSource implementation
2975 */
2976
2977 HRESULT WINAPI CDefView::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
2978 {
2979 TRACE("(%p)\n", this);
2980
2981 if (fEscapePressed)
2982 return DRAGDROP_S_CANCEL;
2983 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2984 return DRAGDROP_S_DROP;
2985 else
2986 return S_OK;
2987 }
2988
2989 HRESULT WINAPI CDefView::GiveFeedback(DWORD dwEffect)
2990 {
2991 TRACE("(%p)\n", this);
2992
2993 return DRAGDROP_S_USEDEFAULTCURSORS;
2994 }
2995
2996 /**********************************************************
2997 * ISVViewObject implementation
2998 */
2999
3000 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)
3001 {
3002 FIXME("Stub: this=%p\n", this);
3003
3004 return E_NOTIMPL;
3005 }
3006
3007 HRESULT WINAPI CDefView::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet)
3008 {
3009 FIXME("Stub: this=%p\n", this);
3010
3011 return E_NOTIMPL;
3012 }
3013
3014 HRESULT WINAPI CDefView::Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze)
3015 {
3016 FIXME("Stub: this=%p\n", this);
3017
3018 return E_NOTIMPL;
3019 }
3020
3021 HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze)
3022 {
3023 FIXME("Stub: this=%p\n", this);
3024
3025 return E_NOTIMPL;
3026 }
3027
3028 HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink)
3029 {
3030 FIXME("partial stub: %p %08x %08x %p\n", this, aspects, advf, pAdvSink);
3031
3032 /* FIXME: we set the AdviseSink, but never use it to send any advice */
3033 m_pAdvSink = pAdvSink;
3034 m_dwAspects = aspects;
3035 m_dwAdvf = advf;
3036
3037 return S_OK;
3038 }
3039
3040 HRESULT WINAPI CDefView::GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink)
3041 {
3042 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects, pAdvf, ppAdvSink);
3043
3044 if (ppAdvSink)
3045 {
3046 *ppAdvSink = m_pAdvSink;
3047 m_pAdvSink.p->AddRef();
3048 }
3049
3050 if (pAspects)
3051 *pAspects = m_dwAspects;
3052
3053 if (pAdvf)
3054 *pAdvf = m_dwAdvf;
3055
3056 return S_OK;
3057 }
3058
3059 HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
3060 {
3061 if (IsEqualIID(guidService, SID_IShellBrowser))
3062 return m_pShellBrowser->QueryInterface(riid, ppvObject);
3063 else if(IsEqualIID(guidService, SID_IFolderView))
3064 return QueryInterface(riid, ppvObject);
3065
3066 return E_NOINTERFACE;
3067 }
3068
3069 HRESULT CDefView::_MergeToolbar()
3070 {
3071 CComPtr<IExplorerToolbar> ptb;
3072 HRESULT hr = S_OK;
3073
3074 hr = IUnknown_QueryService(m_pShellBrowser, IID_IExplorerToolbar, IID_PPV_ARG(IExplorerToolbar, &ptb));
3075 if (FAILED(hr))
3076 return hr;
3077
3078 m_Category = CGID_DefViewFrame;
3079
3080 hr = ptb->SetCommandTarget(static_cast<IOleCommandTarget*>(this), &m_Category, 0);
3081 if (FAILED(hr))
3082 return hr;
3083
3084 if (hr == S_FALSE)
3085 return S_OK;
3086
3087 #if 0
3088 hr = ptb->AddButtons(&m_Category, buttonsCount, buttons);
3089 if (FAILED(hr))
3090 return hr;
3091 #endif
3092
3093 return S_OK;
3094 }
3095 /**********************************************************
3096 * IShellView_Constructor
3097 */
3098 HRESULT WINAPI IShellView_Constructor(IShellFolder *pFolder, IShellView **newView)
3099 {
3100 return ShellObjectCreatorInit<CDefView>(pFolder, IID_IShellView, newView);
3101 }
3102
3103 HRESULT WINAPI CDefView_Constructor(IShellFolder *pFolder, REFIID riid, LPVOID * ppvOut)
3104 {
3105 return ShellObjectCreatorInit<CDefView>(pFolder, riid, ppvOut);
3106 }