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