[BROWSEUI]
[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 DbgPrint("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 DbgPrint("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 DbgPrint("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 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 IDropSource * pds = (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 piaso->Release();
1779 }
1780
1781 if (pds)
1782 { DWORD dwEffect2;
1783 DoDragDrop(pda, pds, dwEffect, &dwEffect2);
1784 }
1785 pda->Release();
1786 }
1787 }
1788 break;
1789
1790 case LVN_BEGINLABELEDITW:
1791 {
1792 DWORD dwAttr = SFGAO_CANRENAME;
1793 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1794
1795 TRACE("-- LVN_BEGINLABELEDITW %p\n", this);
1796
1797 m_pSFParent->GetAttributesOf(1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1798 if (SFGAO_CANRENAME & dwAttr)
1799 {
1800 m_isEditing = TRUE;
1801 return FALSE;
1802 }
1803 return TRUE;
1804 }
1805
1806 case LVN_ENDLABELEDITW:
1807 {
1808 TRACE("-- LVN_ENDLABELEDITW %p\n", this);
1809
1810 m_isEditing = FALSE;
1811
1812 if (lpdi->item.pszText)
1813 {
1814 HRESULT hr;
1815 LVITEMW lvItem;
1816
1817 lvItem.iItem = lpdi->item.iItem;
1818 lvItem.iSubItem = 0;
1819 lvItem.mask = LVIF_PARAM;
1820 SendMessageW(m_hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
1821
1822 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1823 hr = m_pSFParent->SetNameOf(0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidl);
1824
1825 if (SUCCEEDED(hr) && pidl)
1826 {
1827 lvItem.mask = LVIF_PARAM|LVIF_IMAGE;
1828 lvItem.lParam = (LPARAM)pidl;
1829 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
1830 SendMessageW(m_hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
1831 SendMessageW(m_hWndList, LVM_UPDATE, lpdi->item.iItem, 0);
1832
1833 return TRUE;
1834 }
1835 }
1836
1837 return FALSE;
1838 }
1839
1840 default:
1841 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh->code);
1842 break;
1843 }
1844
1845 return 0;
1846 }
1847
1848 /**********************************************************
1849 * ShellView_OnChange()
1850 */
1851 LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1852 {
1853 LPITEMIDLIST *Pidls;
1854
1855 Pidls = (LPITEMIDLIST *)wParam;
1856
1857 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam);
1858
1859 switch (lParam)
1860 {
1861 case SHCNE_MKDIR:
1862 case SHCNE_CREATE:
1863 LV_AddItem(Pidls[0]);
1864 break;
1865
1866 case SHCNE_RMDIR:
1867 case SHCNE_DELETE:
1868 LV_DeleteItem(Pidls[0]);
1869 break;
1870
1871 case SHCNE_RENAMEFOLDER:
1872 case SHCNE_RENAMEITEM:
1873 LV_RenameItem(Pidls[0], Pidls[1]);
1874 break;
1875
1876 case SHCNE_UPDATEITEM:
1877 LV_RenameItem(Pidls[0], Pidls[0]);
1878 break;
1879
1880 case SHCNE_UPDATEDIR:
1881 Refresh();
1882 break;
1883 }
1884 return TRUE;
1885 }
1886
1887 /**********************************************************
1888 * CDefView::OnCustomItem
1889 */
1890 LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1891 {
1892 if (!m_pCM.p)
1893 {
1894 /* no menu */
1895 ERR("no menu!!!\n");
1896 return FALSE;
1897 }
1898
1899 CComPtr<IContextMenu2> pCM2;
1900 HRESULT hres = m_pCM.p->QueryInterface(IID_PPV_ARG(IContextMenu2, &pCM2));
1901 if(FAILED(hres))
1902 return FALSE;
1903
1904 if (pCM2.p->HandleMenuMsg(uMsg, (WPARAM)m_hWnd, lParam) == S_OK)
1905 return TRUE;
1906 else
1907 return FALSE;
1908 }
1909
1910 LRESULT CDefView::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1911 {
1912 /* Wallpaper setting affects drop shadows effect */
1913 if (wParam == SPI_SETDESKWALLPAPER || wParam == 0)
1914 UpdateListColors();
1915
1916 return S_OK;
1917 }
1918
1919 /**********************************************************
1920 * CDefView::OnInitMenuPopup
1921 */
1922 LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1923 {
1924 MENUITEMINFOW mii = { 0 };
1925 HMENU hSubmenu = (HMENU) wParam;
1926
1927 DbgPrint("OnInitMenuPopup lParam=%d\n", lParam);
1928
1929 mii.cbSize = sizeof(mii);
1930 mii.fMask = MIIM_ID | MIIM_SUBMENU;
1931
1932 if (!GetMenuItemInfoW(this->m_hMenu, lParam, TRUE, &mii))
1933 {
1934 DbgPrint("OnInitMenuPopup GetMenuItemInfoW failed!\n");
1935 return FALSE;
1936 }
1937
1938 UINT menuItemId = mii.wID;
1939
1940 if (mii.hSubMenu != hSubmenu)
1941 {
1942 DbgPrint("OnInitMenuPopup submenu does not match!!!!\n");
1943 return FALSE;
1944 }
1945
1946 DbgPrint("OnInitMenuPopup id=%d\n", menuItemId);
1947
1948 switch (menuItemId)
1949 {
1950 case FCIDM_MENU_FILE:
1951 PrepareShowFileMenu(hSubmenu);
1952 break;
1953 case FCIDM_MENU_EDIT:
1954 //PrepareShowEditMenu(hSubmenu);
1955 break;
1956 case FCIDM_MENU_VIEW:
1957 PrepareShowViewMenu(hSubmenu);
1958 break;
1959 }
1960
1961 return FALSE;
1962 }
1963
1964 /**********************************************************
1965 *
1966 *
1967 * The INTERFACE of the IShellView object
1968 *
1969 *
1970 **********************************************************
1971 */
1972
1973 /**********************************************************
1974 * ShellView_GetWindow
1975 */
1976 HRESULT WINAPI CDefView::GetWindow(HWND *phWnd)
1977 {
1978 TRACE("(%p)\n", this);
1979
1980 *phWnd = m_hWnd;
1981
1982 return S_OK;
1983 }
1984
1985 HRESULT WINAPI CDefView::ContextSensitiveHelp(BOOL fEnterMode)
1986 {
1987 FIXME("(%p) stub\n", this);
1988
1989 return E_NOTIMPL;
1990 }
1991
1992 /**********************************************************
1993 * IShellView_TranslateAccelerator
1994 *
1995 * FIXME:
1996 * use the accel functions
1997 */
1998 HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg)
1999 {
2000 if (m_isEditing)
2001 return S_FALSE;
2002
2003 if (lpmsg->message >= WM_KEYFIRST && lpmsg->message <= WM_KEYLAST)
2004 {
2005 if (::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg) != 0)
2006 return S_OK;
2007
2008 TRACE("-- key=0x04%lx\n", lpmsg->wParam) ;
2009 }
2010
2011 return m_pShellBrowser->TranslateAcceleratorSB(lpmsg, 0);
2012 }
2013
2014 HRESULT WINAPI CDefView::EnableModeless(BOOL fEnable)
2015 {
2016 FIXME("(%p) stub\n", this);
2017
2018 return E_NOTIMPL;
2019 }
2020
2021 HRESULT WINAPI CDefView::UIActivate(UINT uState)
2022 {
2023 /*
2024 CHAR szName[MAX_PATH];
2025 */
2026 LRESULT lResult;
2027 int nPartArray[1] = { -1};
2028
2029 TRACE("(%p)->(state=%x) stub\n", this, uState);
2030
2031 /*don't do anything if the state isn't really changing*/
2032 if (m_uState == uState)
2033 {
2034 return S_OK;
2035 }
2036
2037 /*OnActivate handles the menu merging and internal state*/
2038 DoActivate(uState);
2039
2040 /*only do This if we are active*/
2041 if (uState != SVUIA_DEACTIVATE)
2042 {
2043
2044 /*
2045 GetFolderPath is not a method of IShellFolder
2046 IShellFolder_GetFolderPath( m_pSFParent, szName, sizeof(szName) );
2047 */
2048 /* set the number of parts */
2049 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult);
2050
2051 /* set the text for the parts */
2052 /*
2053 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult);
2054 */
2055 }
2056
2057 return S_OK;
2058 }
2059
2060 HRESULT WINAPI CDefView::Refresh()
2061 {
2062 TRACE("(%p)\n", this);
2063
2064 SendMessageW(m_hWndList, LVM_DELETEALLITEMS, 0, 0);
2065 FillList();
2066
2067 return S_OK;
2068 }
2069
2070 HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd)
2071 {
2072 OLEMENUGROUPWIDTHS omw = { { 0, 0, 0, 0, 0, 0 } };
2073
2074 *phWnd = 0;
2075
2076 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n", this, lpPrevView, lpfs, psb, prcView, phWnd);
2077
2078 if (lpfs != NULL)
2079 TRACE("-- vmode=%x flags=%x\n", lpfs->ViewMode, lpfs->fFlags);
2080 if (prcView != NULL)
2081 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom);
2082
2083 /* Validate the Shell Browser */
2084 if (psb == NULL)
2085 return E_UNEXPECTED;
2086
2087 /*set up the member variables*/
2088 m_pShellBrowser = psb;
2089 m_FolderSettings = *lpfs;
2090
2091 /*get our parent window*/
2092 m_pShellBrowser->GetWindow(&m_hWndParent);
2093
2094 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
2095 m_pCommDlgBrowser = NULL;
2096 if (SUCCEEDED(m_pShellBrowser->QueryInterface(IID_PPV_ARG(ICommDlgBrowser, &m_pCommDlgBrowser))))
2097 {
2098 TRACE("-- CommDlgBrowser\n");
2099 }
2100
2101 Create(m_hWndParent, prcView, NULL, WS_CHILD | WS_TABSTOP, 0, 0U);
2102 if (m_hWnd == NULL)
2103 return E_FAIL;
2104
2105 *phWnd = m_hWnd;
2106
2107 CheckToolbar();
2108
2109 if (!*phWnd)
2110 return E_FAIL;
2111
2112 SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
2113 UpdateWindow();
2114
2115 if (!m_hMenu)
2116 {
2117 m_hMenu = CreateMenu();
2118 m_pShellBrowser->InsertMenusSB(m_hMenu, &omw);
2119 TRACE("-- after fnInsertMenusSB\n");
2120 }
2121
2122 return S_OK;
2123 }
2124
2125 HRESULT WINAPI CDefView::DestroyViewWindow()
2126 {
2127 TRACE("(%p)\n", this);
2128
2129 /*Make absolutely sure all our UI is cleaned up.*/
2130 UIActivate(SVUIA_DEACTIVATE);
2131
2132 if (m_hMenu)
2133 {
2134 DestroyMenu(m_hMenu);
2135 }
2136
2137 DestroyWindow();
2138 m_pShellBrowser.Release();
2139 m_pCommDlgBrowser.Release();
2140
2141 return S_OK;
2142 }
2143
2144 HRESULT WINAPI CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
2145 {
2146 TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs,
2147 m_FolderSettings.ViewMode, m_FolderSettings.fFlags);
2148
2149 if (!lpfs)
2150 return E_INVALIDARG;
2151
2152 *lpfs = m_FolderSettings;
2153 return S_OK;
2154 }
2155
2156 HRESULT WINAPI CDefView::AddPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
2157 {
2158 FIXME("(%p) stub\n", this);
2159
2160 return E_NOTIMPL;
2161 }
2162
2163 HRESULT WINAPI CDefView::SaveViewState()
2164 {
2165 FIXME("(%p) stub\n", this);
2166
2167 return S_OK;
2168 }
2169
2170 HRESULT WINAPI CDefView::SelectItem(LPCITEMIDLIST pidl, UINT uFlags)
2171 {
2172 int i;
2173
2174 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl, uFlags);
2175
2176 i = LV_FindItemByPidl(pidl);
2177
2178 if (i != -1)
2179 {
2180 LVITEMW lvItem;
2181
2182 if(uFlags & SVSI_ENSUREVISIBLE)
2183 SendMessageW(m_hWndList, LVM_ENSUREVISIBLE, i, 0);
2184
2185 lvItem.mask = LVIF_STATE;
2186 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
2187 lvItem.iItem = 0;
2188 lvItem.iSubItem = 0;
2189
2190 while (SendMessageW(m_hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem))
2191 {
2192 if (lvItem.iItem == i)
2193 {
2194 if (uFlags & SVSI_SELECT)
2195 lvItem.state |= LVIS_SELECTED;
2196 else
2197 lvItem.state &= ~LVIS_SELECTED;
2198
2199 if (uFlags & SVSI_FOCUSED)
2200 lvItem.state &= ~LVIS_FOCUSED;
2201 }
2202 else
2203 {
2204 if (uFlags & SVSI_DESELECTOTHERS)
2205 lvItem.state &= ~LVIS_SELECTED;
2206 }
2207
2208 SendMessageW(m_hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
2209 lvItem.iItem++;
2210 }
2211
2212
2213 if(uFlags & SVSI_EDIT)
2214 SendMessageW(m_hWndList, LVM_EDITLABELW, i, 0);
2215 }
2216
2217 return S_OK;
2218 }
2219
2220 HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
2221 {
2222 HRESULT hr = E_NOINTERFACE;
2223
2224 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem, debugstr_guid(&riid), ppvOut);
2225
2226 *ppvOut = NULL;
2227
2228 switch (uItem)
2229 {
2230 case SVGIO_BACKGROUND:
2231 if (IsEqualIID(riid, IID_IContextMenu))
2232 {
2233 //*ppvOut = ISvBgCm_Constructor(m_pSFParent, FALSE);
2234 CDefFolderMenu_Create2(NULL, NULL, 0, NULL, m_pSFParent, NULL, 0, NULL, (IContextMenu**)ppvOut);
2235 if (!ppvOut)
2236 hr = E_OUTOFMEMORY;
2237 else
2238 hr = S_OK;
2239 }
2240 break;
2241
2242 case SVGIO_SELECTION:
2243 GetSelections();
2244 hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, (LPCITEMIDLIST*)m_apidl, riid, 0, ppvOut);
2245 break;
2246 }
2247
2248 TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut);
2249
2250 return hr;
2251 }
2252
2253 HRESULT STDMETHODCALLTYPE CDefView::GetCurrentViewMode(UINT *pViewMode)
2254 {
2255 TRACE("(%p)->(%p), stub\n", this, pViewMode);
2256
2257 if (!pViewMode)
2258 return E_INVALIDARG;
2259
2260 *pViewMode = m_FolderSettings.ViewMode;
2261 return S_OK;
2262 }
2263
2264 HRESULT STDMETHODCALLTYPE CDefView::SetCurrentViewMode(UINT ViewMode)
2265 {
2266 DWORD dwStyle;
2267 TRACE("(%p)->(%u), stub\n", this, ViewMode);
2268
2269 /* It's not redundant to check FVM_AUTO because it's a (UINT)-1 */
2270 if ((ViewMode < FVM_FIRST || ViewMode > FVM_LAST) && (ViewMode != (UINT)FVM_AUTO))
2271 return E_INVALIDARG;
2272
2273 /* Windows before Vista uses LVM_SETVIEW and possibly
2274 LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview,
2275 while later versions seem to accomplish this through other
2276 means. */
2277 switch (ViewMode)
2278 {
2279 case FVM_ICON:
2280 dwStyle = LVS_ICON;
2281 break;
2282 case FVM_DETAILS:
2283 dwStyle = LVS_REPORT;
2284 break;
2285 case FVM_SMALLICON:
2286 dwStyle = LVS_SMALLICON;
2287 break;
2288 case FVM_LIST:
2289 dwStyle = LVS_LIST;
2290 break;
2291 default:
2292 {
2293 FIXME("ViewMode %d not implemented\n", ViewMode);
2294 dwStyle = LVS_LIST;
2295 break;
2296 }
2297 }
2298
2299 SetStyle(dwStyle, LVS_TYPEMASK);
2300
2301 /* This will not necessarily be the actual mode set above.
2302 This mimics the behavior of Windows XP. */
2303 m_FolderSettings.ViewMode = ViewMode;
2304
2305 return S_OK;
2306 }
2307
2308 HRESULT STDMETHODCALLTYPE CDefView::GetFolder(REFIID riid, void **ppv)
2309 {
2310 if (m_pSFParent == NULL)
2311 return E_FAIL;
2312
2313 return m_pSFParent->QueryInterface(riid, ppv);
2314 }
2315
2316 HRESULT STDMETHODCALLTYPE CDefView::Item(int iItemIndex, LPITEMIDLIST *ppidl)
2317 {
2318 LVITEMW item;
2319
2320 TRACE("(%p)->(%d %p)\n", this, iItemIndex, ppidl);
2321
2322 item.mask = LVIF_PARAM;
2323 item.iItem = iItemIndex;
2324
2325 if (SendMessageW(m_hWndList, LVM_GETITEMW, 0, (LPARAM)&item))
2326 {
2327 *ppidl = ILClone((PITEMID_CHILD)item.lParam);
2328 return S_OK;
2329 }
2330
2331 *ppidl = 0;
2332
2333 return E_INVALIDARG;
2334 }
2335
2336 HRESULT STDMETHODCALLTYPE CDefView::ItemCount(UINT uFlags, int *pcItems)
2337 {
2338 TRACE("(%p)->(%u %p)\n", this, uFlags, pcItems);
2339
2340 if (uFlags != SVGIO_ALLVIEW)
2341 FIXME("some flags unsupported, %x\n", uFlags & ~SVGIO_ALLVIEW);
2342
2343 *pcItems = SendMessageW(m_hWndList, LVM_GETITEMCOUNT, 0, 0);
2344
2345 return S_OK;
2346 }
2347
2348 HRESULT STDMETHODCALLTYPE CDefView::Items(UINT uFlags, REFIID riid, void **ppv)
2349 {
2350 return E_NOTIMPL;
2351 }
2352
2353 HRESULT STDMETHODCALLTYPE CDefView::GetSelectionMarkedItem(int *piItem)
2354 {
2355 TRACE("(%p)->(%p)\n", this, piItem);
2356
2357 *piItem = SendMessageW(m_hWndList, LVM_GETSELECTIONMARK, 0, 0);
2358
2359 return S_OK;
2360 }
2361
2362 HRESULT STDMETHODCALLTYPE CDefView::GetFocusedItem(int *piItem)
2363 {
2364 TRACE("(%p)->(%p)\n", this, piItem);
2365
2366 *piItem = SendMessageW(m_hWndList, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
2367
2368 return S_OK;
2369 }
2370
2371 HRESULT STDMETHODCALLTYPE CDefView::GetItemPosition(LPCITEMIDLIST pidl, POINT *ppt)
2372 {
2373 return E_NOTIMPL;
2374 }
2375
2376 HRESULT STDMETHODCALLTYPE CDefView::GetSpacing(POINT *ppt)
2377 {
2378 TRACE("(%p)->(%p)\n", this, ppt);
2379
2380 if (NULL == m_hWndList) return S_FALSE;
2381
2382 if (ppt)
2383 {
2384 const DWORD ret = SendMessageW(m_hWndList, LVM_GETITEMSPACING, 0, 0);
2385
2386 ppt->x = LOWORD(ret);
2387 ppt->y = HIWORD(ret);
2388 }
2389
2390 return S_OK;
2391 }
2392
2393 HRESULT STDMETHODCALLTYPE CDefView::GetDefaultSpacing(POINT *ppt)
2394 {
2395 return E_NOTIMPL;
2396 }
2397
2398 HRESULT STDMETHODCALLTYPE CDefView::GetAutoArrange()
2399 {
2400 return E_NOTIMPL;
2401 }
2402
2403 HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags)
2404 {
2405 LVITEMW lvItem;
2406
2407 TRACE("(%p)->(%d, %x)\n", this, iItem, dwFlags);
2408
2409 lvItem.state = 0;
2410 lvItem.stateMask = LVIS_SELECTED;
2411
2412 if (dwFlags & SVSI_ENSUREVISIBLE)
2413 SendMessageW(m_hWndList, LVM_ENSUREVISIBLE, iItem, 0);
2414
2415 /* all items */
2416 if (dwFlags & SVSI_DESELECTOTHERS)
2417 SendMessageW(m_hWndList, LVM_SETITEMSTATE, -1, (LPARAM)&lvItem);
2418
2419 /* this item */
2420 if (dwFlags & SVSI_SELECT)
2421 lvItem.state |= LVIS_SELECTED;
2422
2423 if (dwFlags & SVSI_FOCUSED)
2424 lvItem.stateMask |= LVIS_FOCUSED;
2425
2426 SendMessageW(m_hWndList, LVM_SETITEMSTATE, iItem, (LPARAM)&lvItem);
2427
2428 if (dwFlags & SVSI_EDIT)
2429 SendMessageW(m_hWndList, LVM_EDITLABELW, iItem, 0);
2430
2431 return S_OK;
2432 }
2433
2434 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags)
2435 {
2436 return E_NOTIMPL;
2437 }
2438
2439 /**********************************************************
2440 * IShellFolderView implementation
2441 */
2442 HRESULT STDMETHODCALLTYPE CDefView::Rearrange(LPARAM sort)
2443 {
2444 FIXME("(%p)->(%ld) stub\n", this, sort);
2445 return E_NOTIMPL;
2446 }
2447
2448 HRESULT STDMETHODCALLTYPE CDefView::GetArrangeParam(LPARAM *sort)
2449 {
2450 FIXME("(%p)->(%p) stub\n", this, sort);
2451 return E_NOTIMPL;
2452 }
2453
2454 HRESULT STDMETHODCALLTYPE CDefView::ArrangeGrid()
2455 {
2456 FIXME("(%p) stub\n", this);
2457 return E_NOTIMPL;
2458 }
2459
2460 HRESULT STDMETHODCALLTYPE CDefView::AutoArrange()
2461 {
2462 FIXME("(%p) stub\n", this);
2463 return E_NOTIMPL;
2464 }
2465
2466 HRESULT STDMETHODCALLTYPE CDefView::AddObject(PITEMID_CHILD pidl, UINT *item)
2467 {
2468 FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2469 return E_NOTIMPL;
2470 }
2471
2472 HRESULT STDMETHODCALLTYPE CDefView::GetObject(PITEMID_CHILD *pidl, UINT item)
2473 {
2474 TRACE("(%p)->(%p %d)\n", this, pidl, item);
2475 return Item(item, pidl);
2476 }
2477
2478 HRESULT STDMETHODCALLTYPE CDefView::RemoveObject(PITEMID_CHILD pidl, UINT *item)
2479 {
2480
2481 TRACE("(%p)->(%p %p)\n", this, pidl, item);
2482
2483 if (pidl)
2484 {
2485 *item = LV_FindItemByPidl(ILFindLastID(pidl));
2486 SendMessageW(m_hWndList, LVM_DELETEITEM, *item, 0);
2487 }
2488 else
2489 {
2490 *item = 0;
2491 SendMessageW(m_hWndList, LVM_DELETEALLITEMS, 0, 0);
2492 }
2493
2494 return S_OK;
2495 }
2496
2497 HRESULT STDMETHODCALLTYPE CDefView::GetObjectCount(UINT *count)
2498 {
2499 TRACE("(%p)->(%p)\n", this, count);
2500 return ItemCount(SVGIO_ALLVIEW, reinterpret_cast<INT*>(count));
2501 }
2502
2503 HRESULT STDMETHODCALLTYPE CDefView::SetObjectCount(UINT count, UINT flags)
2504 {
2505 FIXME("(%p)->(%d %x) stub\n", this, count, flags);
2506 return E_NOTIMPL;
2507 }
2508
2509 HRESULT STDMETHODCALLTYPE CDefView::UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item)
2510 {
2511 FIXME("(%p)->(%p %p %p) stub\n", this, pidl_old, pidl_new, item);
2512 return E_NOTIMPL;
2513 }
2514
2515 HRESULT STDMETHODCALLTYPE CDefView::RefreshObject(PITEMID_CHILD pidl, UINT *item)
2516 {
2517 FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2518 return E_NOTIMPL;
2519 }
2520
2521 HRESULT STDMETHODCALLTYPE CDefView::SetRedraw(BOOL redraw)
2522 {
2523 TRACE("(%p)->(%d)\n", this, redraw);
2524 SendMessageW(m_hWndList, WM_SETREDRAW, redraw, 0);
2525 return S_OK;
2526 }
2527
2528 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedCount(UINT *count)
2529 {
2530 FIXME("(%p)->(%p) stub\n", this, count);
2531 return E_NOTIMPL;
2532 }
2533
2534 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items)
2535 {
2536 TRACE("(%p)->(%p %p)\n", this, pidl, items);
2537
2538 *items = GetSelections();
2539
2540 if (*items)
2541 {
2542 *pidl = static_cast<PCUITEMID_CHILD *>(LocalAlloc(0, *items * sizeof(LPITEMIDLIST)));
2543 if (!*pidl)
2544 {
2545 return E_OUTOFMEMORY;
2546 }
2547
2548 /* it's documented that caller shouldn't PIDLs, only array itself */
2549 memcpy(static_cast<PCUITEMID_CHILD *>(*pidl), m_apidl, *items * sizeof(LPITEMIDLIST));
2550 }
2551
2552 return S_OK;
2553 }
2554
2555 HRESULT STDMETHODCALLTYPE CDefView::IsDropOnSource(IDropTarget *drop_target)
2556 {
2557 FIXME("(%p)->(%p) stub\n", this, drop_target);
2558 return E_NOTIMPL;
2559 }
2560
2561 HRESULT STDMETHODCALLTYPE CDefView::GetDragPoint(POINT *pt)
2562 {
2563 FIXME("(%p)->(%p) stub\n", this, pt);
2564 return E_NOTIMPL;
2565 }
2566
2567 HRESULT STDMETHODCALLTYPE CDefView::GetDropPoint(POINT *pt)
2568 {
2569 FIXME("(%p)->(%p) stub\n", this, pt);
2570 return E_NOTIMPL;
2571 }
2572
2573 HRESULT STDMETHODCALLTYPE CDefView::MoveIcons(IDataObject *obj)
2574 {
2575 TRACE("(%p)->(%p)\n", this, obj);
2576 return E_NOTIMPL;
2577 }
2578
2579 HRESULT STDMETHODCALLTYPE CDefView::SetItemPos(PCUITEMID_CHILD pidl, POINT *pt)
2580 {
2581 FIXME("(%p)->(%p %p) stub\n", this, pidl, pt);
2582 return E_NOTIMPL;
2583 }
2584
2585 HRESULT STDMETHODCALLTYPE CDefView::IsBkDropTarget(IDropTarget *drop_target)
2586 {
2587 FIXME("(%p)->(%p) stub\n", this, drop_target);
2588 return E_NOTIMPL;
2589 }
2590
2591 HRESULT STDMETHODCALLTYPE CDefView::SetClipboard(BOOL move)
2592 {
2593 FIXME("(%p)->(%d) stub\n", this, move);
2594 return E_NOTIMPL;
2595 }
2596
2597 HRESULT STDMETHODCALLTYPE CDefView::SetPoints(IDataObject *obj)
2598 {
2599 FIXME("(%p)->(%p) stub\n", this, obj);
2600 return E_NOTIMPL;
2601 }
2602
2603 HRESULT STDMETHODCALLTYPE CDefView::GetItemSpacing(ITEMSPACING *spacing)
2604 {
2605 FIXME("(%p)->(%p) stub\n", this, spacing);
2606 return E_NOTIMPL;
2607 }
2608
2609 HRESULT STDMETHODCALLTYPE CDefView::SetCallback(IShellFolderViewCB *new_cb, IShellFolderViewCB **old_cb)
2610 {
2611 FIXME("(%p)->(%p %p) stub\n", this, new_cb, old_cb);
2612 return E_NOTIMPL;
2613 }
2614
2615 HRESULT STDMETHODCALLTYPE CDefView::Select(UINT flags)
2616 {
2617 FIXME("(%p)->(%d) stub\n", this, flags);
2618 return E_NOTIMPL;
2619 }
2620
2621 HRESULT STDMETHODCALLTYPE CDefView::QuerySupport(UINT *support)
2622 {
2623 TRACE("(%p)->(%p)\n", this, support);
2624 return S_OK;
2625 }
2626
2627 HRESULT STDMETHODCALLTYPE CDefView::SetAutomationObject(IDispatch *disp)
2628 {
2629 FIXME("(%p)->(%p) stub\n", this, disp);
2630 return E_NOTIMPL;
2631 }
2632
2633 /**********************************************************
2634 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2635 */
2636 HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText)
2637 {
2638 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2639 this, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2640
2641 if (!prgCmds)
2642 return E_INVALIDARG;
2643
2644 for (UINT i = 0; i < cCmds; i++)
2645 {
2646 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2647 prgCmds[i].cmdf = 0;
2648 }
2649
2650 return OLECMDERR_E_UNKNOWNGROUP;
2651 }
2652
2653 /**********************************************************
2654 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2655 *
2656 * nCmdID is the OLECMDID_* enumeration
2657 */
2658 HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
2659 {
2660 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2661 this, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2662
2663 if (!pguidCmdGroup)
2664 return OLECMDERR_E_UNKNOWNGROUP;
2665
2666 if (IsEqualIID(*pguidCmdGroup, CGID_Explorer) &&
2667 (nCmdID == 0x29) &&
2668 (nCmdexecopt == 4) && pvaOut)
2669 return S_OK;
2670
2671 if (IsEqualIID(*pguidCmdGroup, CGID_ShellDocView) &&
2672 (nCmdID == 9) &&
2673 (nCmdexecopt == 0))
2674 return 1;
2675
2676 return OLECMDERR_E_UNKNOWNGROUP;
2677 }
2678
2679 /**********************************************************
2680 * ISVDropTarget implementation
2681 */
2682
2683 /******************************************************************************
2684 * drag_notify_subitem [Internal]
2685 *
2686 * Figure out the shellfolder object, which is currently under the mouse cursor
2687 * and notify it via the IDropTarget interface.
2688 */
2689
2690 #define SCROLLAREAWIDTH 20
2691
2692 HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2693 {
2694 LVHITTESTINFO htinfo;
2695 LVITEMW lvItem;
2696 LONG lResult;
2697 HRESULT hr;
2698 RECT clientRect;
2699
2700 /* Map from global to client coordinates and query the index of the listview-item, which is
2701 * currently under the mouse cursor. */
2702 htinfo.pt.x = pt.x;
2703 htinfo.pt.y = pt.y;
2704 htinfo.flags = LVHT_ONITEM;
2705 ::ScreenToClient(m_hWndList, &htinfo.pt);
2706 lResult = SendMessageW(m_hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2707
2708 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2709 ::GetClientRect(m_hWndList, &clientRect);
2710 if (htinfo.pt.x == m_ptLastMousePos.x && htinfo.pt.y == m_ptLastMousePos.y &&
2711 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2712 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2713 {
2714 m_cScrollDelay = (m_cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2715 if (m_cScrollDelay == 0)
2716 {
2717 /* Mouse did hover another 250 ms over the scroll-area */
2718 if (htinfo.pt.x < SCROLLAREAWIDTH)
2719 SendMessageW(m_hWndList, WM_HSCROLL, SB_LINEUP, 0);
2720
2721 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2722 SendMessageW(m_hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2723
2724 if (htinfo.pt.y < SCROLLAREAWIDTH)
2725 SendMessageW(m_hWndList, WM_VSCROLL, SB_LINEUP, 0);
2726
2727 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2728 SendMessageW(m_hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2729 }
2730 }
2731 else
2732 {
2733 m_cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2734 }
2735
2736 m_ptLastMousePos = htinfo.pt;
2737
2738 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2739 if (m_pCurDropTarget && lResult == m_iDragOverItem)
2740 return m_pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect);
2741
2742 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2743 if (m_pCurDropTarget)
2744 {
2745 m_pCurDropTarget->DragLeave();
2746 m_pCurDropTarget.Release();
2747 }
2748
2749 m_iDragOverItem = lResult;
2750 if (lResult == -1)
2751 {
2752 /* We are not above one of the listview's subitems. Bind to the parent folder's
2753 * DropTarget interface. */
2754 hr = m_pSFParent->QueryInterface(IID_PPV_ARG(IDropTarget,&m_pCurDropTarget));
2755 }
2756 else
2757 {
2758 /* Query the relative PIDL of the shellfolder object represented by the currently
2759 * dragged over listview-item ... */
2760 lvItem.mask = LVIF_PARAM;
2761 lvItem.iItem = lResult;
2762 lvItem.iSubItem = 0;
2763 SendMessageW(m_hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
2764
2765 /* ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2766 hr = m_pSFParent->GetUIObjectOf(m_hWndList, 1, (LPCITEMIDLIST*)&lvItem.lParam, IID_NULL_PPV_ARG(IDropTarget, &m_pCurDropTarget));
2767 }
2768
2769 /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */
2770 if (FAILED(hr))
2771 return hr;
2772
2773 /* Notify the item just entered via DragEnter. */
2774 return m_pCurDropTarget->DragEnter(m_pCurDataObject, grfKeyState, pt, pdwEffect);
2775 }
2776
2777 HRESULT WINAPI CDefView::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2778 {
2779 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2780 m_pCurDataObject = pDataObject;
2781 pDataObject->AddRef();
2782
2783 return drag_notify_subitem(grfKeyState, pt, pdwEffect);
2784 }
2785
2786 HRESULT WINAPI CDefView::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2787 {
2788 return drag_notify_subitem(grfKeyState, pt, pdwEffect);
2789 }
2790
2791 HRESULT WINAPI CDefView::DragLeave()
2792 {
2793 if (m_pCurDropTarget)
2794 {
2795 m_pCurDropTarget->DragLeave();
2796 m_pCurDropTarget.Release();
2797 }
2798
2799 if (m_pCurDataObject != NULL)
2800 {
2801 m_pCurDataObject.Release();
2802 }
2803
2804 m_iDragOverItem = 0;
2805
2806 return S_OK;
2807 }
2808
2809 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2810 {
2811 if (m_pCurDropTarget)
2812 {
2813 m_pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect);
2814 m_pCurDropTarget.Release();
2815 }
2816
2817 m_pCurDataObject.Release();
2818 m_iDragOverItem = 0;
2819 return S_OK;
2820 }
2821
2822 /**********************************************************
2823 * ISVDropSource implementation
2824 */
2825
2826 HRESULT WINAPI CDefView::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
2827 {
2828 TRACE("(%p)\n", this);
2829
2830 if (fEscapePressed)
2831 return DRAGDROP_S_CANCEL;
2832 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2833 return DRAGDROP_S_DROP;
2834 else
2835 return S_OK;
2836 }
2837
2838 HRESULT WINAPI CDefView::GiveFeedback(DWORD dwEffect)
2839 {
2840 TRACE("(%p)\n", this);
2841
2842 return DRAGDROP_S_USEDEFAULTCURSORS;
2843 }
2844
2845 /**********************************************************
2846 * ISVViewObject implementation
2847 */
2848
2849 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)
2850 {
2851 FIXME("Stub: this=%p\n", this);
2852
2853 return E_NOTIMPL;
2854 }
2855
2856 HRESULT WINAPI CDefView::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet)
2857 {
2858 FIXME("Stub: this=%p\n", this);
2859
2860 return E_NOTIMPL;
2861 }
2862
2863 HRESULT WINAPI CDefView::Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze)
2864 {
2865 FIXME("Stub: this=%p\n", this);
2866
2867 return E_NOTIMPL;
2868 }
2869
2870 HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze)
2871 {
2872 FIXME("Stub: this=%p\n", this);
2873
2874 return E_NOTIMPL;
2875 }
2876
2877 HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink)
2878 {
2879 FIXME("partial stub: %p %08x %08x %p\n", this, aspects, advf, pAdvSink);
2880
2881 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2882 m_pAdvSink = pAdvSink;
2883 m_dwAspects = aspects;
2884 m_dwAdvf = advf;
2885
2886 return S_OK;
2887 }
2888
2889 HRESULT WINAPI CDefView::GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink)
2890 {
2891 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects, pAdvf, ppAdvSink);
2892
2893 if (ppAdvSink)
2894 {
2895 *ppAdvSink = m_pAdvSink;
2896 m_pAdvSink.p->AddRef();
2897 }
2898
2899 if (pAspects)
2900 *pAspects = m_dwAspects;
2901
2902 if (pAdvf)
2903 *pAdvf = m_dwAdvf;
2904
2905 return S_OK;
2906 }
2907
2908 HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
2909 {
2910 if (IsEqualIID(guidService, SID_IShellBrowser))
2911 return m_pShellBrowser->QueryInterface(riid, ppvObject);
2912 else if(IsEqualIID(guidService, SID_IFolderView))
2913 return QueryInterface(riid, ppvObject);
2914
2915 return E_NOINTERFACE;
2916 }
2917
2918 /**********************************************************
2919 * IShellView_Constructor
2920 */
2921 HRESULT WINAPI IShellView_Constructor(IShellFolder *pFolder, IShellView **newView)
2922 {
2923 CComObject<CDefView> *theView;
2924 CComPtr<IShellView> result;
2925 HRESULT hResult;
2926
2927 if (newView == NULL)
2928 return E_POINTER;
2929
2930 *newView = NULL;
2931 ATLTRY (theView = new CComObject<CDefView>);
2932
2933 if (theView == NULL)
2934 return E_OUTOFMEMORY;
2935
2936 hResult = theView->QueryInterface(IID_PPV_ARG(IShellView, &result));
2937 if (FAILED (hResult))
2938 {
2939 delete theView;
2940 return hResult;
2941 }
2942
2943 hResult = theView->Initialize (pFolder);
2944 if (FAILED (hResult))
2945 return hResult;
2946 *newView = result.Detach ();
2947
2948 return S_OK;
2949 }