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