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