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