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