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