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