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