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