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