* Sync up to trunk head (r65426).
[reactos.git] / dll / win32 / shell32 / CDefView.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 HIMAGELIST big_icons, small_icons;
591
592 TRACE("%p\n", this);
593
594 m_ListView.DeleteAllItems();
595
596 if (m_pSF2Parent)
597 {
598 for (int i = 0; 1; i++)
599 {
600 if (FAILED(m_pSF2Parent->GetDetailsOf(NULL, i, &sd)))
601 break;
602 StrRetToStrNW( szTemp, 50, &sd.str, NULL);
603 m_ListView.InsertColumn(i, szTemp, sd.fmt, sd.cxChar * 8);
604
605 }
606 }
607 else
608 {
609 FIXME("no SF2\n");
610 }
611
612 Shell_GetImageLists(&big_icons, &small_icons);
613 m_ListView.SetImageList(big_icons, LVSIL_NORMAL);
614 m_ListView.SetImageList(small_icons, LVSIL_SMALL);
615
616 return TRUE;
617 }
618
619 /**********************************************************
620 * ShellView_CompareItems()
621 *
622 * NOTES
623 * internal, CALLBACK for DSA_Sort
624 */
625 INT CALLBACK CDefView::CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
626 {
627 int ret;
628 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
629
630 if (!lpData)
631 return 0;
632
633 IShellFolder* psf = reinterpret_cast<IShellFolder*>(lpData);
634 PCUIDLIST_RELATIVE pidl1 = reinterpret_cast<PCUIDLIST_RELATIVE>(lParam1);
635 PCUIDLIST_RELATIVE pidl2 = reinterpret_cast<PCUIDLIST_RELATIVE>(lParam2);
636
637 ret = (SHORT)SCODE_CODE(psf->CompareIDs(0, pidl1, pidl2));
638 TRACE("ret=%i\n", ret);
639
640 return ret;
641 }
642
643 /*************************************************************************
644 * ShellView_ListViewCompareItems
645 *
646 * Compare Function for the Listview (FileOpen Dialog)
647 *
648 * PARAMS
649 * lParam1 [I] the first ItemIdList to compare with
650 * lParam2 [I] the second ItemIdList to compare with
651 * lpData [I] The column ID for the header Ctrl to process
652 *
653 * RETURNS
654 * A negative value if the first item should precede the second,
655 * a positive value if the first item should follow the second,
656 * or zero if the two items are equivalent
657 *
658 * NOTES
659 * FIXME: function does what ShellView_CompareItems is supposed to do.
660 * unify it and figure out how to use the undocumented first parameter
661 * of IShellFolder_CompareIDs to do the job this function does and
662 * move this code to IShellFolder.
663 * make LISTVIEW_SORT_INFO obsolete
664 * the way this function works is only usable if we had only
665 * filesystemfolders (25/10/99 jsch)
666 */
667 INT CALLBACK CDefView::ListViewCompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
668 {
669 INT nDiff = 0;
670 FILETIME fd1, fd2;
671 char strName1[MAX_PATH], strName2[MAX_PATH];
672 BOOL bIsFolder1, bIsFolder2, bIsBothFolder;
673 PCUIDLIST_RELATIVE pidl1 = reinterpret_cast<PCUIDLIST_RELATIVE>(lParam1);
674 PCUIDLIST_RELATIVE pidl2 = reinterpret_cast<PCUIDLIST_RELATIVE>(lParam2);
675 LISTVIEW_SORT_INFO *pSortInfo = reinterpret_cast<LPLISTVIEW_SORT_INFO>(lpData);
676
677
678 bIsFolder1 = _ILIsFolder(pidl1);
679 bIsFolder2 = _ILIsFolder(pidl2);
680 bIsBothFolder = bIsFolder1 && bIsFolder2;
681
682 /* When sorting between a File and a Folder, the Folder gets sorted first */
683 if ( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
684 {
685 nDiff = bIsFolder1 ? -1 : 1;
686 }
687 else
688 {
689 /* Sort by Time: Folders or Files can be sorted */
690
691 if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
692 {
693 _ILGetFileDateTime(pidl1, &fd1);
694 _ILGetFileDateTime(pidl2, &fd2);
695 nDiff = CompareFileTime(&fd2, &fd1);
696 }
697 /* Sort by Attribute: Folder or Files can be sorted */
698 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
699 {
700 _ILGetFileAttributes(pidl1, strName1, MAX_PATH);
701 _ILGetFileAttributes(pidl2, strName2, MAX_PATH);
702 nDiff = lstrcmpiA(strName1, strName2);
703 }
704 /* Sort by FileName: Folder or Files can be sorted */
705 else if (pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
706 {
707 /* Sort by Text */
708 _ILSimpleGetText(pidl1, strName1, MAX_PATH);
709 _ILSimpleGetText(pidl2, strName2, MAX_PATH);
710 nDiff = lstrcmpiA(strName1, strName2);
711 }
712 /* Sort by File Size, Only valid for Files */
713 else if (pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
714 {
715 nDiff = (INT)(_ILGetFileSize(pidl1, NULL, 0) - _ILGetFileSize(pidl2, NULL, 0));
716 }
717 /* Sort by File Type, Only valid for Files */
718 else if (pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
719 {
720 /* Sort by Type */
721 _ILGetFileType(pidl1, strName1, MAX_PATH);
722 _ILGetFileType(pidl2, strName2, MAX_PATH);
723 nDiff = lstrcmpiA(strName1, strName2);
724 }
725 }
726 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
727
728 if (nDiff == 0)
729 {
730 _ILSimpleGetText(pidl1, strName1, MAX_PATH);
731 _ILSimpleGetText(pidl2, strName2, MAX_PATH);
732 nDiff = lstrcmpiA(strName1, strName2);
733 }
734
735 if (!pSortInfo->bIsAscending)
736 {
737 nDiff = -nDiff;
738 }
739
740 return nDiff;
741 }
742
743 PCUITEMID_CHILD CDefView::_PidlByItem(int i)
744 {
745 return reinterpret_cast<PCUITEMID_CHILD>(m_ListView.GetItemData(i));
746 }
747
748 PCUITEMID_CHILD CDefView::_PidlByItem(LVITEM& lvItem)
749 {
750 return reinterpret_cast<PCUITEMID_CHILD>(lvItem.lParam);
751 }
752
753 /**********************************************************
754 * LV_FindItemByPidl()
755 */
756 int CDefView::LV_FindItemByPidl(PCUITEMID_CHILD pidl)
757 {
758 int cItems = m_ListView.GetItemCount();
759
760 for (int i = 0; i<cItems; i++)
761 {
762 PCUITEMID_CHILD currentpidl = _PidlByItem(i);
763 HRESULT hr = m_pSFParent->CompareIDs(0, pidl, currentpidl);
764
765 if (SUCCEEDED(hr) && !HRESULT_CODE(hr))
766 {
767 return i;
768 }
769 }
770 return -1;
771 }
772
773 /**********************************************************
774 * LV_AddItem()
775 */
776 BOOLEAN CDefView::LV_AddItem(PCUITEMID_CHILD pidl)
777 {
778 LVITEMW lvItem;
779
780 TRACE("(%p)(pidl=%p)\n", this, pidl);
781
782 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/
783 lvItem.iItem = m_ListView.GetItemCount(); /*add the item to the end of the list*/
784 lvItem.iSubItem = 0;
785 lvItem.lParam = reinterpret_cast<LPARAM>(ILClone(pidl)); /*set the item's data*/
786 lvItem.pszText = LPSTR_TEXTCALLBACKW; /*get text on a callback basis*/
787 lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/
788
789 if (m_ListView.InsertItem(&lvItem) == -1)
790 return FALSE;
791 else
792 return TRUE;
793 }
794
795 /**********************************************************
796 * LV_DeleteItem()
797 */
798 BOOLEAN CDefView::LV_DeleteItem(PCUITEMID_CHILD pidl)
799 {
800 int nIndex;
801
802 TRACE("(%p)(pidl=%p)\n", this, pidl);
803
804 nIndex = LV_FindItemByPidl(pidl);
805
806 return (-1 == m_ListView.DeleteItem(nIndex)) ? FALSE : TRUE;
807 }
808
809 /**********************************************************
810 * LV_RenameItem()
811 */
812 BOOLEAN CDefView::LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew)
813 {
814 int nItem;
815 LVITEMW lvItem;
816
817 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", this, pidlOld, pidlNew);
818
819 nItem = LV_FindItemByPidl(pidlOld);
820
821 if ( -1 != nItem )
822 {
823 lvItem.mask = LVIF_PARAM; /* only the pidl */
824 lvItem.iItem = nItem;
825 m_ListView.GetItem(&lvItem);
826
827 SHFree(reinterpret_cast<LPVOID>(lvItem.lParam));
828 lvItem.mask = LVIF_PARAM|LVIF_IMAGE;
829 lvItem.iItem = nItem;
830 lvItem.lParam = reinterpret_cast<LPARAM>(ILClone(pidlNew)); /* set the item's data */
831 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0);
832 m_ListView.SetItem(&lvItem);
833 m_ListView.Update(nItem);
834 return TRUE; /* FIXME: better handling */
835 }
836
837 return FALSE;
838 }
839
840 /**********************************************************
841 * ShellView_FillList()
842 *
843 * - gets the objectlist from the shellfolder
844 * - sorts the list
845 * - fills the list into the view
846 */
847 INT CALLBACK CDefView::fill_list( LPVOID ptr, LPVOID arg )
848 {
849 PITEMID_CHILD pidl = static_cast<PITEMID_CHILD>(ptr);
850 CDefView *pThis = static_cast<CDefView *>(arg);
851
852 /* in a commdlg This works as a filemask*/
853 if (pThis->IncludeObject(pidl) == S_OK)
854 pThis->LV_AddItem(pidl);
855
856 SHFree(pidl);
857 return TRUE;
858 }
859
860 HRESULT CDefView::FillList()
861 {
862 CComPtr<IEnumIDList> pEnumIDList;
863 PITEMID_CHILD pidl;
864 DWORD dwFetched;
865 HRESULT hRes;
866 HDPA hdpa;
867
868 TRACE("%p\n", this);
869
870 /* get the itemlist from the shfolder*/
871 hRes = m_pSFParent->EnumObjects(m_hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
872 if (hRes != S_OK)
873 {
874 if (hRes == S_FALSE)
875 return(NOERROR);
876 return(hRes);
877 }
878
879 /* create a pointer array */
880 hdpa = DPA_Create(16);
881 if (!hdpa)
882 {
883 return(E_OUTOFMEMORY);
884 }
885
886 /* copy the items into the array*/
887 while((S_OK == pEnumIDList->Next(1, &pidl, &dwFetched)) && dwFetched)
888 {
889 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
890 {
891 SHFree(pidl);
892 }
893 }
894
895 /* sort the array */
896 DPA_Sort(hdpa, CompareItems, reinterpret_cast<LPARAM>(m_pSFParent.p));
897
898 /*turn the listview's redrawing off*/
899 m_ListView.SetRedraw(FALSE);
900
901 DPA_DestroyCallback( hdpa, fill_list, this);
902
903 /*turn the listview's redrawing back on and force it to draw*/
904 m_ListView.SetRedraw(TRUE);
905
906 return S_OK;
907 }
908
909 LRESULT CDefView::OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
910 {
911 m_ListView.UpdateWindow();
912 bHandled = FALSE;
913 return 0;
914 }
915
916 LRESULT CDefView::OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
917 {
918 return m_ListView.SendMessageW(uMsg, 0, 0);
919 }
920
921 LRESULT CDefView::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
922 {
923 if (m_hMenu)
924 DestroyMenu(m_hMenu);
925 RevokeDragDrop(m_hWnd);
926 SHChangeNotifyDeregister(m_hNotify);
927 bHandled = FALSE;
928 return 0;
929 }
930
931 LRESULT CDefView::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
932 {
933 /* redirect to parent */
934 if (m_FolderSettings.fFlags & (FWF_DESKTOP | FWF_TRANSPARENT))
935 return SendMessageW(GetParent(), WM_ERASEBKGND, wParam, lParam);
936
937 bHandled = FALSE;
938 return 0;
939 }
940
941 LRESULT CDefView::OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
942 {
943 /* Update desktop labels color */
944 UpdateListColors();
945
946 /* Forward WM_SYSCOLORCHANGE to common controls */
947 return m_ListView.SendMessageW(uMsg, 0, 0);
948 }
949
950 LRESULT CDefView::OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
951 {
952 return reinterpret_cast<LRESULT>(m_pShellBrowser.p);
953 }
954
955 /**********************************************************
956 * ShellView_OnCreate()
957 */
958 LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
959 {
960 CComPtr<IDropTarget> pdt;
961 SHChangeNotifyEntry ntreg;
962 CComPtr<IPersistFolder2> ppf2;
963
964 TRACE("%p\n", this);
965
966 if(CreateList())
967 {
968 if(InitList())
969 {
970 FillList();
971 }
972 }
973
974 if (SUCCEEDED(QueryInterface(IID_PPV_ARG(IDropTarget, &pdt))))
975 {
976 if (FAILED(RegisterDragDrop(m_hWnd, pdt)))
977 ERR("Registering Drag Drop Failed");
978 }
979
980 /* register for receiving notifications */
981 m_pSFParent->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2));
982 if (ppf2)
983 {
984 PIDLIST_ABSOLUTE pidlParent;
985 ppf2->GetCurFolder(&pidlParent);
986 ntreg.fRecursive = TRUE;
987 ntreg.pidl = pidlParent;
988 m_hNotify = SHChangeNotifyRegister(m_hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
989 SHFree(pidlParent);
990 }
991
992 m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_SHELLVIEW));
993
994 return S_OK;
995 }
996
997 /**********************************************************
998 * #### Handling of the menus ####
999 */
1000
1001 HMENU CDefView::BuildFileMenu()
1002 {
1003 HRESULT hr;
1004 CComPtr<IContextMenu> cm;
1005
1006 GetSelections();
1007
1008 hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IContextMenu, &cm));
1009 if (FAILED(hr))
1010 return NULL;
1011
1012 HMENU hmenu = CreatePopupMenu();
1013
1014 //FIXME: get proper numbers ?
1015 const UINT first = 0x7800;
1016 const UINT last = 0x7A00;
1017 hr = cm->QueryContextMenu(hmenu, 0, first, last, 0);
1018 if (FAILED(hr))
1019 return NULL;
1020
1021 // TODO: filter or something
1022
1023 return hmenu;
1024 }
1025
1026 void CDefView::PrepareShowFileMenu(HMENU hSubMenu)
1027 {
1028 TRACE("(%p)->(submenu=%p) stub\n", this, hSubMenu);
1029
1030 if (!hSubMenu)
1031 return;
1032
1033 /* Cleanup the items added previously */
1034 for (int i = 0; i < GetMenuItemCount(hSubMenu); )
1035 {
1036 MENUITEMINFOW mii;
1037 mii.cbSize = sizeof(mii);
1038 mii.fMask = MIIM_ID;
1039 GetMenuItemInfoW(hSubMenu, i, TRUE, &mii);
1040
1041 if (mii.wID < 0x8000)
1042 {
1043 DeleteMenu(hSubMenu, i, MF_BYPOSITION);
1044 }
1045 else
1046 {
1047 i++;
1048 }
1049 }
1050
1051 /* Insert This item at the beginning of the menu. */
1052 _InsertMenuItemW(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
1053 _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM + 4, MFT_STRING, L"Properties", MFS_DISABLED);
1054 _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM + 3, MFT_STRING, L"Rename", MFS_DISABLED);
1055 _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM + 2, MFT_STRING, L"Delete", MFS_DISABLED);
1056 _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM + 1, MFT_STRING, L"Create Shortcut", MFS_DISABLED);
1057 _InsertMenuItemW(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
1058 _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, L"New", MFS_ENABLED);
1059
1060 HMENU menubase = BuildFileMenu();
1061 if (menubase)
1062 {
1063 int count = ::GetMenuItemCount(menubase);
1064
1065 for (int i = 0; i < count; i++)
1066 {
1067 WCHAR label[128];
1068
1069 MENUITEMINFOW mii = { 0 };
1070 mii.cbSize = sizeof(mii);
1071 mii.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_DATA | MIIM_STRING | MIIM_BITMAP | MIIM_FTYPE;
1072 mii.dwTypeData = label;
1073 mii.cch = _countof(label);
1074 ::GetMenuItemInfoW(menubase, i, TRUE, &mii);
1075
1076 TRACE("Adding item %d label %S type %d\n", mii.wID, mii.dwTypeData, mii.fType);
1077
1078 mii.fType |= MFT_RADIOCHECK;
1079
1080 ::InsertMenuItemW(hSubMenu, IDM_MYFILEITEM, FALSE, &mii);
1081 }
1082
1083 _InsertMenuItemW(hSubMenu, IDM_MYFILEITEM, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
1084
1085 ::DestroyMenu(menubase);
1086 }
1087 TRACE("--\n");
1088 }
1089
1090 void CDefView::PrepareShowViewMenu(HMENU hSubMenu)
1091 {
1092 TRACE("(%p)->(submenu=%p)\n", this, hSubMenu);
1093
1094 if (!hSubMenu)
1095 return;
1096
1097 if (m_FolderSettings.ViewMode >= FVM_FIRST && m_FolderSettings.ViewMode <= FVM_LAST)
1098 {
1099 UINT iItemFirst = FCIDM_SHVIEW_BIGICON;
1100 UINT iItemLast = iItemFirst + FVM_LAST - FVM_FIRST;
1101 UINT iItem = iItemFirst + m_FolderSettings.ViewMode - FVM_FIRST;
1102 CheckMenuRadioItem(hSubMenu, iItemFirst, iItemLast, iItem, MF_BYCOMMAND);
1103 }
1104 }
1105
1106 /**********************************************************
1107 * ShellView_GetSelections()
1108 *
1109 * - fills the m_apidl list with the selected objects
1110 *
1111 * RETURNS
1112 * number of selected items
1113 */
1114 UINT CDefView::GetSelections()
1115 {
1116 SHFree(m_apidl);
1117
1118 m_cidl = m_ListView.GetSelectedCount();
1119 m_apidl = reinterpret_cast<PCUITEMID_CHILD_ARRAY>(SHAlloc(m_cidl * sizeof(PCUITEMID_CHILD)));
1120 if (!m_apidl)
1121 {
1122 m_cidl = 0;
1123 return 0;
1124 }
1125
1126 TRACE("-- Items selected =%u\n", m_cidl);
1127
1128 UINT i = 0;
1129 int lvIndex = -1;
1130 while ((lvIndex = m_ListView.GetNextItem(lvIndex, LVNI_SELECTED)) > -1)
1131 {
1132 m_apidl[i] = _PidlByItem(lvIndex);
1133 i++;
1134 if (i == m_cidl)
1135 break;
1136 TRACE("-- selected Item found\n");
1137 }
1138
1139 return m_cidl;
1140 }
1141
1142 /**********************************************************
1143 * ShellView_OpenSelectedItems()
1144 */
1145 HRESULT CDefView::OpenSelectedItems()
1146 {
1147 HMENU hMenu;
1148 CMINVOKECOMMANDINFO cmi;
1149 UINT uCommand;
1150 HRESULT hResult;
1151
1152 m_cidl = m_ListView.GetSelectedCount();
1153 if (m_cidl == 0)
1154 return S_OK;
1155
1156 hResult = OnDefaultCommand();
1157 if (hResult == S_OK)
1158 return hResult;
1159
1160 hMenu = CreatePopupMenu();
1161 if (!hMenu)
1162 return E_FAIL;
1163
1164 hResult = GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IContextMenu, &m_pCM));
1165 if (FAILED(hResult))
1166 goto cleanup;
1167
1168 hResult = IUnknown_SetSite(m_pCM, (IShellView *)this);
1169 //if (FAILED( hResult))
1170 // goto cleanup;
1171
1172 hResult = m_pCM->QueryContextMenu(hMenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY);
1173 if (FAILED(hResult))
1174 goto cleanup;
1175
1176 uCommand = GetMenuDefaultItem(hMenu, FALSE, 0);
1177 if (uCommand == (UINT)-1)
1178 {
1179 hResult = E_FAIL;
1180 goto cleanup;
1181 }
1182
1183 ZeroMemory(&cmi, sizeof(cmi));
1184 cmi.cbSize = sizeof(cmi);
1185 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1186 cmi.hwnd = m_hWnd;
1187
1188 hResult = m_pCM->InvokeCommand(&cmi);
1189
1190 cleanup:
1191
1192 if (hMenu)
1193 DestroyMenu(hMenu);
1194
1195 if (m_pCM)
1196 {
1197 IUnknown_SetSite(m_pCM, NULL);
1198 m_pCM.Release();
1199 }
1200
1201 return hResult;
1202 }
1203
1204 /**********************************************************
1205 * ShellView_DoContextMenu()
1206 */
1207 LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1208 {
1209 WORD x;
1210 WORD y;
1211 UINT uCommand;
1212 HMENU hMenu;
1213 CMINVOKECOMMANDINFO cmi;
1214 HRESULT hResult;
1215
1216 // for some reason I haven't figured out, we sometimes recurse into this method
1217 if (m_pCM != NULL)
1218 return 0;
1219
1220 x = LOWORD(lParam);
1221 y = HIWORD(lParam);
1222
1223 TRACE("(%p)->(0x%08x 0x%08x) stub\n", this, x, y);
1224
1225 hMenu = CreatePopupMenu();
1226 if (!hMenu)
1227 return E_FAIL;
1228
1229 m_cidl = m_ListView.GetSelectedCount();
1230
1231 hResult = GetItemObject( m_cidl ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
1232 if (FAILED( hResult))
1233 goto cleanup;
1234
1235 hResult = IUnknown_SetSite(m_pCM, (IShellView *)this);
1236 //if (FAILED( hResult))
1237 // goto cleanup;
1238
1239 hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
1240 if (FAILED( hResult))
1241 goto cleanup;
1242
1243 if (m_FolderSettings.fFlags & FWF_DESKTOP)
1244 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
1245
1246 uCommand = TrackPopupMenu(hMenu,
1247 TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
1248 x, y, 0, m_hWnd, NULL);
1249 if (uCommand == 0)
1250 goto cleanup;
1251
1252 if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK)
1253 goto cleanup;
1254
1255 ZeroMemory(&cmi, sizeof(cmi));
1256 cmi.cbSize = sizeof(cmi);
1257 cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1258 cmi.hwnd = m_hWnd;
1259 m_pCM->InvokeCommand(&cmi);
1260
1261 cleanup:
1262
1263 if (m_pCM)
1264 {
1265 IUnknown_SetSite(m_pCM, NULL);
1266 m_pCM.Release();
1267 }
1268
1269 if (hMenu)
1270 DestroyMenu(hMenu);
1271
1272 return 0;
1273 }
1274
1275 LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
1276 {
1277 HRESULT hResult;
1278 CMINVOKECOMMANDINFO cmi;
1279 HMENU hMenu;
1280
1281 hMenu = CreatePopupMenu();
1282 if (!hMenu)
1283 return 0;
1284
1285 hResult = GetItemObject( bUseSelection ? 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 ZeroMemory(&cmi, sizeof(cmi));
1298 cmi.cbSize = sizeof(cmi);
1299 cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1300 cmi.hwnd = m_hWnd;
1301 m_pCM->InvokeCommand(&cmi);
1302
1303 cleanup:
1304
1305 if (m_pCM)
1306 {
1307 IUnknown_SetSite(m_pCM, NULL);
1308 m_pCM.Release();
1309 }
1310
1311 if (hMenu)
1312 DestroyMenu(hMenu);
1313
1314 return 0;
1315 }
1316
1317 /**********************************************************
1318 * ##### message handling #####
1319 */
1320
1321 /**********************************************************
1322 * ShellView_OnSize()
1323 */
1324 LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1325 {
1326 WORD wWidth;
1327 WORD wHeight;
1328
1329 wWidth = LOWORD(lParam);
1330 wHeight = HIWORD(lParam);
1331
1332 TRACE("%p width=%u height=%u\n", this, wWidth, wHeight);
1333
1334 /*resize the ListView to fit our window*/
1335 if (m_ListView)
1336 {
1337 ::MoveWindow(m_ListView, 0, 0, wWidth, wHeight, TRUE);
1338 }
1339
1340 return 0;
1341 }
1342
1343 /**********************************************************
1344 * ShellView_OnDeactivate()
1345 *
1346 * NOTES
1347 * internal
1348 */
1349 void CDefView::OnDeactivate()
1350 {
1351 TRACE("%p\n", this);
1352
1353 if (m_uState != SVUIA_DEACTIVATE)
1354 {
1355 // TODO: cleanup menu after deactivation
1356
1357 m_uState = SVUIA_DEACTIVATE;
1358 }
1359 }
1360
1361 void CDefView::DoActivate(UINT uState)
1362 {
1363 TRACE("%p uState=%x\n", this, uState);
1364
1365 /*don't do anything if the state isn't really changing */
1366 if (m_uState == uState)
1367 {
1368 return;
1369 }
1370
1371 if (uState == SVUIA_DEACTIVATE)
1372 {
1373 OnDeactivate();
1374 }
1375 else
1376 {
1377 if(m_hMenu)
1378 {
1379 if (!m_menusLoaded)
1380 {
1381 MENUITEMINFOW mii = { 0 };
1382
1383 /* initialize EDIT menu */
1384 mii.cbSize = sizeof(mii);
1385 mii.fMask = MIIM_SUBMENU;
1386 if (::GetMenuItemInfoW(m_hMenu, FCIDM_MENU_EDIT, FALSE, &mii))
1387 {
1388 HMENU hSubMenu = mii.hSubMenu;
1389
1390 HMENU menubase = ::LoadMenuW(shell32_hInstance, L"MENU_003");
1391
1392 int count = ::GetMenuItemCount(menubase);
1393 for (int i = 0; i < count; i++)
1394 {
1395 WCHAR label[128];
1396
1397 ZeroMemory(&mii, sizeof(mii));
1398 mii.cbSize = sizeof(mii);
1399 mii.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_DATA | MIIM_STRING | MIIM_BITMAP | MIIM_FTYPE;
1400 mii.dwTypeData = label;
1401 mii.cch = _countof(label);
1402 ::GetMenuItemInfoW(menubase, i, TRUE, &mii);
1403
1404 TRACE("Adding item %d label %S type %d\n", mii.wID, mii.dwTypeData, mii.fType);
1405
1406 mii.fType |= MFT_RADIOCHECK;
1407
1408 ::InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
1409 }
1410
1411 ::DestroyMenu(menubase);
1412 }
1413
1414 /* initialize VIEW menu */
1415
1416 mii.cbSize = sizeof(mii);
1417 mii.fMask = MIIM_SUBMENU;
1418 if (::GetMenuItemInfoW(m_hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1419 {
1420 HMENU menubase = ::LoadMenuW(shell32_hInstance, L"MENU_001");
1421
1422 HMENU hSubMenu = mii.hSubMenu;
1423
1424 m_hView = CreatePopupMenu();
1425
1426 _InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
1427
1428 int count = ::GetMenuItemCount(menubase);
1429 for (int i = 0; i < count; i++)
1430 {
1431 WCHAR label[128];
1432
1433 ZeroMemory(&mii, sizeof(mii));
1434 mii.cbSize = sizeof(mii);
1435 mii.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_DATA | MIIM_STRING | MIIM_BITMAP | MIIM_FTYPE;
1436 mii.dwTypeData = label;
1437 mii.cch = _countof(label);
1438 ::GetMenuItemInfoW(menubase, i, TRUE, &mii);
1439
1440 ::AppendMenuW(m_hView, mii.fType, mii.wID, mii.dwTypeData);
1441
1442 TRACE("Adding item %d label %S type %d\n", mii.wID, mii.dwTypeData, mii.fType);
1443
1444 mii.fType |= MFT_RADIOCHECK;
1445
1446 ::InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
1447 }
1448
1449 ::DestroyMenu(menubase);
1450 }
1451
1452
1453 TRACE("-- before fnSetMenuSB\n");
1454 m_pShellBrowser->SetMenuSB(m_hMenu, 0, m_hWnd);
1455
1456 m_menusLoaded = TRUE;
1457 }
1458 }
1459
1460 if (SVUIA_ACTIVATE_FOCUS == uState)
1461 {
1462 m_ListView.SetFocus();
1463 }
1464 }
1465
1466 m_uState = uState;
1467 TRACE("--\n");
1468 }
1469
1470 /**********************************************************
1471 * ShellView_OnActivate()
1472 */
1473 LRESULT CDefView::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1474 {
1475 DoActivate(SVUIA_ACTIVATE_FOCUS);
1476 return 0;
1477 }
1478
1479 /**********************************************************
1480 * ShellView_OnSetFocus()
1481 *
1482 */
1483 LRESULT CDefView::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1484 {
1485 TRACE("%p\n", this);
1486
1487 /* Tell the browser one of our windows has received the focus. This
1488 should always be done before merging menus (OnActivate merges the
1489 menus) if one of our windows has the focus.*/
1490
1491 m_pShellBrowser->OnViewWindowActive(this);
1492 DoActivate(SVUIA_ACTIVATE_FOCUS);
1493
1494 /* Set the focus to the listview */
1495 m_ListView.SetFocus();
1496
1497 /* Notify the ICommDlgBrowser interface */
1498 OnStateChange(CDBOSC_SETFOCUS);
1499
1500 return 0;
1501 }
1502
1503 /**********************************************************
1504 * ShellView_OnKillFocus()
1505 */
1506 LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1507 {
1508 TRACE("(%p) stub\n", this);
1509
1510 DoActivate(SVUIA_ACTIVATE_NOFOCUS);
1511 /* Notify the ICommDlgBrowser */
1512 OnStateChange(CDBOSC_KILLFOCUS);
1513
1514 return 0;
1515 }
1516
1517 /**********************************************************
1518 * ShellView_OnCommand()
1519 *
1520 * NOTES
1521 * the CmdID's are the ones from the context menu
1522 */
1523 LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1524 {
1525 DWORD dwCmdID;
1526 DWORD dwCmd;
1527 HWND hwndCmd;
1528
1529 dwCmdID = GET_WM_COMMAND_ID(wParam, lParam);
1530 dwCmd = GET_WM_COMMAND_CMD(wParam, lParam);
1531 hwndCmd = GET_WM_COMMAND_HWND(wParam, lParam);
1532
1533 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n", this, dwCmdID, dwCmd, hwndCmd);
1534
1535 switch (dwCmdID)
1536 {
1537 case FCIDM_SHVIEW_SMALLICON:
1538 m_FolderSettings.ViewMode = FVM_SMALLICON;
1539 SetStyle (LVS_SMALLICON, LVS_TYPEMASK);
1540 CheckToolbar();
1541 break;
1542
1543 case FCIDM_SHVIEW_BIGICON:
1544 m_FolderSettings.ViewMode = FVM_ICON;
1545 SetStyle (LVS_ICON, LVS_TYPEMASK);
1546 CheckToolbar();
1547 break;
1548
1549 case FCIDM_SHVIEW_LISTVIEW:
1550 m_FolderSettings.ViewMode = FVM_LIST;
1551 SetStyle (LVS_LIST, LVS_TYPEMASK);
1552 CheckToolbar();
1553 break;
1554
1555 case FCIDM_SHVIEW_REPORTVIEW:
1556 m_FolderSettings.ViewMode = FVM_DETAILS;
1557 SetStyle (LVS_REPORT, LVS_TYPEMASK);
1558 CheckToolbar();
1559 break;
1560
1561 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1562 case 0x30:
1563 case 0x31:
1564 case 0x32:
1565 case 0x33:
1566 m_sortInfo.nHeaderID = dwCmdID - 0x30;
1567 m_sortInfo.bIsAscending = TRUE;
1568 m_sortInfo.nLastHeaderID = m_sortInfo.nHeaderID;
1569 m_ListView.SortItems(ListViewCompareItems, &m_sortInfo);
1570 break;
1571
1572 case FCIDM_SHVIEW_REFRESH:
1573 Refresh();
1574 break;
1575
1576 case FCIDM_SHVIEW_DELETE:
1577 case FCIDM_SHVIEW_CUT:
1578 case FCIDM_SHVIEW_COPY:
1579 case FCIDM_SHVIEW_RENAME:
1580 return OnExplorerCommand(dwCmdID, TRUE);
1581
1582 case FCIDM_SHVIEW_INSERT:
1583 case FCIDM_SHVIEW_UNDO:
1584 case FCIDM_SHVIEW_INSERTLINK:
1585 case FCIDM_SHVIEW_NEWFOLDER:
1586 return OnExplorerCommand(dwCmdID, FALSE);
1587 default:
1588 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID);
1589 }
1590
1591 return 0;
1592 }
1593
1594 /**********************************************************
1595 * ShellView_OnNotify()
1596 */
1597
1598 LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1599 {
1600 UINT CtlID;
1601 LPNMHDR lpnmh;
1602 LPNMLISTVIEW lpnmlv;
1603 NMLVDISPINFOW *lpdi;
1604 PCUITEMID_CHILD pidl;
1605 BOOL unused;
1606
1607 CtlID = wParam;
1608 lpnmh = (LPNMHDR)lParam;
1609 lpnmlv = (LPNMLISTVIEW)lpnmh;
1610 lpdi = (NMLVDISPINFOW *)lpnmh;
1611
1612 TRACE("%p CtlID=%u lpnmh->code=%x\n", this, CtlID, lpnmh->code);
1613
1614 switch (lpnmh->code)
1615 {
1616 case NM_SETFOCUS:
1617 TRACE("-- NM_SETFOCUS %p\n", this);
1618 OnSetFocus(0, 0, 0, unused);
1619 break;
1620
1621 case NM_KILLFOCUS:
1622 TRACE("-- NM_KILLFOCUS %p\n", this);
1623 OnDeactivate();
1624 /* Notify the ICommDlgBrowser interface */
1625 OnStateChange(CDBOSC_KILLFOCUS);
1626 break;
1627
1628 case NM_CUSTOMDRAW:
1629 TRACE("-- NM_CUSTOMDRAW %p\n", this);
1630 return CDRF_DODEFAULT;
1631
1632 case NM_RELEASEDCAPTURE:
1633 TRACE("-- NM_RELEASEDCAPTURE %p\n", this);
1634 break;
1635
1636 case NM_CLICK:
1637 TRACE("-- NM_CLICK %p\n", this);
1638 break;
1639
1640 case NM_RCLICK:
1641 TRACE("-- NM_RCLICK %p\n", this);
1642 break;
1643
1644 case NM_DBLCLK:
1645 TRACE("-- NM_DBLCLK %p\n", this);
1646 OpenSelectedItems();
1647 break;
1648
1649 case NM_RETURN:
1650 TRACE("-- NM_RETURN %p\n", this);
1651 OpenSelectedItems();
1652 break;
1653
1654 case HDN_ENDTRACKW:
1655 TRACE("-- HDN_ENDTRACKW %p\n", this);
1656 /*nColumn1 = m_ListView.GetColumnWidth(0);
1657 nColumn2 = m_ListView.GetColumnWidth(1);*/
1658 break;
1659
1660 case LVN_DELETEITEM:
1661 TRACE("-- LVN_DELETEITEM %p\n", this);
1662
1663 /*delete the pidl because we made a copy of it*/
1664 SHFree(reinterpret_cast<LPVOID>(lpnmlv->lParam));
1665
1666 break;
1667
1668 case LVN_DELETEALLITEMS:
1669 TRACE("-- LVN_DELETEALLITEMS %p\n", this);
1670 return FALSE;
1671
1672 case LVN_INSERTITEM:
1673 TRACE("-- LVN_INSERTITEM (STUB)%p\n", this);
1674 break;
1675
1676 case LVN_ITEMACTIVATE:
1677 TRACE("-- LVN_ITEMACTIVATE %p\n", this);
1678 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1679 break;
1680
1681 case LVN_COLUMNCLICK:
1682 m_sortInfo.nHeaderID = lpnmlv->iSubItem;
1683 if (m_sortInfo.nLastHeaderID == m_sortInfo.nHeaderID)
1684 m_sortInfo.bIsAscending = !m_sortInfo.bIsAscending;
1685 else
1686 m_sortInfo.bIsAscending = TRUE;
1687 m_sortInfo.nLastHeaderID = m_sortInfo.nHeaderID;
1688
1689 m_ListView.SortItems(ListViewCompareItems, &m_sortInfo);
1690 break;
1691
1692 case LVN_GETDISPINFOA:
1693 case LVN_GETDISPINFOW:
1694 TRACE("-- LVN_GETDISPINFO %p\n", this);
1695 pidl = _PidlByItem(lpdi->item);
1696
1697 if (lpdi->item.mask & LVIF_TEXT) /* text requested */
1698 {
1699 if (m_pSF2Parent)
1700 {
1701 SHELLDETAILS sd;
1702 if (FAILED(m_pSF2Parent->GetDetailsOf(pidl, lpdi->item.iSubItem, &sd)))
1703 {
1704 FIXME("failed to get details\n");
1705 break;
1706 }
1707
1708 if (lpnmh->code == LVN_GETDISPINFOA)
1709 {
1710 /* shouldn't happen */
1711 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1712 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1713 TRACE("-- text=%s\n", lpdiA->item.pszText);
1714 }
1715 else /* LVN_GETDISPINFOW */
1716 {
1717 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1718 TRACE("-- text=%s\n", debugstr_w(lpdi->item.pszText));
1719 }
1720 }
1721 else
1722 {
1723 FIXME("no SF2\n");
1724 }
1725 }
1726 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1727 {
1728 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
1729 }
1730 lpdi->item.mask |= LVIF_DI_SETITEM;
1731 break;
1732
1733 case LVN_ITEMCHANGED:
1734 TRACE("-- LVN_ITEMCHANGED %p\n", this);
1735 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1736 break;
1737
1738 case LVN_BEGINDRAG:
1739 case LVN_BEGINRDRAG:
1740 TRACE("-- LVN_BEGINDRAG\n");
1741
1742 if (GetSelections())
1743 {
1744 CComPtr<IDataObject> pda;
1745 DWORD dwAttributes = SFGAO_CANLINK;
1746 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1747
1748 if (SUCCEEDED(m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IDataObject, &pda))))
1749 {
1750 if (SUCCEEDED(m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &dwAttributes)))
1751 {
1752 if (dwAttributes & SFGAO_CANLINK)
1753 {
1754 dwEffect |= DROPEFFECT_LINK;
1755 }
1756 }
1757
1758 CComPtr<IAsyncOperation> piaso;
1759 if (SUCCEEDED(pda->QueryInterface(IID_PPV_ARG(IAsyncOperation, &piaso))))
1760 {
1761 piaso->SetAsyncMode(TRUE);
1762 }
1763
1764 DWORD dwEffect2;
1765 DoDragDrop(pda, this, dwEffect, &dwEffect2);
1766 }
1767 }
1768 break;
1769
1770 case LVN_BEGINLABELEDITW:
1771 {
1772 DWORD dwAttr = SFGAO_CANRENAME;
1773 pidl = _PidlByItem(lpdi->item);
1774
1775 TRACE("-- LVN_BEGINLABELEDITW %p\n", this);
1776
1777 m_pSFParent->GetAttributesOf(1, &pidl, &dwAttr);
1778 if (SFGAO_CANRENAME & dwAttr)
1779 {
1780 m_isEditing = TRUE;
1781 return FALSE;
1782 }
1783 return TRUE;
1784 }
1785
1786 case LVN_ENDLABELEDITW:
1787 {
1788 TRACE("-- LVN_ENDLABELEDITW %p\n", this);
1789
1790 m_isEditing = FALSE;
1791
1792 if (lpdi->item.pszText)
1793 {
1794 HRESULT hr;
1795 LVITEMW lvItem;
1796
1797 pidl = _PidlByItem(lpdi->item);
1798 PITEMID_CHILD pidlNew;
1799 hr = m_pSFParent->SetNameOf(0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidlNew);
1800
1801 if (SUCCEEDED(hr) && pidlNew)
1802 {
1803 lvItem.mask = LVIF_PARAM|LVIF_IMAGE;
1804 lvItem.iItem = lpdi->item.iItem;
1805 lvItem.lParam = reinterpret_cast<LPARAM>(pidlNew);
1806 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0);
1807 m_ListView.SetItem(&lvItem);
1808 m_ListView.Update(lpdi->item.iItem);
1809 return TRUE;
1810 }
1811 }
1812
1813 return FALSE;
1814 }
1815
1816 default:
1817 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh->code);
1818 break;
1819 }
1820
1821 return 0;
1822 }
1823
1824 /**********************************************************
1825 * ShellView_OnChange()
1826 */
1827 LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1828 {
1829 PCIDLIST_ABSOLUTE *Pidls = reinterpret_cast<PCIDLIST_ABSOLUTE*>(wParam);
1830
1831 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam);
1832
1833 switch (lParam)
1834 {
1835 case SHCNE_MKDIR:
1836 case SHCNE_CREATE:
1837 LV_AddItem(ILFindLastID(Pidls[0]));
1838 break;
1839
1840 case SHCNE_RMDIR:
1841 case SHCNE_DELETE:
1842 LV_DeleteItem(ILFindLastID(Pidls[0]));
1843 break;
1844
1845 case SHCNE_RENAMEFOLDER:
1846 case SHCNE_RENAMEITEM:
1847 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[1]));
1848 break;
1849
1850 case SHCNE_UPDATEITEM:
1851 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0]));
1852 break;
1853
1854 case SHCNE_UPDATEDIR:
1855 Refresh();
1856 break;
1857 }
1858 return TRUE;
1859 }
1860
1861 /**********************************************************
1862 * CDefView::OnCustomItem
1863 */
1864 LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1865 {
1866 if (!m_pCM.p)
1867 {
1868 /* no menu */
1869 ERR("no menu!!!\n");
1870 return FALSE;
1871 }
1872
1873 CComPtr<IContextMenu2> pCM2;
1874 HRESULT hres = m_pCM.p->QueryInterface(IID_PPV_ARG(IContextMenu2, &pCM2));
1875 if(FAILED(hres))
1876 return FALSE;
1877
1878 if (pCM2.p->HandleMenuMsg(uMsg, (WPARAM)m_hWnd, lParam) == S_OK)
1879 return TRUE;
1880 else
1881 return FALSE;
1882 }
1883
1884 LRESULT CDefView::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1885 {
1886 /* Wallpaper setting affects drop shadows effect */
1887 if (wParam == SPI_SETDESKWALLPAPER || wParam == 0)
1888 UpdateListColors();
1889
1890 return S_OK;
1891 }
1892
1893 /**********************************************************
1894 * CDefView::OnInitMenuPopup
1895 */
1896 LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1897 {
1898 MENUITEMINFOW mii = { 0 };
1899 HMENU hSubmenu = (HMENU) wParam;
1900
1901 DbgPrint("OnInitMenuPopup lParam=%d\n", lParam);
1902
1903 mii.cbSize = sizeof(mii);
1904 mii.fMask = MIIM_ID | MIIM_SUBMENU;
1905
1906 if (!GetMenuItemInfoW(this->m_hMenu, lParam, TRUE, &mii))
1907 {
1908 DbgPrint("OnInitMenuPopup GetMenuItemInfoW failed!\n");
1909 return FALSE;
1910 }
1911
1912 UINT menuItemId = mii.wID;
1913
1914 if (mii.hSubMenu != hSubmenu)
1915 {
1916 DbgPrint("OnInitMenuPopup submenu does not match!!!!\n");
1917 return FALSE;
1918 }
1919
1920 DbgPrint("OnInitMenuPopup id=%d\n", menuItemId);
1921
1922 switch (menuItemId)
1923 {
1924 case FCIDM_MENU_FILE:
1925 PrepareShowFileMenu(hSubmenu);
1926 break;
1927 case FCIDM_MENU_EDIT:
1928 //PrepareShowEditMenu(hSubmenu);
1929 break;
1930 case FCIDM_MENU_VIEW:
1931 PrepareShowViewMenu(hSubmenu);
1932 break;
1933 }
1934
1935 return FALSE;
1936 }
1937
1938 /**********************************************************
1939 *
1940 *
1941 * The INTERFACE of the IShellView object
1942 *
1943 *
1944 **********************************************************
1945 */
1946
1947 /**********************************************************
1948 * ShellView_GetWindow
1949 */
1950 HRESULT WINAPI CDefView::GetWindow(HWND *phWnd)
1951 {
1952 TRACE("(%p)\n", this);
1953
1954 *phWnd = m_hWnd;
1955
1956 return S_OK;
1957 }
1958
1959 HRESULT WINAPI CDefView::ContextSensitiveHelp(BOOL fEnterMode)
1960 {
1961 FIXME("(%p) stub\n", this);
1962
1963 return E_NOTIMPL;
1964 }
1965
1966 /**********************************************************
1967 * IShellView_TranslateAccelerator
1968 *
1969 * FIXME:
1970 * use the accel functions
1971 */
1972 HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg)
1973 {
1974 if (m_isEditing)
1975 return S_FALSE;
1976
1977 if (lpmsg->message >= WM_KEYFIRST && lpmsg->message <= WM_KEYLAST)
1978 {
1979 if (::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg) != 0)
1980 return S_OK;
1981
1982 TRACE("-- key=0x04%lx\n", lpmsg->wParam) ;
1983 }
1984
1985 return m_pShellBrowser->TranslateAcceleratorSB(lpmsg, 0);
1986 }
1987
1988 HRESULT WINAPI CDefView::EnableModeless(BOOL fEnable)
1989 {
1990 FIXME("(%p) stub\n", this);
1991
1992 return E_NOTIMPL;
1993 }
1994
1995 HRESULT WINAPI CDefView::UIActivate(UINT uState)
1996 {
1997 /*
1998 CHAR szName[MAX_PATH];
1999 */
2000 LRESULT lResult;
2001 int nPartArray[1] = { -1};
2002
2003 TRACE("(%p)->(state=%x) stub\n", this, uState);
2004
2005 /*don't do anything if the state isn't really changing*/
2006 if (m_uState == uState)
2007 {
2008 return S_OK;
2009 }
2010
2011 /*OnActivate handles the menu merging and internal state*/
2012 DoActivate(uState);
2013
2014 /*only do This if we are active*/
2015 if (uState != SVUIA_DEACTIVATE)
2016 {
2017
2018 /*
2019 GetFolderPath is not a method of IShellFolder
2020 IShellFolder_GetFolderPath( m_pSFParent, szName, sizeof(szName) );
2021 */
2022 /* set the number of parts */
2023 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult);
2024
2025 /* set the text for the parts */
2026 /*
2027 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult);
2028 */
2029 }
2030
2031 return S_OK;
2032 }
2033
2034 HRESULT WINAPI CDefView::Refresh()
2035 {
2036 TRACE("(%p)\n", this);
2037
2038 m_ListView.DeleteAllItems();
2039 FillList();
2040
2041 return S_OK;
2042 }
2043
2044 HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd)
2045 {
2046 OLEMENUGROUPWIDTHS omw = { { 0, 0, 0, 0, 0, 0 } };
2047
2048 *phWnd = 0;
2049
2050 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n", this, lpPrevView, lpfs, psb, prcView, phWnd);
2051
2052 if (lpfs != NULL)
2053 TRACE("-- vmode=%x flags=%x\n", lpfs->ViewMode, lpfs->fFlags);
2054 if (prcView != NULL)
2055 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom);
2056
2057 /* Validate the Shell Browser */
2058 if (psb == NULL)
2059 return E_UNEXPECTED;
2060
2061 /*set up the member variables*/
2062 m_pShellBrowser = psb;
2063 m_FolderSettings = *lpfs;
2064
2065 /*get our parent window*/
2066 m_pShellBrowser->GetWindow(&m_hWndParent);
2067
2068 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
2069 m_pCommDlgBrowser = NULL;
2070 if (SUCCEEDED(m_pShellBrowser->QueryInterface(IID_PPV_ARG(ICommDlgBrowser, &m_pCommDlgBrowser))))
2071 {
2072 TRACE("-- CommDlgBrowser\n");
2073 }
2074
2075 Create(m_hWndParent, prcView, NULL, WS_CHILD | WS_TABSTOP, 0, 0U);
2076 if (m_hWnd == NULL)
2077 return E_FAIL;
2078
2079 *phWnd = m_hWnd;
2080
2081 CheckToolbar();
2082
2083 if (!*phWnd)
2084 return E_FAIL;
2085
2086 SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
2087 UpdateWindow();
2088
2089 if (!m_hMenu)
2090 {
2091 m_hMenu = CreateMenu();
2092 m_pShellBrowser->InsertMenusSB(m_hMenu, &omw);
2093 TRACE("-- after fnInsertMenusSB\n");
2094 }
2095
2096 _MergeToolbar();
2097
2098 return S_OK;
2099 }
2100
2101 HRESULT WINAPI CDefView::DestroyViewWindow()
2102 {
2103 TRACE("(%p)\n", this);
2104
2105 /*Make absolutely sure all our UI is cleaned up.*/
2106 UIActivate(SVUIA_DEACTIVATE);
2107
2108 if (m_hAccel)
2109 {
2110 // "Accelerator tables loaded from resources are freed automatically when the application terminates." -- MSDN
2111 m_hAccel = NULL;
2112 }
2113
2114 if (m_hView)
2115 {
2116 DestroyMenu(m_hView);
2117 m_hView = NULL;
2118 }
2119
2120 if (m_hMenu)
2121 {
2122 DestroyMenu(m_hMenu);
2123 m_hView = NULL;
2124 }
2125
2126 if (m_ListView)
2127 {
2128 m_ListView.DestroyWindow();
2129 }
2130
2131 if (m_hWnd)
2132 {
2133 DestroyWindow();
2134 }
2135
2136 m_pShellBrowser.Release();
2137 m_pCommDlgBrowser.Release();
2138
2139 return S_OK;
2140 }
2141
2142 HRESULT WINAPI CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
2143 {
2144 TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs,
2145 m_FolderSettings.ViewMode, m_FolderSettings.fFlags);
2146
2147 if (!lpfs)
2148 return E_INVALIDARG;
2149
2150 *lpfs = m_FolderSettings;
2151 return S_OK;
2152 }
2153
2154 HRESULT WINAPI CDefView::AddPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
2155 {
2156 FIXME("(%p) stub\n", this);
2157
2158 return E_NOTIMPL;
2159 }
2160
2161 HRESULT WINAPI CDefView::SaveViewState()
2162 {
2163 FIXME("(%p) stub\n", this);
2164
2165 return S_OK;
2166 }
2167
2168 HRESULT WINAPI CDefView::SelectItem(PCUITEMID_CHILD pidl, UINT uFlags)
2169 {
2170 int i;
2171
2172 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl, uFlags);
2173
2174 i = LV_FindItemByPidl(pidl);
2175 if (i == -1)
2176 return S_OK;
2177
2178 if(uFlags & SVSI_ENSUREVISIBLE)
2179 m_ListView.EnsureVisible(i, FALSE);
2180
2181 LVITEMW lvItem = {0};
2182 lvItem.mask = LVIF_STATE;
2183 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
2184
2185 while (m_ListView.GetItem(&lvItem))
2186 {
2187 if (lvItem.iItem == i)
2188 {
2189 if (uFlags & SVSI_SELECT)
2190 lvItem.state |= LVIS_SELECTED;
2191 else
2192 lvItem.state &= ~LVIS_SELECTED;
2193
2194 if (uFlags & SVSI_FOCUSED)
2195 lvItem.state &= ~LVIS_FOCUSED;
2196 }
2197 else
2198 {
2199 if (uFlags & SVSI_DESELECTOTHERS)
2200 lvItem.state &= ~LVIS_SELECTED;
2201 }
2202
2203 m_ListView.SetItem(&lvItem);
2204 lvItem.iItem++;
2205 }
2206
2207 if(uFlags & SVSI_EDIT)
2208 m_ListView.EditLabel(i);
2209
2210 return S_OK;
2211 }
2212
2213 HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
2214 {
2215 HRESULT hr = E_NOINTERFACE;
2216
2217 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem, debugstr_guid(&riid), ppvOut);
2218
2219 *ppvOut = NULL;
2220
2221 switch (uItem)
2222 {
2223 case SVGIO_BACKGROUND:
2224 if (IsEqualIID(riid, IID_IContextMenu))
2225 {
2226 //*ppvOut = ISvBgCm_Constructor(m_pSFParent, FALSE);
2227 if (!ppvOut)
2228 hr = E_OUTOFMEMORY;
2229
2230 IContextMenu* pcm;
2231 hr = CDefFolderMenu_Create2(NULL, NULL, 0, NULL, m_pSFParent, NULL, 0, NULL, &pcm);
2232 if (FAILED(hr))
2233 return hr;
2234 *ppvOut = pcm;
2235 }
2236 break;
2237
2238 case SVGIO_SELECTION:
2239 GetSelections();
2240 hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, riid, 0, ppvOut);
2241 break;
2242 }
2243
2244 TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut);
2245
2246 return hr;
2247 }
2248
2249 HRESULT STDMETHODCALLTYPE CDefView::GetCurrentViewMode(UINT *pViewMode)
2250 {
2251 TRACE("(%p)->(%p), stub\n", this, pViewMode);
2252
2253 if (!pViewMode)
2254 return E_INVALIDARG;
2255
2256 *pViewMode = m_FolderSettings.ViewMode;
2257 return S_OK;
2258 }
2259
2260 HRESULT STDMETHODCALLTYPE CDefView::SetCurrentViewMode(UINT ViewMode)
2261 {
2262 DWORD dwStyle;
2263 TRACE("(%p)->(%u), stub\n", this, ViewMode);
2264
2265 /* It's not redundant to check FVM_AUTO because it's a (UINT)-1 */
2266 if (((INT)ViewMode < FVM_FIRST || (INT)ViewMode > FVM_LAST) && ((INT)ViewMode != FVM_AUTO))
2267 return E_INVALIDARG;
2268
2269 /* Windows before Vista uses LVM_SETVIEW and possibly
2270 LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview,
2271 while later versions seem to accomplish this through other
2272 means. */
2273 switch (ViewMode)
2274 {
2275 case FVM_ICON:
2276 dwStyle = LVS_ICON;
2277 break;
2278 case FVM_DETAILS:
2279 dwStyle = LVS_REPORT;
2280 break;
2281 case FVM_SMALLICON:
2282 dwStyle = LVS_SMALLICON;
2283 break;
2284 case FVM_LIST:
2285 dwStyle = LVS_LIST;
2286 break;
2287 default:
2288 {
2289 FIXME("ViewMode %d not implemented\n", ViewMode);
2290 dwStyle = LVS_LIST;
2291 break;
2292 }
2293 }
2294
2295 SetStyle(dwStyle, LVS_TYPEMASK);
2296
2297 /* This will not necessarily be the actual mode set above.
2298 This mimics the behavior of Windows XP. */
2299 m_FolderSettings.ViewMode = ViewMode;
2300
2301 return S_OK;
2302 }
2303
2304 HRESULT STDMETHODCALLTYPE CDefView::GetFolder(REFIID riid, void **ppv)
2305 {
2306 if (m_pSFParent == NULL)
2307 return E_FAIL;
2308
2309 return m_pSFParent->QueryInterface(riid, ppv);
2310 }
2311
2312 HRESULT STDMETHODCALLTYPE CDefView::Item(int iItemIndex, PITEMID_CHILD *ppidl)
2313 {
2314 PCUITEMID_CHILD pidl = _PidlByItem(iItemIndex);
2315 if (pidl)
2316 {
2317 *ppidl = ILClone(pidl);
2318 return S_OK;
2319 }
2320
2321 *ppidl = 0;
2322 return E_INVALIDARG;
2323 }
2324
2325 HRESULT STDMETHODCALLTYPE CDefView::ItemCount(UINT uFlags, int *pcItems)
2326 {
2327 TRACE("(%p)->(%u %p)\n", this, uFlags, pcItems);
2328
2329 if (uFlags != SVGIO_ALLVIEW)
2330 FIXME("some flags unsupported, %x\n", uFlags & ~SVGIO_ALLVIEW);
2331
2332 *pcItems = m_ListView.GetItemCount();
2333
2334 return S_OK;
2335 }
2336
2337 HRESULT STDMETHODCALLTYPE CDefView::Items(UINT uFlags, REFIID riid, void **ppv)
2338 {
2339 return E_NOTIMPL;
2340 }
2341
2342 HRESULT STDMETHODCALLTYPE CDefView::GetSelectionMarkedItem(int *piItem)
2343 {
2344 TRACE("(%p)->(%p)\n", this, piItem);
2345
2346 *piItem = m_ListView.GetSelectionMark();
2347
2348 return S_OK;
2349 }
2350
2351 HRESULT STDMETHODCALLTYPE CDefView::GetFocusedItem(int *piItem)
2352 {
2353 TRACE("(%p)->(%p)\n", this, piItem);
2354
2355 *piItem = m_ListView.GetNextItem(-1, LVNI_FOCUSED);
2356
2357 return S_OK;
2358 }
2359
2360 HRESULT STDMETHODCALLTYPE CDefView::GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt)
2361 {
2362 return E_NOTIMPL;
2363 }
2364
2365 HRESULT STDMETHODCALLTYPE CDefView::GetSpacing(POINT *ppt)
2366 {
2367 TRACE("(%p)->(%p)\n", this, ppt);
2368
2369 if (!m_ListView)
2370 return S_FALSE;
2371
2372 if (ppt)
2373 {
2374 SIZE spacing;
2375 m_ListView.GetItemSpacing(spacing);
2376
2377 ppt->x = spacing.cx;
2378 ppt->y = spacing.cy;
2379 }
2380
2381 return S_OK;
2382 }
2383
2384 HRESULT STDMETHODCALLTYPE CDefView::GetDefaultSpacing(POINT *ppt)
2385 {
2386 return E_NOTIMPL;
2387 }
2388
2389 HRESULT STDMETHODCALLTYPE CDefView::GetAutoArrange()
2390 {
2391 return E_NOTIMPL;
2392 }
2393
2394 HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags)
2395 {
2396 LVITEMW lvItem;
2397
2398 TRACE("(%p)->(%d, %x)\n", this, iItem, dwFlags);
2399
2400 lvItem.state = 0;
2401 lvItem.stateMask = LVIS_SELECTED;
2402
2403 if (dwFlags & SVSI_ENSUREVISIBLE)
2404 m_ListView.EnsureVisible(iItem, 0);
2405
2406 /* all items */
2407 if (dwFlags & SVSI_DESELECTOTHERS)
2408 m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
2409
2410 /* this item */
2411 if (dwFlags & SVSI_SELECT)
2412 lvItem.state |= LVIS_SELECTED;
2413
2414 if (dwFlags & SVSI_FOCUSED)
2415 lvItem.stateMask |= LVIS_FOCUSED;
2416
2417 m_ListView.SetItemState(iItem, lvItem.state, lvItem.stateMask);
2418
2419 if (dwFlags & SVSI_EDIT)
2420 m_ListView.EditLabel(iItem);
2421
2422 return S_OK;
2423 }
2424
2425 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags)
2426 {
2427 return E_NOTIMPL;
2428 }
2429
2430 /**********************************************************
2431 * IShellFolderView implementation
2432 */
2433 HRESULT STDMETHODCALLTYPE CDefView::Rearrange(LPARAM sort)
2434 {
2435 FIXME("(%p)->(%ld) stub\n", this, sort);
2436 return E_NOTIMPL;
2437 }
2438
2439 HRESULT STDMETHODCALLTYPE CDefView::GetArrangeParam(LPARAM *sort)
2440 {
2441 FIXME("(%p)->(%p) stub\n", this, sort);
2442 return E_NOTIMPL;
2443 }
2444
2445 HRESULT STDMETHODCALLTYPE CDefView::ArrangeGrid()
2446 {
2447 FIXME("(%p) stub\n", this);
2448 return E_NOTIMPL;
2449 }
2450
2451 HRESULT STDMETHODCALLTYPE CDefView::AutoArrange()
2452 {
2453 FIXME("(%p) stub\n", this);
2454 return E_NOTIMPL;
2455 }
2456
2457 HRESULT STDMETHODCALLTYPE CDefView::AddObject(PITEMID_CHILD pidl, UINT *item)
2458 {
2459 FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2460 return E_NOTIMPL;
2461 }
2462
2463 HRESULT STDMETHODCALLTYPE CDefView::GetObject(PITEMID_CHILD *pidl, UINT item)
2464 {
2465 TRACE("(%p)->(%p %d)\n", this, pidl, item);
2466 return Item(item, pidl);
2467 }
2468
2469 HRESULT STDMETHODCALLTYPE CDefView::RemoveObject(PITEMID_CHILD pidl, UINT *item)
2470 {
2471
2472 TRACE("(%p)->(%p %p)\n", this, pidl, item);
2473
2474 if (pidl)
2475 {
2476 *item = LV_FindItemByPidl(ILFindLastID(pidl));
2477 m_ListView.DeleteItem(*item);
2478 }
2479 else
2480 {
2481 *item = 0;
2482 m_ListView.DeleteAllItems();
2483 }
2484
2485 return S_OK;
2486 }
2487
2488 HRESULT STDMETHODCALLTYPE CDefView::GetObjectCount(UINT *count)
2489 {
2490 TRACE("(%p)->(%p)\n", this, count);
2491 *count = m_ListView.GetItemCount();
2492 return S_OK;
2493 }
2494
2495 HRESULT STDMETHODCALLTYPE CDefView::SetObjectCount(UINT count, UINT flags)
2496 {
2497 FIXME("(%p)->(%d %x) stub\n", this, count, flags);
2498 return E_NOTIMPL;
2499 }
2500
2501 HRESULT STDMETHODCALLTYPE CDefView::UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item)
2502 {
2503 FIXME("(%p)->(%p %p %p) stub\n", this, pidl_old, pidl_new, item);
2504 return E_NOTIMPL;
2505 }
2506
2507 HRESULT STDMETHODCALLTYPE CDefView::RefreshObject(PITEMID_CHILD pidl, UINT *item)
2508 {
2509 FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2510 return E_NOTIMPL;
2511 }
2512
2513 HRESULT STDMETHODCALLTYPE CDefView::SetRedraw(BOOL redraw)
2514 {
2515 TRACE("(%p)->(%d)\n", this, redraw);
2516 m_ListView.SetRedraw(redraw);
2517 return S_OK;
2518 }
2519
2520 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedCount(UINT *count)
2521 {
2522 FIXME("(%p)->(%p) stub\n", this, count);
2523 return E_NOTIMPL;
2524 }
2525
2526 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items)
2527 {
2528 TRACE("(%p)->(%p %p)\n", this, pidl, items);
2529
2530 *items = GetSelections();
2531
2532 if (*items)
2533 {
2534 *pidl = static_cast<PCUITEMID_CHILD *>(LocalAlloc(0, *items * sizeof(PCUITEMID_CHILD)));
2535 if (!*pidl)
2536 {
2537 return E_OUTOFMEMORY;
2538 }
2539
2540 /* it's documented that caller shouldn't PIDLs, only array itself */
2541 memcpy(*pidl, m_apidl, *items * sizeof(PCUITEMID_CHILD));
2542 }
2543
2544 return S_OK;
2545 }
2546
2547 HRESULT STDMETHODCALLTYPE CDefView::IsDropOnSource(IDropTarget *drop_target)
2548 {
2549 FIXME("(%p)->(%p) stub\n", this, drop_target);
2550 return E_NOTIMPL;
2551 }
2552
2553 HRESULT STDMETHODCALLTYPE CDefView::GetDragPoint(POINT *pt)
2554 {
2555 FIXME("(%p)->(%p) stub\n", this, pt);
2556 return E_NOTIMPL;
2557 }
2558
2559 HRESULT STDMETHODCALLTYPE CDefView::GetDropPoint(POINT *pt)
2560 {
2561 FIXME("(%p)->(%p) stub\n", this, pt);
2562 return E_NOTIMPL;
2563 }
2564
2565 HRESULT STDMETHODCALLTYPE CDefView::MoveIcons(IDataObject *obj)
2566 {
2567 TRACE("(%p)->(%p)\n", this, obj);
2568 return E_NOTIMPL;
2569 }
2570
2571 HRESULT STDMETHODCALLTYPE CDefView::SetItemPos(PCUITEMID_CHILD pidl, POINT *pt)
2572 {
2573 FIXME("(%p)->(%p %p) stub\n", this, pidl, pt);
2574 return E_NOTIMPL;
2575 }
2576
2577 HRESULT STDMETHODCALLTYPE CDefView::IsBkDropTarget(IDropTarget *drop_target)
2578 {
2579 FIXME("(%p)->(%p) stub\n", this, drop_target);
2580 return E_NOTIMPL;
2581 }
2582
2583 HRESULT STDMETHODCALLTYPE CDefView::SetClipboard(BOOL move)
2584 {
2585 FIXME("(%p)->(%d) stub\n", this, move);
2586 return E_NOTIMPL;
2587 }
2588
2589 HRESULT STDMETHODCALLTYPE CDefView::SetPoints(IDataObject *obj)
2590 {
2591 FIXME("(%p)->(%p) stub\n", this, obj);
2592 return E_NOTIMPL;
2593 }
2594
2595 HRESULT STDMETHODCALLTYPE CDefView::GetItemSpacing(ITEMSPACING *spacing)
2596 {
2597 FIXME("(%p)->(%p) stub\n", this, spacing);
2598 return E_NOTIMPL;
2599 }
2600
2601 HRESULT STDMETHODCALLTYPE CDefView::SetCallback(IShellFolderViewCB *new_cb, IShellFolderViewCB **old_cb)
2602 {
2603 FIXME("(%p)->(%p %p) stub\n", this, new_cb, old_cb);
2604 return E_NOTIMPL;
2605 }
2606
2607 HRESULT STDMETHODCALLTYPE CDefView::Select(UINT flags)
2608 {
2609 FIXME("(%p)->(%d) stub\n", this, flags);
2610 return E_NOTIMPL;
2611 }
2612
2613 HRESULT STDMETHODCALLTYPE CDefView::QuerySupport(UINT *support)
2614 {
2615 TRACE("(%p)->(%p)\n", this, support);
2616 return S_OK;
2617 }
2618
2619 HRESULT STDMETHODCALLTYPE CDefView::SetAutomationObject(IDispatch *disp)
2620 {
2621 FIXME("(%p)->(%p) stub\n", this, disp);
2622 return E_NOTIMPL;
2623 }
2624
2625 /**********************************************************
2626 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2627 */
2628 HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText)
2629 {
2630 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2631 this, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2632
2633 if (!prgCmds)
2634 return E_INVALIDARG;
2635
2636 for (UINT i = 0; i < cCmds; i++)
2637 {
2638 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2639 prgCmds[i].cmdf = 0;
2640 }
2641
2642 return OLECMDERR_E_UNKNOWNGROUP;
2643 }
2644
2645 /**********************************************************
2646 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2647 *
2648 * nCmdID is the OLECMDID_* enumeration
2649 */
2650 HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
2651 {
2652 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2653 this, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2654
2655 if (!pguidCmdGroup)
2656 return OLECMDERR_E_UNKNOWNGROUP;
2657
2658 if (IsEqualCLSID(*pguidCmdGroup, m_Category))
2659 {
2660 if (nCmdID == FCIDM_SHVIEW_AUTOARRANGE)
2661 {
2662 if (V_VT(pvaIn) != VT_INT_PTR)
2663 return OLECMDERR_E_NOTSUPPORTED;
2664
2665
2666 TPMPARAMS params;
2667 params.cbSize = sizeof(params);
2668 params.rcExclude = *(RECT*) V_INTREF(pvaIn);
2669
2670 HMENU hView = m_hView;
2671 #if 0
2672 hView = CreatePopupMenu();
2673 AppendMenuW(hView, MF_STRING, FCIDM_SHVIEW_BIGICON, L"Big!");
2674 AppendMenuW(hView, MF_STRING, FCIDM_SHVIEW_SMALLICON, L"Small!");
2675 AppendMenuW(hView, MF_STRING, FCIDM_SHVIEW_LISTVIEW, L"List!");
2676 AppendMenuW(hView, MF_STRING, FCIDM_SHVIEW_REPORTVIEW, L"Report!");
2677 #endif
2678
2679 if (hView)
2680 {
2681 PrepareShowViewMenu(hView);
2682
2683 TrackPopupMenuEx(hView, TPM_LEFTALIGN | TPM_TOPALIGN, params.rcExclude.left, params.rcExclude.bottom, m_hWndParent, &params);
2684 }
2685
2686 // pvaOut is VT_I4 with value 0x403 (cmd id of the new mode maybe?)
2687 V_VT(pvaOut) = VT_I4;
2688 V_I4(pvaOut) = 0x403;
2689 }
2690 }
2691
2692 if (IsEqualIID(*pguidCmdGroup, CGID_Explorer) &&
2693 (nCmdID == 0x29) &&
2694 (nCmdexecopt == 4) && pvaOut)
2695 return S_OK;
2696
2697 if (IsEqualIID(*pguidCmdGroup, CGID_ShellDocView) &&
2698 (nCmdID == 9) &&
2699 (nCmdexecopt == 0))
2700 return 1;
2701
2702 return OLECMDERR_E_UNKNOWNGROUP;
2703 }
2704
2705 /**********************************************************
2706 * ISVDropTarget implementation
2707 */
2708
2709 /******************************************************************************
2710 * drag_notify_subitem [Internal]
2711 *
2712 * Figure out the shellfolder object, which is currently under the mouse cursor
2713 * and notify it via the IDropTarget interface.
2714 */
2715
2716 #define SCROLLAREAWIDTH 20
2717
2718 HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2719 {
2720 LVHITTESTINFO htinfo;
2721 LONG lResult;
2722 HRESULT hr;
2723 RECT clientRect;
2724
2725 /* Map from global to client coordinates and query the index of the listview-item, which is
2726 * currently under the mouse cursor. */
2727 htinfo.pt.x = pt.x;
2728 htinfo.pt.y = pt.y;
2729 htinfo.flags = LVHT_ONITEM;
2730 ::ScreenToClient(m_ListView, &htinfo.pt);
2731 lResult = m_ListView.HitTest(&htinfo);
2732
2733 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2734 ::GetClientRect(m_ListView, &clientRect);
2735 if (htinfo.pt.x == m_ptLastMousePos.x && htinfo.pt.y == m_ptLastMousePos.y &&
2736 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2737 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2738 {
2739 m_cScrollDelay = (m_cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2740 if (m_cScrollDelay == 0)
2741 {
2742 /* Mouse did hover another 250 ms over the scroll-area */
2743 if (htinfo.pt.x < SCROLLAREAWIDTH)
2744 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEUP, 0);
2745
2746 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2747 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEDOWN, 0);
2748
2749 if (htinfo.pt.y < SCROLLAREAWIDTH)
2750 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEUP, 0);
2751
2752 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2753 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEDOWN, 0);
2754 }
2755 }
2756 else
2757 {
2758 m_cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2759 }
2760
2761 m_ptLastMousePos = htinfo.pt;
2762
2763 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2764 if (m_pCurDropTarget && lResult == m_iDragOverItem)
2765 return m_pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect);
2766
2767 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2768 if (m_pCurDropTarget)
2769 {
2770 m_pCurDropTarget->DragLeave();
2771 m_pCurDropTarget.Release();
2772 }
2773
2774 m_iDragOverItem = lResult;
2775 if (lResult == -1)
2776 {
2777 /* We are not above one of the listview's subitems. Bind to the parent folder's
2778 * DropTarget interface. */
2779 hr = m_pSFParent->QueryInterface(IID_PPV_ARG(IDropTarget,&m_pCurDropTarget));
2780 }
2781 else
2782 {
2783 /* Query the relative PIDL of the shellfolder object represented by the currently
2784 * dragged over listview-item ... */
2785 PCUITEMID_CHILD pidl = _PidlByItem(lResult);
2786
2787 /* ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2788 hr = m_pSFParent->GetUIObjectOf(m_ListView, 1, &pidl, IID_NULL_PPV_ARG(IDropTarget, &m_pCurDropTarget));
2789 }
2790
2791 /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */
2792 if (FAILED(hr))
2793 return hr;
2794
2795 /* Notify the item just entered via DragEnter. */
2796 return m_pCurDropTarget->DragEnter(m_pCurDataObject, grfKeyState, pt, pdwEffect);
2797 }
2798
2799 HRESULT WINAPI CDefView::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2800 {
2801 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2802 m_pCurDataObject = pDataObject;
2803 pDataObject->AddRef();
2804
2805 return drag_notify_subitem(grfKeyState, pt, pdwEffect);
2806 }
2807
2808 HRESULT WINAPI CDefView::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2809 {
2810 return drag_notify_subitem(grfKeyState, pt, pdwEffect);
2811 }
2812
2813 HRESULT WINAPI CDefView::DragLeave()
2814 {
2815 if (m_pCurDropTarget)
2816 {
2817 m_pCurDropTarget->DragLeave();
2818 m_pCurDropTarget.Release();
2819 }
2820
2821 if (m_pCurDataObject != NULL)
2822 {
2823 m_pCurDataObject.Release();
2824 }
2825
2826 m_iDragOverItem = 0;
2827
2828 return S_OK;
2829 }
2830
2831 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2832 {
2833 if (m_pCurDropTarget)
2834 {
2835 m_pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect);
2836 m_pCurDropTarget.Release();
2837 }
2838
2839 m_pCurDataObject.Release();
2840 m_iDragOverItem = 0;
2841 return S_OK;
2842 }
2843
2844 /**********************************************************
2845 * ISVDropSource implementation
2846 */
2847
2848 HRESULT WINAPI CDefView::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
2849 {
2850 TRACE("(%p)\n", this);
2851
2852 if (fEscapePressed)
2853 return DRAGDROP_S_CANCEL;
2854 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2855 return DRAGDROP_S_DROP;
2856 else
2857 return S_OK;
2858 }
2859
2860 HRESULT WINAPI CDefView::GiveFeedback(DWORD dwEffect)
2861 {
2862 TRACE("(%p)\n", this);
2863
2864 return DRAGDROP_S_USEDEFAULTCURSORS;
2865 }
2866
2867 /**********************************************************
2868 * ISVViewObject implementation
2869 */
2870
2871 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)
2872 {
2873 FIXME("Stub: this=%p\n", this);
2874
2875 return E_NOTIMPL;
2876 }
2877
2878 HRESULT WINAPI CDefView::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet)
2879 {
2880 FIXME("Stub: this=%p\n", this);
2881
2882 return E_NOTIMPL;
2883 }
2884
2885 HRESULT WINAPI CDefView::Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze)
2886 {
2887 FIXME("Stub: this=%p\n", this);
2888
2889 return E_NOTIMPL;
2890 }
2891
2892 HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze)
2893 {
2894 FIXME("Stub: this=%p\n", this);
2895
2896 return E_NOTIMPL;
2897 }
2898
2899 HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink)
2900 {
2901 FIXME("partial stub: %p %08x %08x %p\n", this, aspects, advf, pAdvSink);
2902
2903 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2904 m_pAdvSink = pAdvSink;
2905 m_dwAspects = aspects;
2906 m_dwAdvf = advf;
2907
2908 return S_OK;
2909 }
2910
2911 HRESULT WINAPI CDefView::GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink)
2912 {
2913 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects, pAdvf, ppAdvSink);
2914
2915 if (ppAdvSink)
2916 {
2917 *ppAdvSink = m_pAdvSink;
2918 m_pAdvSink.p->AddRef();
2919 }
2920
2921 if (pAspects)
2922 *pAspects = m_dwAspects;
2923
2924 if (pAdvf)
2925 *pAdvf = m_dwAdvf;
2926
2927 return S_OK;
2928 }
2929
2930 HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
2931 {
2932 if (IsEqualIID(guidService, SID_IShellBrowser))
2933 return m_pShellBrowser->QueryInterface(riid, ppvObject);
2934 else if(IsEqualIID(guidService, SID_IFolderView))
2935 return QueryInterface(riid, ppvObject);
2936
2937 return E_NOINTERFACE;
2938 }
2939
2940 HRESULT CDefView::_MergeToolbar()
2941 {
2942 CComPtr<IExplorerToolbar> ptb; // [sp+8h] [bp-4h]@1
2943
2944 HRESULT hr = S_OK;
2945
2946 hr = IUnknown_QueryService(m_pShellBrowser, IID_IExplorerToolbar, IID_PPV_ARG(IExplorerToolbar, &ptb));
2947 if (FAILED(hr))
2948 return hr;
2949
2950 m_Category = CGID_DefViewFrame;
2951
2952 hr = ptb->SetCommandTarget(static_cast<IOleCommandTarget*>(this), &m_Category, 0);
2953 if (FAILED(hr))
2954 return hr;
2955
2956 if (hr == S_FALSE)
2957 return S_OK;
2958
2959 #if 0
2960 hr = ptb->AddButtons(&m_Category, buttonsCount, buttons);
2961 if (FAILED(hr))
2962 return hr;
2963 #endif
2964
2965 return S_OK;
2966 }
2967 /**********************************************************
2968 * IShellView_Constructor
2969 */
2970 HRESULT WINAPI IShellView_Constructor(IShellFolder *pFolder, IShellView **newView)
2971 {
2972 return ShellObjectCreatorInit<CDefView>(pFolder, IID_IShellView, newView);
2973 }