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