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