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