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