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