0d639a4f80fcdc743fc09895d36cfbfd9c26fb36
[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 OLEMENUGROUPWIDTHS omw = { { 0, 0, 0, 0, 0, 0 } };
2148
2149 *phWnd = 0;
2150
2151 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n", this, lpPrevView, lpfs, psb, prcView, phWnd);
2152
2153 if (lpfs != NULL)
2154 TRACE("-- vmode=%x flags=%x\n", lpfs->ViewMode, lpfs->fFlags);
2155 if (prcView != NULL)
2156 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom);
2157
2158 /* Validate the Shell Browser */
2159 if (psb == NULL || m_hWnd)
2160 return E_UNEXPECTED;
2161
2162 /* Set up the member variables */
2163 m_pShellBrowser = psb;
2164 m_FolderSettings = *lpfs;
2165
2166 /* Get our parent window */
2167 m_pShellBrowser->GetWindow(&m_hWndParent);
2168
2169 /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
2170 m_pCommDlgBrowser = NULL;
2171 if (SUCCEEDED(m_pShellBrowser->QueryInterface(IID_PPV_ARG(ICommDlgBrowser, &m_pCommDlgBrowser))))
2172 {
2173 TRACE("-- CommDlgBrowser\n");
2174 }
2175
2176 Create(m_hWndParent, prcView, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP, 0, 0U);
2177 if (m_hWnd == NULL)
2178 return E_FAIL;
2179
2180 *phWnd = m_hWnd;
2181
2182 CheckToolbar();
2183
2184 if (!*phWnd)
2185 return E_FAIL;
2186
2187 SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
2188 UpdateWindow();
2189
2190 if (!m_hMenu)
2191 {
2192 m_hMenu = CreateMenu();
2193 m_pShellBrowser->InsertMenusSB(m_hMenu, &omw);
2194 TRACE("-- after fnInsertMenusSB\n");
2195 }
2196
2197 _MergeToolbar();
2198
2199 return S_OK;
2200 }
2201
2202 HRESULT WINAPI CDefView::DestroyViewWindow()
2203 {
2204 TRACE("(%p)\n", this);
2205
2206 /* Make absolutely sure all our UI is cleaned up */
2207 UIActivate(SVUIA_DEACTIVATE);
2208
2209 if (m_hAccel)
2210 {
2211 // "Accelerator tables loaded from resources are freed automatically when the application terminates." -- MSDN
2212 m_hAccel = NULL;
2213 }
2214
2215 if (m_hView)
2216 {
2217 DestroyMenu(m_hView);
2218 m_hView = NULL;
2219 }
2220
2221 if (m_hMenu)
2222 {
2223 DestroyMenu(m_hMenu);
2224 m_hMenu = NULL;
2225 }
2226
2227 if (m_ListView)
2228 {
2229 m_ListView.DestroyWindow();
2230 }
2231
2232 if (m_hWnd)
2233 {
2234 DestroyWindow();
2235 }
2236
2237 m_pShellBrowser.Release();
2238 m_pCommDlgBrowser.Release();
2239
2240 return S_OK;
2241 }
2242
2243 HRESULT WINAPI CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
2244 {
2245 TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs,
2246 m_FolderSettings.ViewMode, m_FolderSettings.fFlags);
2247
2248 if (!lpfs)
2249 return E_INVALIDARG;
2250
2251 *lpfs = m_FolderSettings;
2252 return S_OK;
2253 }
2254
2255 HRESULT WINAPI CDefView::AddPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
2256 {
2257 FIXME("(%p) stub\n", this);
2258
2259 return E_NOTIMPL;
2260 }
2261
2262 HRESULT WINAPI CDefView::SaveViewState()
2263 {
2264 FIXME("(%p) stub\n", this);
2265
2266 return S_OK;
2267 }
2268
2269 HRESULT WINAPI CDefView::SelectItem(PCUITEMID_CHILD pidl, UINT uFlags)
2270 {
2271 int i;
2272
2273 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl, uFlags);
2274
2275 i = LV_FindItemByPidl(pidl);
2276 if (i == -1)
2277 return S_OK;
2278
2279 if(uFlags & SVSI_ENSUREVISIBLE)
2280 m_ListView.EnsureVisible(i, FALSE);
2281
2282 LVITEMW lvItem = {0};
2283 lvItem.mask = LVIF_STATE;
2284 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
2285
2286 while (m_ListView.GetItem(&lvItem))
2287 {
2288 if (lvItem.iItem == i)
2289 {
2290 if (uFlags & SVSI_SELECT)
2291 lvItem.state |= LVIS_SELECTED;
2292 else
2293 lvItem.state &= ~LVIS_SELECTED;
2294
2295 if (uFlags & SVSI_FOCUSED)
2296 lvItem.state &= ~LVIS_FOCUSED;
2297 }
2298 else
2299 {
2300 if (uFlags & SVSI_DESELECTOTHERS)
2301 lvItem.state &= ~LVIS_SELECTED;
2302 }
2303
2304 m_ListView.SetItem(&lvItem);
2305 lvItem.iItem++;
2306 }
2307
2308 if(uFlags & SVSI_EDIT)
2309 m_ListView.EditLabel(i);
2310
2311 return S_OK;
2312 }
2313
2314 HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
2315 {
2316 HRESULT hr = E_NOINTERFACE;
2317
2318 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem, debugstr_guid(&riid), ppvOut);
2319
2320 *ppvOut = NULL;
2321
2322 switch (uItem)
2323 {
2324 case SVGIO_BACKGROUND:
2325 if (IsEqualIID(riid, IID_IContextMenu))
2326 {
2327 //*ppvOut = ISvBgCm_Constructor(m_pSFParent, FALSE);
2328 if (!ppvOut)
2329 hr = E_OUTOFMEMORY;
2330
2331 IContextMenu* pcm;
2332 hr = CDefFolderMenu_Create2(NULL, NULL, 0, NULL, m_pSFParent, NULL, 0, NULL, &pcm);
2333 if (FAILED(hr))
2334 return hr;
2335 *ppvOut = pcm;
2336 }
2337 else if (IsEqualIID(riid, IID_IDispatch))
2338 {
2339 if (m_pShellFolderViewDual == NULL)
2340 {
2341 hr = CDefViewDual_Constructor(riid, (LPVOID*)&m_pShellFolderViewDual);
2342 if (FAILED_UNEXPECTEDLY(hr))
2343 {
2344 return hr;
2345 }
2346 }
2347 hr = m_pShellFolderViewDual->QueryInterface(riid, ppvOut);
2348 }
2349 break;
2350
2351 case SVGIO_SELECTION:
2352 GetSelections();
2353 hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, riid, 0, ppvOut);
2354 break;
2355 }
2356
2357 TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut);
2358
2359 return hr;
2360 }
2361
2362 HRESULT STDMETHODCALLTYPE CDefView::GetCurrentViewMode(UINT *pViewMode)
2363 {
2364 TRACE("(%p)->(%p), stub\n", this, pViewMode);
2365
2366 if (!pViewMode)
2367 return E_INVALIDARG;
2368
2369 *pViewMode = m_FolderSettings.ViewMode;
2370 return S_OK;
2371 }
2372
2373 HRESULT STDMETHODCALLTYPE CDefView::SetCurrentViewMode(UINT ViewMode)
2374 {
2375 DWORD dwStyle;
2376 TRACE("(%p)->(%u), stub\n", this, ViewMode);
2377
2378 /* It's not redundant to check FVM_AUTO because it's a (UINT)-1 */
2379 if (((INT)ViewMode < FVM_FIRST || (INT)ViewMode > FVM_LAST) && ((INT)ViewMode != FVM_AUTO))
2380 return E_INVALIDARG;
2381
2382 /* Windows before Vista uses LVM_SETVIEW and possibly
2383 LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview,
2384 while later versions seem to accomplish this through other
2385 means. */
2386 switch (ViewMode)
2387 {
2388 case FVM_ICON:
2389 dwStyle = LVS_ICON;
2390 break;
2391 case FVM_DETAILS:
2392 dwStyle = LVS_REPORT;
2393 break;
2394 case FVM_SMALLICON:
2395 dwStyle = LVS_SMALLICON;
2396 break;
2397 case FVM_LIST:
2398 dwStyle = LVS_LIST;
2399 break;
2400 default:
2401 {
2402 FIXME("ViewMode %d not implemented\n", ViewMode);
2403 dwStyle = LVS_LIST;
2404 break;
2405 }
2406 }
2407
2408 SetStyle(dwStyle, LVS_TYPEMASK);
2409
2410 /* This will not necessarily be the actual mode set above.
2411 This mimics the behavior of Windows XP. */
2412 m_FolderSettings.ViewMode = ViewMode;
2413
2414 return S_OK;
2415 }
2416
2417 HRESULT STDMETHODCALLTYPE CDefView::GetFolder(REFIID riid, void **ppv)
2418 {
2419 if (m_pSFParent == NULL)
2420 return E_FAIL;
2421
2422 return m_pSFParent->QueryInterface(riid, ppv);
2423 }
2424
2425 HRESULT STDMETHODCALLTYPE CDefView::Item(int iItemIndex, PITEMID_CHILD *ppidl)
2426 {
2427 PCUITEMID_CHILD pidl = _PidlByItem(iItemIndex);
2428 if (pidl)
2429 {
2430 *ppidl = ILClone(pidl);
2431 return S_OK;
2432 }
2433
2434 *ppidl = 0;
2435 return E_INVALIDARG;
2436 }
2437
2438 HRESULT STDMETHODCALLTYPE CDefView::ItemCount(UINT uFlags, int *pcItems)
2439 {
2440 TRACE("(%p)->(%u %p)\n", this, uFlags, pcItems);
2441
2442 if (uFlags != SVGIO_ALLVIEW)
2443 FIXME("some flags unsupported, %x\n", uFlags & ~SVGIO_ALLVIEW);
2444
2445 *pcItems = m_ListView.GetItemCount();
2446
2447 return S_OK;
2448 }
2449
2450 HRESULT STDMETHODCALLTYPE CDefView::Items(UINT uFlags, REFIID riid, void **ppv)
2451 {
2452 return E_NOTIMPL;
2453 }
2454
2455 HRESULT STDMETHODCALLTYPE CDefView::GetSelectionMarkedItem(int *piItem)
2456 {
2457 TRACE("(%p)->(%p)\n", this, piItem);
2458
2459 *piItem = m_ListView.GetSelectionMark();
2460
2461 return S_OK;
2462 }
2463
2464 HRESULT STDMETHODCALLTYPE CDefView::GetFocusedItem(int *piItem)
2465 {
2466 TRACE("(%p)->(%p)\n", this, piItem);
2467
2468 *piItem = m_ListView.GetNextItem(-1, LVNI_FOCUSED);
2469
2470 return S_OK;
2471 }
2472
2473 HRESULT STDMETHODCALLTYPE CDefView::GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt)
2474 {
2475 return E_NOTIMPL;
2476 }
2477
2478 HRESULT STDMETHODCALLTYPE CDefView::GetSpacing(POINT *ppt)
2479 {
2480 TRACE("(%p)->(%p)\n", this, ppt);
2481
2482 if (!m_ListView)
2483 return S_FALSE;
2484
2485 if (ppt)
2486 {
2487 SIZE spacing;
2488 m_ListView.GetItemSpacing(spacing);
2489
2490 ppt->x = spacing.cx;
2491 ppt->y = spacing.cy;
2492 }
2493
2494 return S_OK;
2495 }
2496
2497 HRESULT STDMETHODCALLTYPE CDefView::GetDefaultSpacing(POINT *ppt)
2498 {
2499 return E_NOTIMPL;
2500 }
2501
2502 HRESULT STDMETHODCALLTYPE CDefView::GetAutoArrange()
2503 {
2504 return E_NOTIMPL;
2505 }
2506
2507 HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags)
2508 {
2509 LVITEMW lvItem;
2510
2511 TRACE("(%p)->(%d, %x)\n", this, iItem, dwFlags);
2512
2513 lvItem.state = 0;
2514 lvItem.stateMask = LVIS_SELECTED;
2515
2516 if (dwFlags & SVSI_ENSUREVISIBLE)
2517 m_ListView.EnsureVisible(iItem, 0);
2518
2519 /* all items */
2520 if (dwFlags & SVSI_DESELECTOTHERS)
2521 m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
2522
2523 /* this item */
2524 if (dwFlags & SVSI_SELECT)
2525 lvItem.state |= LVIS_SELECTED;
2526
2527 if (dwFlags & SVSI_FOCUSED)
2528 lvItem.stateMask |= LVIS_FOCUSED;
2529
2530 m_ListView.SetItemState(iItem, lvItem.state, lvItem.stateMask);
2531
2532 if (dwFlags & SVSI_EDIT)
2533 m_ListView.EditLabel(iItem);
2534
2535 return S_OK;
2536 }
2537
2538 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags)
2539 {
2540 return E_NOTIMPL;
2541 }
2542
2543 /**********************************************************
2544 * IShellView2 implementation
2545 */
2546
2547 HRESULT STDMETHODCALLTYPE CDefView::GetView(SHELLVIEWID *view_guid, ULONG view_type)
2548 {
2549 FIXME("(%p)->(%p, %lu) stub\n", this, view_guid, view_type);
2550 return E_NOTIMPL;
2551 }
2552
2553 HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow2(LPSV2CVW2_PARAMS view_params)
2554 {
2555 FIXME("(%p)->(%p) stub\n", this, view_params);
2556 return E_NOTIMPL;
2557 }
2558
2559 HRESULT STDMETHODCALLTYPE CDefView::HandleRename(LPCITEMIDLIST new_pidl)
2560 {
2561 FIXME("(%p)->(%p) stub\n", this, new_pidl);
2562 return E_NOTIMPL;
2563 }
2564
2565 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point)
2566 {
2567 FIXME("(%p)->(%p, %u, %p) stub\n", this, item, flags, point);
2568 return E_NOTIMPL;
2569 }
2570
2571 /**********************************************************
2572 * IShellFolderView implementation
2573 */
2574 HRESULT STDMETHODCALLTYPE CDefView::Rearrange(LPARAM sort)
2575 {
2576 FIXME("(%p)->(%ld) stub\n", this, sort);
2577 return E_NOTIMPL;
2578 }
2579
2580 HRESULT STDMETHODCALLTYPE CDefView::GetArrangeParam(LPARAM *sort)
2581 {
2582 FIXME("(%p)->(%p) stub\n", this, sort);
2583 return E_NOTIMPL;
2584 }
2585
2586 HRESULT STDMETHODCALLTYPE CDefView::ArrangeGrid()
2587 {
2588 FIXME("(%p) stub\n", this);
2589 return E_NOTIMPL;
2590 }
2591
2592 HRESULT STDMETHODCALLTYPE CDefView::AutoArrange()
2593 {
2594 FIXME("(%p) stub\n", this);
2595 return E_NOTIMPL;
2596 }
2597
2598 HRESULT STDMETHODCALLTYPE CDefView::AddObject(PITEMID_CHILD pidl, UINT *item)
2599 {
2600 FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2601 return E_NOTIMPL;
2602 }
2603
2604 HRESULT STDMETHODCALLTYPE CDefView::GetObject(PITEMID_CHILD *pidl, UINT item)
2605 {
2606 TRACE("(%p)->(%p %d)\n", this, pidl, item);
2607 return Item(item, pidl);
2608 }
2609
2610 HRESULT STDMETHODCALLTYPE CDefView::RemoveObject(PITEMID_CHILD pidl, UINT *item)
2611 {
2612
2613 TRACE("(%p)->(%p %p)\n", this, pidl, item);
2614
2615 if (pidl)
2616 {
2617 *item = LV_FindItemByPidl(ILFindLastID(pidl));
2618 m_ListView.DeleteItem(*item);
2619 }
2620 else
2621 {
2622 *item = 0;
2623 m_ListView.DeleteAllItems();
2624 }
2625
2626 return S_OK;
2627 }
2628
2629 HRESULT STDMETHODCALLTYPE CDefView::GetObjectCount(UINT *count)
2630 {
2631 TRACE("(%p)->(%p)\n", this, count);
2632 *count = m_ListView.GetItemCount();
2633 return S_OK;
2634 }
2635
2636 HRESULT STDMETHODCALLTYPE CDefView::SetObjectCount(UINT count, UINT flags)
2637 {
2638 FIXME("(%p)->(%d %x) stub\n", this, count, flags);
2639 return E_NOTIMPL;
2640 }
2641
2642 HRESULT STDMETHODCALLTYPE CDefView::UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item)
2643 {
2644 FIXME("(%p)->(%p %p %p) stub\n", this, pidl_old, pidl_new, item);
2645 return E_NOTIMPL;
2646 }
2647
2648 HRESULT STDMETHODCALLTYPE CDefView::RefreshObject(PITEMID_CHILD pidl, UINT *item)
2649 {
2650 FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2651 return E_NOTIMPL;
2652 }
2653
2654 HRESULT STDMETHODCALLTYPE CDefView::SetRedraw(BOOL redraw)
2655 {
2656 TRACE("(%p)->(%d)\n", this, redraw);
2657 m_ListView.SetRedraw(redraw);
2658 return S_OK;
2659 }
2660
2661 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedCount(UINT *count)
2662 {
2663 FIXME("(%p)->(%p) stub\n", this, count);
2664 return E_NOTIMPL;
2665 }
2666
2667 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items)
2668 {
2669 TRACE("(%p)->(%p %p)\n", this, pidl, items);
2670
2671 *items = GetSelections();
2672
2673 if (*items)
2674 {
2675 *pidl = static_cast<PCUITEMID_CHILD *>(LocalAlloc(0, *items * sizeof(PCUITEMID_CHILD)));
2676 if (!*pidl)
2677 {
2678 return E_OUTOFMEMORY;
2679 }
2680
2681 /* it's documented that caller shouldn't PIDLs, only array itself */
2682 memcpy(*pidl, m_apidl, *items * sizeof(PCUITEMID_CHILD));
2683 }
2684
2685 return S_OK;
2686 }
2687
2688 HRESULT STDMETHODCALLTYPE CDefView::IsDropOnSource(IDropTarget *drop_target)
2689 {
2690 FIXME("(%p)->(%p) stub\n", this, drop_target);
2691 return E_NOTIMPL;
2692 }
2693
2694 HRESULT STDMETHODCALLTYPE CDefView::GetDragPoint(POINT *pt)
2695 {
2696 FIXME("(%p)->(%p) stub\n", this, pt);
2697 return E_NOTIMPL;
2698 }
2699
2700 HRESULT STDMETHODCALLTYPE CDefView::GetDropPoint(POINT *pt)
2701 {
2702 FIXME("(%p)->(%p) stub\n", this, pt);
2703 return E_NOTIMPL;
2704 }
2705
2706 HRESULT STDMETHODCALLTYPE CDefView::MoveIcons(IDataObject *obj)
2707 {
2708 TRACE("(%p)->(%p)\n", this, obj);
2709 return E_NOTIMPL;
2710 }
2711
2712 HRESULT STDMETHODCALLTYPE CDefView::SetItemPos(PCUITEMID_CHILD pidl, POINT *pt)
2713 {
2714 FIXME("(%p)->(%p %p) stub\n", this, pidl, pt);
2715 return E_NOTIMPL;
2716 }
2717
2718 HRESULT STDMETHODCALLTYPE CDefView::IsBkDropTarget(IDropTarget *drop_target)
2719 {
2720 FIXME("(%p)->(%p) stub\n", this, drop_target);
2721 return E_NOTIMPL;
2722 }
2723
2724 HRESULT STDMETHODCALLTYPE CDefView::SetClipboard(BOOL move)
2725 {
2726 FIXME("(%p)->(%d) stub\n", this, move);
2727 return E_NOTIMPL;
2728 }
2729
2730 HRESULT STDMETHODCALLTYPE CDefView::SetPoints(IDataObject *obj)
2731 {
2732 FIXME("(%p)->(%p) stub\n", this, obj);
2733 return E_NOTIMPL;
2734 }
2735
2736 HRESULT STDMETHODCALLTYPE CDefView::GetItemSpacing(ITEMSPACING *spacing)
2737 {
2738 FIXME("(%p)->(%p) stub\n", this, spacing);
2739 return E_NOTIMPL;
2740 }
2741
2742 HRESULT STDMETHODCALLTYPE CDefView::SetCallback(IShellFolderViewCB *new_cb, IShellFolderViewCB **old_cb)
2743 {
2744 FIXME("(%p)->(%p %p) stub\n", this, new_cb, old_cb);
2745 return E_NOTIMPL;
2746 }
2747
2748 HRESULT STDMETHODCALLTYPE CDefView::Select(UINT flags)
2749 {
2750 FIXME("(%p)->(%d) stub\n", this, flags);
2751 return E_NOTIMPL;
2752 }
2753
2754 HRESULT STDMETHODCALLTYPE CDefView::QuerySupport(UINT *support)
2755 {
2756 TRACE("(%p)->(%p)\n", this, support);
2757 return S_OK;
2758 }
2759
2760 HRESULT STDMETHODCALLTYPE CDefView::SetAutomationObject(IDispatch *disp)
2761 {
2762 FIXME("(%p)->(%p) stub\n", this, disp);
2763 return E_NOTIMPL;
2764 }
2765
2766 /**********************************************************
2767 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2768 */
2769 HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText)
2770 {
2771 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2772 this, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2773
2774 if (!prgCmds)
2775 return E_INVALIDARG;
2776
2777 for (UINT i = 0; i < cCmds; i++)
2778 {
2779 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2780 prgCmds[i].cmdf = 0;
2781 }
2782
2783 return OLECMDERR_E_UNKNOWNGROUP;
2784 }
2785
2786 /**********************************************************
2787 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2788 *
2789 * nCmdID is the OLECMDID_* enumeration
2790 */
2791 HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
2792 {
2793 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2794 this, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2795
2796 if (!pguidCmdGroup)
2797 return OLECMDERR_E_UNKNOWNGROUP;
2798
2799 if (IsEqualCLSID(*pguidCmdGroup, m_Category))
2800 {
2801 if (nCmdID == FCIDM_SHVIEW_AUTOARRANGE)
2802 {
2803 if (V_VT(pvaIn) != VT_INT_PTR)
2804 return OLECMDERR_E_NOTSUPPORTED;
2805
2806
2807 TPMPARAMS params;
2808 params.cbSize = sizeof(params);
2809 params.rcExclude = *(RECT*) V_INTREF(pvaIn);
2810
2811 HMENU hView = m_hView;
2812 #if 0
2813 hView = CreatePopupMenu();
2814 AppendMenuW(hView, MF_STRING, FCIDM_SHVIEW_BIGICON, L"Big!");
2815 AppendMenuW(hView, MF_STRING, FCIDM_SHVIEW_SMALLICON, L"Small!");
2816 AppendMenuW(hView, MF_STRING, FCIDM_SHVIEW_LISTVIEW, L"List!");
2817 AppendMenuW(hView, MF_STRING, FCIDM_SHVIEW_REPORTVIEW, L"Report!");
2818 #endif
2819
2820 if (hView)
2821 {
2822 PrepareShowViewMenu(hView);
2823
2824 TrackPopupMenuEx(hView, TPM_LEFTALIGN | TPM_TOPALIGN, params.rcExclude.left, params.rcExclude.bottom, m_hWndParent, &params);
2825 }
2826
2827 // pvaOut is VT_I4 with value 0x403 (cmd id of the new mode maybe?)
2828 V_VT(pvaOut) = VT_I4;
2829 V_I4(pvaOut) = 0x403;
2830 }
2831 }
2832
2833 if (IsEqualIID(*pguidCmdGroup, CGID_Explorer) &&
2834 (nCmdID == 0x29) &&
2835 (nCmdexecopt == 4) && pvaOut)
2836 return S_OK;
2837
2838 if (IsEqualIID(*pguidCmdGroup, CGID_ShellDocView) &&
2839 (nCmdID == 9) &&
2840 (nCmdexecopt == 0))
2841 return 1;
2842
2843 return OLECMDERR_E_UNKNOWNGROUP;
2844 }
2845
2846 /**********************************************************
2847 * ISVDropTarget implementation
2848 */
2849
2850 /******************************************************************************
2851 * drag_notify_subitem [Internal]
2852 *
2853 * Figure out the shellfolder object, which is currently under the mouse cursor
2854 * and notify it via the IDropTarget interface.
2855 */
2856
2857 #define SCROLLAREAWIDTH 20
2858
2859 HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2860 {
2861 LVHITTESTINFO htinfo;
2862 LONG lResult;
2863 HRESULT hr;
2864 RECT clientRect;
2865
2866 /* Map from global to client coordinates and query the index of the listview-item, which is
2867 * currently under the mouse cursor. */
2868 htinfo.pt.x = pt.x;
2869 htinfo.pt.y = pt.y;
2870 htinfo.flags = LVHT_ONITEM;
2871 ::ScreenToClient(m_ListView, &htinfo.pt);
2872 lResult = m_ListView.HitTest(&htinfo);
2873
2874 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2875 ::GetClientRect(m_ListView, &clientRect);
2876 if (htinfo.pt.x == m_ptLastMousePos.x && htinfo.pt.y == m_ptLastMousePos.y &&
2877 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2878 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2879 {
2880 m_cScrollDelay = (m_cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2881 if (m_cScrollDelay == 0)
2882 {
2883 /* Mouse did hover another 250 ms over the scroll-area */
2884 if (htinfo.pt.x < SCROLLAREAWIDTH)
2885 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEUP, 0);
2886
2887 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2888 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEDOWN, 0);
2889
2890 if (htinfo.pt.y < SCROLLAREAWIDTH)
2891 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEUP, 0);
2892
2893 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2894 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEDOWN, 0);
2895 }
2896 }
2897 else
2898 {
2899 m_cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2900 }
2901
2902 m_ptLastMousePos = htinfo.pt;
2903
2904 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2905 if (m_pCurDropTarget && lResult == m_iDragOverItem)
2906 return m_pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect);
2907
2908 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2909 if (m_pCurDropTarget)
2910 {
2911 m_pCurDropTarget->DragLeave();
2912 m_pCurDropTarget.Release();
2913 }
2914
2915 m_iDragOverItem = lResult;
2916 if (lResult == -1)
2917 {
2918 /* We are not above one of the listview's subitems. Bind to the parent folder's
2919 * DropTarget interface. */
2920 hr = m_pSFParent->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget,&m_pCurDropTarget));
2921 }
2922 else
2923 {
2924 /* Query the relative PIDL of the shellfolder object represented by the currently
2925 * dragged over listview-item ... */
2926 PCUITEMID_CHILD pidl = _PidlByItem(lResult);
2927
2928 /* ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2929 hr = m_pSFParent->GetUIObjectOf(m_ListView, 1, &pidl, IID_NULL_PPV_ARG(IDropTarget, &m_pCurDropTarget));
2930 }
2931
2932 /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */
2933 if (FAILED(hr))
2934 return hr;
2935
2936 /* Notify the item just entered via DragEnter. */
2937 return m_pCurDropTarget->DragEnter(m_pCurDataObject, grfKeyState, pt, pdwEffect);
2938 }
2939
2940 HRESULT WINAPI CDefView::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2941 {
2942 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2943 m_pCurDataObject = pDataObject;
2944 pDataObject->AddRef();
2945
2946 return drag_notify_subitem(grfKeyState, pt, pdwEffect);
2947 }
2948
2949 HRESULT WINAPI CDefView::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2950 {
2951 return drag_notify_subitem(grfKeyState, pt, pdwEffect);
2952 }
2953
2954 HRESULT WINAPI CDefView::DragLeave()
2955 {
2956 if (m_pCurDropTarget)
2957 {
2958 m_pCurDropTarget->DragLeave();
2959 m_pCurDropTarget.Release();
2960 }
2961
2962 if (m_pCurDataObject != NULL)
2963 {
2964 m_pCurDataObject.Release();
2965 }
2966
2967 m_iDragOverItem = 0;
2968
2969 return S_OK;
2970 }
2971
2972 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2973 {
2974 ERR("GetKeyState(VK_LBUTTON): %d\n", GetKeyState(VK_LBUTTON));
2975
2976 if ((m_iDragOverItem == -1) &&
2977 (*pdwEffect & DROPEFFECT_MOVE) &&
2978 (GetKeyState(VK_LBUTTON) != 0) &&
2979 (m_pSourceDataObject.p) &&
2980 (SHIsSameObject(pDataObject, m_pSourceDataObject)))
2981 {
2982 ERR("Should implement moving items here!\n");
2983
2984 if (m_pCurDropTarget)
2985 {
2986 m_pCurDropTarget->DragLeave();
2987 m_pCurDropTarget.Release();
2988 }
2989 }
2990 else if (m_pCurDropTarget)
2991 {
2992 m_pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect);
2993 m_pCurDropTarget.Release();
2994 }
2995
2996 m_pCurDataObject.Release();
2997 m_iDragOverItem = 0;
2998 return S_OK;
2999 }
3000
3001 /**********************************************************
3002 * ISVDropSource implementation
3003 */
3004
3005 HRESULT WINAPI CDefView::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
3006 {
3007 TRACE("(%p)\n", this);
3008
3009 if (fEscapePressed)
3010 return DRAGDROP_S_CANCEL;
3011 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
3012 return DRAGDROP_S_DROP;
3013 else
3014 return S_OK;
3015 }
3016
3017 HRESULT WINAPI CDefView::GiveFeedback(DWORD dwEffect)
3018 {
3019 TRACE("(%p)\n", this);
3020
3021 return DRAGDROP_S_USEDEFAULTCURSORS;
3022 }
3023
3024 /**********************************************************
3025 * ISVViewObject implementation
3026 */
3027
3028 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)
3029 {
3030 FIXME("Stub: this=%p\n", this);
3031
3032 return E_NOTIMPL;
3033 }
3034
3035 HRESULT WINAPI CDefView::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet)
3036 {
3037 FIXME("Stub: this=%p\n", this);
3038
3039 return E_NOTIMPL;
3040 }
3041
3042 HRESULT WINAPI CDefView::Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze)
3043 {
3044 FIXME("Stub: this=%p\n", this);
3045
3046 return E_NOTIMPL;
3047 }
3048
3049 HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze)
3050 {
3051 FIXME("Stub: this=%p\n", this);
3052
3053 return E_NOTIMPL;
3054 }
3055
3056 HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink)
3057 {
3058 FIXME("partial stub: %p %08x %08x %p\n", this, aspects, advf, pAdvSink);
3059
3060 /* FIXME: we set the AdviseSink, but never use it to send any advice */
3061 m_pAdvSink = pAdvSink;
3062 m_dwAspects = aspects;
3063 m_dwAdvf = advf;
3064
3065 return S_OK;
3066 }
3067
3068 HRESULT WINAPI CDefView::GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink)
3069 {
3070 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects, pAdvf, ppAdvSink);
3071
3072 if (ppAdvSink)
3073 {
3074 *ppAdvSink = m_pAdvSink;
3075 m_pAdvSink.p->AddRef();
3076 }
3077
3078 if (pAspects)
3079 *pAspects = m_dwAspects;
3080
3081 if (pAdvf)
3082 *pAdvf = m_dwAdvf;
3083
3084 return S_OK;
3085 }
3086
3087 HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
3088 {
3089 if (IsEqualIID(guidService, SID_IShellBrowser))
3090 return m_pShellBrowser->QueryInterface(riid, ppvObject);
3091 else if(IsEqualIID(guidService, SID_IFolderView))
3092 return QueryInterface(riid, ppvObject);
3093
3094 return E_NOINTERFACE;
3095 }
3096
3097 HRESULT CDefView::_MergeToolbar()
3098 {
3099 CComPtr<IExplorerToolbar> ptb;
3100 HRESULT hr = S_OK;
3101
3102 hr = IUnknown_QueryService(m_pShellBrowser, IID_IExplorerToolbar, IID_PPV_ARG(IExplorerToolbar, &ptb));
3103 if (FAILED(hr))
3104 return hr;
3105
3106 m_Category = CGID_DefViewFrame;
3107
3108 hr = ptb->SetCommandTarget(static_cast<IOleCommandTarget*>(this), &m_Category, 0);
3109 if (FAILED(hr))
3110 return hr;
3111
3112 if (hr == S_FALSE)
3113 return S_OK;
3114
3115 #if 0
3116 hr = ptb->AddButtons(&m_Category, buttonsCount, buttons);
3117 if (FAILED(hr))
3118 return hr;
3119 #endif
3120
3121 return S_OK;
3122 }
3123 /**********************************************************
3124 * IShellView_Constructor
3125 */
3126 HRESULT WINAPI IShellView_Constructor(IShellFolder *pFolder, IShellView **newView)
3127 {
3128 return ShellObjectCreatorInit<CDefView>(pFolder, IID_IShellView, newView);
3129 }
3130
3131 HRESULT WINAPI CDefView_Constructor(IShellFolder *pFolder, REFIID riid, LPVOID * ppvOut)
3132 {
3133 return ShellObjectCreatorInit<CDefView>(pFolder, riid, ppvOut);
3134 }