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