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