3cfe27f14fd7b258a870e972522f4ba7b9e3878c
[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 = m_pCM->QueryContextMenu(hMenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY);
1227 if (FAILED(hResult))
1228 goto cleanup;
1229
1230 uCommand = GetMenuDefaultItem(hMenu, FALSE, 0);
1231 if (uCommand == (UINT)-1)
1232 {
1233 hResult = E_FAIL;
1234 goto cleanup;
1235 }
1236
1237 ZeroMemory(&cmi, sizeof(cmi));
1238 cmi.cbSize = sizeof(cmi);
1239 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1240 cmi.hwnd = m_hWnd;
1241
1242 hResult = m_pCM->InvokeCommand(&cmi);
1243
1244 cleanup:
1245
1246 if (hMenu)
1247 DestroyMenu(hMenu);
1248
1249 if (m_pCM)
1250 m_pCM.Release();
1251
1252 return hResult;
1253 }
1254
1255 /**********************************************************
1256 * ShellView_DoContextMenu()
1257 */
1258 LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1259 {
1260 WORD x;
1261 WORD y;
1262 UINT uCommand;
1263 HMENU hMenu;
1264 CMINVOKECOMMANDINFO cmi;
1265 HRESULT hResult;
1266
1267 // for some reason I haven't figured out, we sometimes recurse into this method
1268 if (m_pCM != NULL)
1269 return 0;
1270
1271 x = LOWORD(lParam);
1272 y = HIWORD(lParam);
1273
1274 TRACE("(%p)->(0x%08x 0x%08x) stub\n", this, x, y);
1275
1276 hMenu = CreatePopupMenu();
1277 if (!hMenu)
1278 return E_FAIL;
1279
1280 m_cidl = m_ListView.GetSelectedCount();
1281
1282 hResult = GetItemObject( m_cidl ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
1283 if (FAILED( hResult))
1284 goto cleanup;
1285
1286 hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
1287 if (FAILED( hResult))
1288 goto cleanup;
1289
1290 if (m_FolderSettings.fFlags & FWF_DESKTOP)
1291 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
1292
1293 uCommand = TrackPopupMenu(hMenu,
1294 TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
1295 x, y, 0, m_hWnd, NULL);
1296 if (uCommand == 0)
1297 goto cleanup;
1298
1299 if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK)
1300 goto cleanup;
1301
1302 ZeroMemory(&cmi, sizeof(cmi));
1303 cmi.cbSize = sizeof(cmi);
1304 cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1305 cmi.hwnd = m_hWnd;
1306 m_pCM->InvokeCommand(&cmi);
1307
1308 cleanup:
1309
1310 if (m_pCM)
1311 m_pCM.Release();
1312
1313 if (hMenu)
1314 DestroyMenu(hMenu);
1315
1316 return 0;
1317 }
1318
1319 LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection)
1320 {
1321 HRESULT hResult;
1322 CMINVOKECOMMANDINFO cmi;
1323 HMENU hMenu;
1324
1325 hMenu = CreatePopupMenu();
1326 if (!hMenu)
1327 return 0;
1328
1329 hResult = GetItemObject( bUseSelection ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM));
1330 if (FAILED( hResult))
1331 goto cleanup;
1332
1333 hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL);
1334 if (FAILED( hResult))
1335 goto cleanup;
1336
1337 ZeroMemory(&cmi, sizeof(cmi));
1338 cmi.cbSize = sizeof(cmi);
1339 cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1340 cmi.hwnd = m_hWnd;
1341 m_pCM->InvokeCommand(&cmi);
1342
1343 cleanup:
1344
1345 if (m_pCM)
1346 m_pCM.Release();
1347
1348 if (hMenu)
1349 DestroyMenu(hMenu);
1350
1351 return 0;
1352 }
1353
1354 /**********************************************************
1355 * ##### message handling #####
1356 */
1357
1358 /**********************************************************
1359 * ShellView_OnSize()
1360 */
1361 LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1362 {
1363 WORD wWidth;
1364 WORD wHeight;
1365
1366 wWidth = LOWORD(lParam);
1367 wHeight = HIWORD(lParam);
1368
1369 TRACE("%p width=%u height=%u\n", this, wWidth, wHeight);
1370
1371 /*resize the ListView to fit our window*/
1372 if (m_ListView)
1373 {
1374 ::MoveWindow(m_ListView, 0, 0, wWidth, wHeight, TRUE);
1375 }
1376
1377 return 0;
1378 }
1379
1380 /**********************************************************
1381 * ShellView_OnDeactivate()
1382 *
1383 * NOTES
1384 * internal
1385 */
1386 void CDefView::OnDeactivate()
1387 {
1388 TRACE("%p\n", this);
1389
1390 if (m_uState != SVUIA_DEACTIVATE)
1391 {
1392 // TODO: cleanup menu after deactivation
1393
1394 m_uState = SVUIA_DEACTIVATE;
1395 }
1396 }
1397
1398 void CDefView::DoActivate(UINT uState)
1399 {
1400 TRACE("%p uState=%x\n", this, uState);
1401
1402 /*don't do anything if the state isn't really changing */
1403 if (m_uState == uState)
1404 {
1405 return;
1406 }
1407
1408 if (uState == SVUIA_DEACTIVATE)
1409 {
1410 OnDeactivate();
1411 }
1412 else
1413 {
1414 if(m_hMenu)
1415 {
1416 if (!m_menusLoaded)
1417 {
1418 MENUITEMINFOW mii = { 0 };
1419
1420 /* initialize EDIT menu */
1421 mii.cbSize = sizeof(mii);
1422 mii.fMask = MIIM_SUBMENU;
1423 if (::GetMenuItemInfoW(m_hMenu, FCIDM_MENU_EDIT, FALSE, &mii))
1424 {
1425 HMENU hSubMenu = mii.hSubMenu;
1426
1427 HMENU menubase = ::LoadMenuW(shell32_hInstance, L"MENU_003");
1428
1429 int count = ::GetMenuItemCount(menubase);
1430 for (int i = 0; i < count; i++)
1431 {
1432 WCHAR label[128];
1433
1434 ZeroMemory(&mii, sizeof(mii));
1435 mii.cbSize = sizeof(mii);
1436 mii.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_DATA | MIIM_STRING | MIIM_BITMAP | MIIM_FTYPE;
1437 mii.dwTypeData = label;
1438 mii.cch = _countof(label);
1439 ::GetMenuItemInfoW(menubase, i, TRUE, &mii);
1440
1441 TRACE("Adding item %d label %S type %d\n", mii.wID, mii.dwTypeData, mii.fType);
1442
1443 mii.fType |= MFT_RADIOCHECK;
1444
1445 ::InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
1446 }
1447
1448 ::DestroyMenu(menubase);
1449 }
1450
1451 /* initialize VIEW menu */
1452
1453 mii.cbSize = sizeof(mii);
1454 mii.fMask = MIIM_SUBMENU;
1455 if (::GetMenuItemInfoW(m_hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1456 {
1457 HMENU menubase = ::LoadMenuW(shell32_hInstance, L"MENU_001");
1458
1459 HMENU hSubMenu = mii.hSubMenu;
1460
1461 m_hView = CreatePopupMenu();
1462
1463 _InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
1464
1465 int count = ::GetMenuItemCount(menubase);
1466 for (int i = 0; i < count; i++)
1467 {
1468 WCHAR label[128];
1469
1470 ZeroMemory(&mii, sizeof(mii));
1471 mii.cbSize = sizeof(mii);
1472 mii.fMask = MIIM_STATE | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_DATA | MIIM_STRING | MIIM_BITMAP | MIIM_FTYPE;
1473 mii.dwTypeData = label;
1474 mii.cch = _countof(label);
1475 ::GetMenuItemInfoW(menubase, i, TRUE, &mii);
1476
1477 ::AppendMenuW(m_hView, mii.fType, mii.wID, mii.dwTypeData);
1478
1479 TRACE("Adding item %d label %S type %d\n", mii.wID, mii.dwTypeData, mii.fType);
1480
1481 mii.fType |= MFT_RADIOCHECK;
1482
1483 ::InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
1484 }
1485
1486 ::DestroyMenu(menubase);
1487 }
1488
1489
1490 TRACE("-- before fnSetMenuSB\n");
1491 m_pShellBrowser->SetMenuSB(m_hMenu, 0, m_hWnd);
1492
1493 m_menusLoaded = TRUE;
1494 }
1495 }
1496
1497 if (SVUIA_ACTIVATE_FOCUS == uState)
1498 {
1499 m_ListView.SetFocus();
1500 }
1501 }
1502
1503 m_uState = uState;
1504 TRACE("--\n");
1505 }
1506
1507 /**********************************************************
1508 * ShellView_OnActivate()
1509 */
1510 LRESULT CDefView::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1511 {
1512 DoActivate(SVUIA_ACTIVATE_FOCUS);
1513 return 0;
1514 }
1515
1516 /**********************************************************
1517 * ShellView_OnSetFocus()
1518 *
1519 */
1520 LRESULT CDefView::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1521 {
1522 TRACE("%p\n", this);
1523
1524 /* Tell the browser one of our windows has received the focus. This
1525 should always be done before merging menus (OnActivate merges the
1526 menus) if one of our windows has the focus.*/
1527
1528 m_pShellBrowser->OnViewWindowActive(this);
1529 DoActivate(SVUIA_ACTIVATE_FOCUS);
1530
1531 /* Set the focus to the listview */
1532 m_ListView.SetFocus();
1533
1534 /* Notify the ICommDlgBrowser interface */
1535 OnStateChange(CDBOSC_SETFOCUS);
1536
1537 return 0;
1538 }
1539
1540 /**********************************************************
1541 * ShellView_OnKillFocus()
1542 */
1543 LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1544 {
1545 TRACE("(%p) stub\n", this);
1546
1547 DoActivate(SVUIA_ACTIVATE_NOFOCUS);
1548 /* Notify the ICommDlgBrowser */
1549 OnStateChange(CDBOSC_KILLFOCUS);
1550
1551 return 0;
1552 }
1553
1554 /**********************************************************
1555 * ShellView_OnCommand()
1556 *
1557 * NOTES
1558 * the CmdID's are the ones from the context menu
1559 */
1560 LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1561 {
1562 DWORD dwCmdID;
1563 DWORD dwCmd;
1564 HWND hwndCmd;
1565 int nCount;
1566
1567 dwCmdID = GET_WM_COMMAND_ID(wParam, lParam);
1568 dwCmd = GET_WM_COMMAND_CMD(wParam, lParam);
1569 hwndCmd = GET_WM_COMMAND_HWND(wParam, lParam);
1570
1571 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n", this, dwCmdID, dwCmd, hwndCmd);
1572
1573 switch (dwCmdID)
1574 {
1575 case FCIDM_SHVIEW_SMALLICON:
1576 m_FolderSettings.ViewMode = FVM_SMALLICON;
1577 SetStyle (LVS_SMALLICON, LVS_TYPEMASK);
1578 CheckToolbar();
1579 break;
1580
1581 case FCIDM_SHVIEW_BIGICON:
1582 m_FolderSettings.ViewMode = FVM_ICON;
1583 SetStyle (LVS_ICON, LVS_TYPEMASK);
1584 CheckToolbar();
1585 break;
1586
1587 case FCIDM_SHVIEW_LISTVIEW:
1588 m_FolderSettings.ViewMode = FVM_LIST;
1589 SetStyle (LVS_LIST, LVS_TYPEMASK);
1590 CheckToolbar();
1591 break;
1592
1593 case FCIDM_SHVIEW_REPORTVIEW:
1594 m_FolderSettings.ViewMode = FVM_DETAILS;
1595 SetStyle (LVS_REPORT, LVS_TYPEMASK);
1596 CheckToolbar();
1597 break;
1598
1599 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1600 case 0x30:
1601 case 0x31:
1602 case 0x32:
1603 case 0x33:
1604 m_sortInfo.nHeaderID = dwCmdID - 0x30;
1605 m_sortInfo.bIsAscending = TRUE;
1606 m_sortInfo.nLastHeaderID = m_sortInfo.nHeaderID;
1607 m_ListView.SortItems(ListViewCompareItems, &m_sortInfo);
1608 break;
1609
1610 case FCIDM_SHVIEW_SELECTALL:
1611 m_ListView.SetItemState(-1, LVIS_SELECTED, LVIS_SELECTED);
1612 break;
1613
1614 case FCIDM_SHVIEW_INVERTSELECTION:
1615 nCount = m_ListView.GetItemCount();
1616 for (int i=0; i < nCount; i++)
1617 m_ListView.SetItemState(i, m_ListView.GetItemState(i, LVIS_SELECTED) ? 0 : LVIS_SELECTED, LVIS_SELECTED);
1618 break;
1619
1620 case FCIDM_SHVIEW_REFRESH:
1621 Refresh();
1622 break;
1623
1624 case FCIDM_SHVIEW_DELETE:
1625 case FCIDM_SHVIEW_CUT:
1626 case FCIDM_SHVIEW_COPY:
1627 case FCIDM_SHVIEW_RENAME:
1628 return OnExplorerCommand(dwCmdID, TRUE);
1629
1630 case FCIDM_SHVIEW_INSERT:
1631 case FCIDM_SHVIEW_UNDO:
1632 case FCIDM_SHVIEW_INSERTLINK:
1633 case FCIDM_SHVIEW_NEWFOLDER:
1634 return OnExplorerCommand(dwCmdID, FALSE);
1635 default:
1636 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID);
1637 }
1638
1639 return 0;
1640 }
1641
1642 /**********************************************************
1643 * ShellView_OnNotify()
1644 */
1645
1646 LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1647 {
1648 UINT CtlID;
1649 LPNMHDR lpnmh;
1650 LPNMLISTVIEW lpnmlv;
1651 NMLVDISPINFOW *lpdi;
1652 PCUITEMID_CHILD pidl;
1653 BOOL unused;
1654
1655 CtlID = wParam;
1656 lpnmh = (LPNMHDR)lParam;
1657 lpnmlv = (LPNMLISTVIEW)lpnmh;
1658 lpdi = (NMLVDISPINFOW *)lpnmh;
1659
1660 TRACE("%p CtlID=%u lpnmh->code=%x\n", this, CtlID, lpnmh->code);
1661
1662 switch (lpnmh->code)
1663 {
1664 case NM_SETFOCUS:
1665 TRACE("-- NM_SETFOCUS %p\n", this);
1666 OnSetFocus(0, 0, 0, unused);
1667 break;
1668
1669 case NM_KILLFOCUS:
1670 TRACE("-- NM_KILLFOCUS %p\n", this);
1671 OnDeactivate();
1672 /* Notify the ICommDlgBrowser interface */
1673 OnStateChange(CDBOSC_KILLFOCUS);
1674 break;
1675
1676 case NM_CUSTOMDRAW:
1677 TRACE("-- NM_CUSTOMDRAW %p\n", this);
1678 return CDRF_DODEFAULT;
1679
1680 case NM_RELEASEDCAPTURE:
1681 TRACE("-- NM_RELEASEDCAPTURE %p\n", this);
1682 break;
1683
1684 case NM_CLICK:
1685 TRACE("-- NM_CLICK %p\n", this);
1686 break;
1687
1688 case NM_RCLICK:
1689 TRACE("-- NM_RCLICK %p\n", this);
1690 break;
1691
1692 case NM_DBLCLK:
1693 TRACE("-- NM_DBLCLK %p\n", this);
1694 OpenSelectedItems();
1695 break;
1696
1697 case NM_RETURN:
1698 TRACE("-- NM_RETURN %p\n", this);
1699 OpenSelectedItems();
1700 break;
1701
1702 case HDN_ENDTRACKW:
1703 TRACE("-- HDN_ENDTRACKW %p\n", this);
1704 /*nColumn1 = m_ListView.GetColumnWidth(0);
1705 nColumn2 = m_ListView.GetColumnWidth(1);*/
1706 break;
1707
1708 case LVN_DELETEITEM:
1709 TRACE("-- LVN_DELETEITEM %p\n", this);
1710
1711 /*delete the pidl because we made a copy of it*/
1712 SHFree(reinterpret_cast<LPVOID>(lpnmlv->lParam));
1713
1714 break;
1715
1716 case LVN_DELETEALLITEMS:
1717 TRACE("-- LVN_DELETEALLITEMS %p\n", this);
1718 return FALSE;
1719
1720 case LVN_INSERTITEM:
1721 TRACE("-- LVN_INSERTITEM (STUB)%p\n", this);
1722 break;
1723
1724 case LVN_ITEMACTIVATE:
1725 TRACE("-- LVN_ITEMACTIVATE %p\n", this);
1726 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1727 break;
1728
1729 case LVN_COLUMNCLICK:
1730 m_sortInfo.nHeaderID = lpnmlv->iSubItem;
1731 if (m_sortInfo.nLastHeaderID == m_sortInfo.nHeaderID)
1732 m_sortInfo.bIsAscending = !m_sortInfo.bIsAscending;
1733 else
1734 m_sortInfo.bIsAscending = TRUE;
1735 m_sortInfo.nLastHeaderID = m_sortInfo.nHeaderID;
1736
1737 m_ListView.SortItems(ListViewCompareItems, &m_sortInfo);
1738 break;
1739
1740 case LVN_GETDISPINFOA:
1741 case LVN_GETDISPINFOW:
1742 TRACE("-- LVN_GETDISPINFO %p\n", this);
1743 pidl = _PidlByItem(lpdi->item);
1744
1745 if (lpdi->item.mask & LVIF_TEXT) /* text requested */
1746 {
1747 if (m_pSF2Parent)
1748 {
1749 SHELLDETAILS sd;
1750 if (FAILED(m_pSF2Parent->GetDetailsOf(pidl, lpdi->item.iSubItem, &sd)))
1751 {
1752 FIXME("failed to get details\n");
1753 break;
1754 }
1755
1756 if (lpnmh->code == LVN_GETDISPINFOA)
1757 {
1758 /* shouldn't happen */
1759 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1760 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1761 TRACE("-- text=%s\n", lpdiA->item.pszText);
1762 }
1763 else /* LVN_GETDISPINFOW */
1764 {
1765 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1766 TRACE("-- text=%s\n", debugstr_w(lpdi->item.pszText));
1767 }
1768 }
1769 else
1770 {
1771 FIXME("no SF2\n");
1772 }
1773 }
1774 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1775 {
1776 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0);
1777 }
1778 if(lpdi->item.mask & LVIF_STATE)
1779 {
1780 ULONG attributes = SFGAO_HIDDEN;
1781 if (SUCCEEDED(m_pSFParent->GetAttributesOf(1, &pidl, &attributes)))
1782 {
1783 if (attributes & SFGAO_HIDDEN)
1784 {
1785 lpdi->item.state |= LVIS_CUT;
1786 }
1787 }
1788 }
1789 lpdi->item.mask |= LVIF_DI_SETITEM;
1790 break;
1791
1792 case LVN_ITEMCHANGED:
1793 TRACE("-- LVN_ITEMCHANGED %p\n", this);
1794 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1795 break;
1796
1797 case LVN_BEGINDRAG:
1798 case LVN_BEGINRDRAG:
1799 TRACE("-- LVN_BEGINDRAG\n");
1800
1801 if (GetSelections())
1802 {
1803 CComPtr<IDataObject> pda;
1804 DWORD dwAttributes = SFGAO_CANLINK;
1805 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1806
1807 if (SUCCEEDED(m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IDataObject, &pda))))
1808 {
1809 if (SUCCEEDED(m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &dwAttributes)))
1810 {
1811 if (dwAttributes & SFGAO_CANLINK)
1812 {
1813 dwEffect |= DROPEFFECT_LINK;
1814 }
1815 }
1816
1817 CComPtr<IAsyncOperation> piaso;
1818 if (SUCCEEDED(pda->QueryInterface(IID_PPV_ARG(IAsyncOperation, &piaso))))
1819 {
1820 piaso->SetAsyncMode(TRUE);
1821 }
1822
1823 DWORD dwEffect2;
1824 DoDragDrop(pda, this, dwEffect, &dwEffect2);
1825 }
1826 }
1827 break;
1828
1829 case LVN_BEGINLABELEDITW:
1830 {
1831 DWORD dwAttr = SFGAO_CANRENAME;
1832 pidl = _PidlByItem(lpdi->item);
1833
1834 TRACE("-- LVN_BEGINLABELEDITW %p\n", this);
1835
1836 m_pSFParent->GetAttributesOf(1, &pidl, &dwAttr);
1837 if (SFGAO_CANRENAME & dwAttr)
1838 {
1839 m_isEditing = TRUE;
1840 return FALSE;
1841 }
1842 return TRUE;
1843 }
1844
1845 case LVN_ENDLABELEDITW:
1846 {
1847 TRACE("-- LVN_ENDLABELEDITW %p\n", this);
1848
1849 m_isEditing = FALSE;
1850
1851 if (lpdi->item.pszText)
1852 {
1853 HRESULT hr;
1854 LVITEMW lvItem;
1855
1856 pidl = _PidlByItem(lpdi->item);
1857 PITEMID_CHILD pidlNew;
1858 hr = m_pSFParent->SetNameOf(0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidlNew);
1859
1860 if (SUCCEEDED(hr) && pidlNew)
1861 {
1862 lvItem.mask = LVIF_PARAM|LVIF_IMAGE;
1863 lvItem.iItem = lpdi->item.iItem;
1864 lvItem.lParam = reinterpret_cast<LPARAM>(pidlNew);
1865 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0);
1866 m_ListView.SetItem(&lvItem);
1867 m_ListView.Update(lpdi->item.iItem);
1868 return TRUE;
1869 }
1870 }
1871
1872 return FALSE;
1873 }
1874
1875 default:
1876 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh->code);
1877 break;
1878 }
1879
1880 return 0;
1881 }
1882
1883 /*
1884 * This is just a quick hack to make the desktop work correctly.
1885 * ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the way that
1886 * a folder should know if it should update upon a change notification.
1887 * It is exported by merged folders at a minimum.
1888 */
1889 static BOOL ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2)
1890 {
1891 if (!pidl1 || !pidl2)
1892 return FALSE;
1893 if (ILIsParent(pidl1, pidl2, TRUE))
1894 return TRUE;
1895
1896 if (_ILIsDesktop(pidl1))
1897 {
1898 PIDLIST_ABSOLUTE deskpidl;
1899 SHGetFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
1900 if (ILIsParent(deskpidl, pidl2, TRUE))
1901 {
1902 ILFree(deskpidl);
1903 return TRUE;
1904 }
1905 ILFree(deskpidl);
1906 SHGetFolderLocation(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, &deskpidl);
1907 if (ILIsParent(deskpidl, pidl2, TRUE))
1908 {
1909 ILFree(deskpidl);
1910 return TRUE;
1911 }
1912 ILFree(deskpidl);
1913 }
1914 return FALSE;
1915 }
1916
1917 /**********************************************************
1918 * ShellView_OnChange()
1919 */
1920 LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1921 {
1922 PCIDLIST_ABSOLUTE *Pidls = reinterpret_cast<PCIDLIST_ABSOLUTE*>(wParam);
1923 BOOL bParent0 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[0]);
1924 BOOL bParent1 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[1]);
1925
1926 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam);
1927
1928 switch (lParam)
1929 {
1930 case SHCNE_MKDIR:
1931 case SHCNE_CREATE:
1932 if (bParent0)
1933 {
1934 if (LV_FindItemByPidl(ILFindLastID(Pidls[0])) == -1)
1935 {
1936 LV_AddItem(ILFindLastID(Pidls[0]));
1937 }
1938 else
1939 {
1940 LV_ProdItem(ILFindLastID(Pidls[0]));
1941 }
1942 }
1943 break;
1944
1945 case SHCNE_RMDIR:
1946 case SHCNE_DELETE:
1947 if (bParent0)
1948 LV_DeleteItem(ILFindLastID(Pidls[0]));
1949 break;
1950
1951 case SHCNE_RENAMEFOLDER:
1952 case SHCNE_RENAMEITEM:
1953 if (bParent0 && bParent1)
1954 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[1]));
1955 else if (bParent0)
1956 LV_DeleteItem(ILFindLastID(Pidls[0]));
1957 else if (bParent1)
1958 LV_AddItem(ILFindLastID(Pidls[1]));
1959 break;
1960
1961 case SHCNE_UPDATEITEM:
1962 if (bParent0)
1963 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0]));
1964 break;
1965
1966 case SHCNE_UPDATEDIR:
1967 Refresh();
1968 break;
1969 }
1970 return TRUE;
1971 }
1972
1973 /**********************************************************
1974 * CDefView::OnCustomItem
1975 */
1976 LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1977 {
1978 if (!m_pCM.p)
1979 {
1980 /* no menu */
1981 ERR("no menu!!!\n");
1982 return FALSE;
1983 }
1984
1985 LRESULT result;
1986 HRESULT hres = SHForwardContextMenuMsg(m_pCM, uMsg, wParam, lParam, &result, TRUE);
1987 if (SUCCEEDED(hres))
1988 return TRUE;
1989 else
1990 return FALSE;
1991 }
1992
1993 LRESULT CDefView::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1994 {
1995 /* Wallpaper setting affects drop shadows effect */
1996 if (wParam == SPI_SETDESKWALLPAPER || wParam == 0)
1997 UpdateListColors();
1998
1999 return S_OK;
2000 }
2001
2002 /**********************************************************
2003 * CDefView::OnInitMenuPopup
2004 */
2005 LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2006 {
2007 MENUITEMINFOW mii = { 0 };
2008 HMENU hSubmenu = (HMENU) wParam;
2009
2010 TRACE("OnInitMenuPopup lParam=%d\n", lParam);
2011
2012 mii.cbSize = sizeof(mii);
2013 mii.fMask = MIIM_ID | MIIM_SUBMENU;
2014
2015 if (!GetMenuItemInfoW(this->m_hMenu, lParam, TRUE, &mii))
2016 {
2017 TRACE("OnInitMenuPopup GetMenuItemInfoW failed!\n");
2018 return FALSE;
2019 }
2020
2021 UINT menuItemId = mii.wID;
2022
2023 if (mii.hSubMenu != hSubmenu)
2024 {
2025 TRACE("OnInitMenuPopup submenu does not match!!!!\n");
2026 return FALSE;
2027 }
2028
2029 TRACE("OnInitMenuPopup id=%d\n", menuItemId);
2030
2031 switch (menuItemId)
2032 {
2033 case FCIDM_MENU_FILE:
2034 PrepareShowFileMenu(hSubmenu);
2035 break;
2036 case FCIDM_MENU_EDIT:
2037 //PrepareShowEditMenu(hSubmenu);
2038 break;
2039 case FCIDM_MENU_VIEW:
2040 PrepareShowViewMenu(hSubmenu);
2041 break;
2042 }
2043
2044 return FALSE;
2045 }
2046
2047 /**********************************************************
2048 *
2049 *
2050 * The INTERFACE of the IShellView object
2051 *
2052 *
2053 **********************************************************
2054 */
2055
2056 /**********************************************************
2057 * ShellView_GetWindow
2058 */
2059 HRESULT WINAPI CDefView::GetWindow(HWND *phWnd)
2060 {
2061 TRACE("(%p)\n", this);
2062
2063 *phWnd = m_hWnd;
2064
2065 return S_OK;
2066 }
2067
2068 HRESULT WINAPI CDefView::ContextSensitiveHelp(BOOL fEnterMode)
2069 {
2070 FIXME("(%p) stub\n", this);
2071
2072 return E_NOTIMPL;
2073 }
2074
2075 /**********************************************************
2076 * IShellView_TranslateAccelerator
2077 *
2078 * FIXME:
2079 * use the accel functions
2080 */
2081 HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg)
2082 {
2083 if (m_isEditing)
2084 return S_FALSE;
2085
2086 if (lpmsg->message >= WM_KEYFIRST && lpmsg->message <= WM_KEYLAST)
2087 {
2088 if (::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg) != 0)
2089 return S_OK;
2090
2091 TRACE("-- key=0x04%lx\n", lpmsg->wParam) ;
2092 }
2093
2094 return m_pShellBrowser->TranslateAcceleratorSB(lpmsg, 0);
2095 }
2096
2097 HRESULT WINAPI CDefView::EnableModeless(BOOL fEnable)
2098 {
2099 FIXME("(%p) stub\n", this);
2100
2101 return E_NOTIMPL;
2102 }
2103
2104 HRESULT WINAPI CDefView::UIActivate(UINT uState)
2105 {
2106 /*
2107 CHAR szName[MAX_PATH];
2108 */
2109 LRESULT lResult;
2110 int nPartArray[1] = { -1};
2111
2112 TRACE("(%p)->(state=%x) stub\n", this, uState);
2113
2114 /*don't do anything if the state isn't really changing*/
2115 if (m_uState == uState)
2116 {
2117 return S_OK;
2118 }
2119
2120 /*OnActivate handles the menu merging and internal state*/
2121 DoActivate(uState);
2122
2123 /*only do This if we are active*/
2124 if (uState != SVUIA_DEACTIVATE)
2125 {
2126
2127 /*
2128 GetFolderPath is not a method of IShellFolder
2129 IShellFolder_GetFolderPath( m_pSFParent, szName, sizeof(szName) );
2130 */
2131 /* set the number of parts */
2132 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult);
2133
2134 /* set the text for the parts */
2135 /*
2136 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult);
2137 */
2138 }
2139
2140 return S_OK;
2141 }
2142
2143 HRESULT WINAPI CDefView::Refresh()
2144 {
2145 TRACE("(%p)\n", this);
2146
2147 m_ListView.DeleteAllItems();
2148 FillList();
2149
2150 return S_OK;
2151 }
2152
2153 HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd)
2154 {
2155 OLEMENUGROUPWIDTHS omw = { { 0, 0, 0, 0, 0, 0 } };
2156
2157 *phWnd = 0;
2158
2159 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n", this, lpPrevView, lpfs, psb, prcView, phWnd);
2160
2161 if (lpfs != NULL)
2162 TRACE("-- vmode=%x flags=%x\n", lpfs->ViewMode, lpfs->fFlags);
2163 if (prcView != NULL)
2164 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom);
2165
2166 /* Validate the Shell Browser */
2167 if (psb == NULL)
2168 return E_UNEXPECTED;
2169
2170 /*set up the member variables*/
2171 m_pShellBrowser = psb;
2172 m_FolderSettings = *lpfs;
2173
2174 /*get our parent window*/
2175 m_pShellBrowser->GetWindow(&m_hWndParent);
2176
2177 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
2178 m_pCommDlgBrowser = NULL;
2179 if (SUCCEEDED(m_pShellBrowser->QueryInterface(IID_PPV_ARG(ICommDlgBrowser, &m_pCommDlgBrowser))))
2180 {
2181 TRACE("-- CommDlgBrowser\n");
2182 }
2183
2184 Create(m_hWndParent, prcView, NULL, WS_CHILD | WS_TABSTOP, 0, 0U);
2185 if (m_hWnd == NULL)
2186 return E_FAIL;
2187
2188 *phWnd = m_hWnd;
2189
2190 CheckToolbar();
2191
2192 if (!*phWnd)
2193 return E_FAIL;
2194
2195 SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
2196 UpdateWindow();
2197
2198 if (!m_hMenu)
2199 {
2200 m_hMenu = CreateMenu();
2201 m_pShellBrowser->InsertMenusSB(m_hMenu, &omw);
2202 TRACE("-- after fnInsertMenusSB\n");
2203 }
2204
2205 _MergeToolbar();
2206
2207 return S_OK;
2208 }
2209
2210 HRESULT WINAPI CDefView::DestroyViewWindow()
2211 {
2212 TRACE("(%p)\n", this);
2213
2214 /*Make absolutely sure all our UI is cleaned up.*/
2215 UIActivate(SVUIA_DEACTIVATE);
2216
2217 if (m_hAccel)
2218 {
2219 // "Accelerator tables loaded from resources are freed automatically when the application terminates." -- MSDN
2220 m_hAccel = NULL;
2221 }
2222
2223 if (m_hView)
2224 {
2225 DestroyMenu(m_hView);
2226 m_hView = NULL;
2227 }
2228
2229 if (m_hMenu)
2230 {
2231 DestroyMenu(m_hMenu);
2232 m_hView = NULL;
2233 }
2234
2235 if (m_ListView)
2236 {
2237 m_ListView.DestroyWindow();
2238 }
2239
2240 if (m_hWnd)
2241 {
2242 DestroyWindow();
2243 }
2244
2245 m_pShellBrowser.Release();
2246 m_pCommDlgBrowser.Release();
2247
2248 return S_OK;
2249 }
2250
2251 HRESULT WINAPI CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
2252 {
2253 TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs,
2254 m_FolderSettings.ViewMode, m_FolderSettings.fFlags);
2255
2256 if (!lpfs)
2257 return E_INVALIDARG;
2258
2259 *lpfs = m_FolderSettings;
2260 return S_OK;
2261 }
2262
2263 HRESULT WINAPI CDefView::AddPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
2264 {
2265 FIXME("(%p) stub\n", this);
2266
2267 return E_NOTIMPL;
2268 }
2269
2270 HRESULT WINAPI CDefView::SaveViewState()
2271 {
2272 FIXME("(%p) stub\n", this);
2273
2274 return S_OK;
2275 }
2276
2277 HRESULT WINAPI CDefView::SelectItem(PCUITEMID_CHILD pidl, UINT uFlags)
2278 {
2279 int i;
2280
2281 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl, uFlags);
2282
2283 i = LV_FindItemByPidl(pidl);
2284 if (i == -1)
2285 return S_OK;
2286
2287 if(uFlags & SVSI_ENSUREVISIBLE)
2288 m_ListView.EnsureVisible(i, FALSE);
2289
2290 LVITEMW lvItem = {0};
2291 lvItem.mask = LVIF_STATE;
2292 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
2293
2294 while (m_ListView.GetItem(&lvItem))
2295 {
2296 if (lvItem.iItem == i)
2297 {
2298 if (uFlags & SVSI_SELECT)
2299 lvItem.state |= LVIS_SELECTED;
2300 else
2301 lvItem.state &= ~LVIS_SELECTED;
2302
2303 if (uFlags & SVSI_FOCUSED)
2304 lvItem.state &= ~LVIS_FOCUSED;
2305 }
2306 else
2307 {
2308 if (uFlags & SVSI_DESELECTOTHERS)
2309 lvItem.state &= ~LVIS_SELECTED;
2310 }
2311
2312 m_ListView.SetItem(&lvItem);
2313 lvItem.iItem++;
2314 }
2315
2316 if(uFlags & SVSI_EDIT)
2317 m_ListView.EditLabel(i);
2318
2319 return S_OK;
2320 }
2321
2322 HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
2323 {
2324 HRESULT hr = E_NOINTERFACE;
2325
2326 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem, debugstr_guid(&riid), ppvOut);
2327
2328 *ppvOut = NULL;
2329
2330 switch (uItem)
2331 {
2332 case SVGIO_BACKGROUND:
2333 if (IsEqualIID(riid, IID_IContextMenu))
2334 {
2335 //*ppvOut = ISvBgCm_Constructor(m_pSFParent, FALSE);
2336 if (!ppvOut)
2337 hr = E_OUTOFMEMORY;
2338
2339 IContextMenu* pcm;
2340 hr = CDefFolderMenu_Create2(NULL, NULL, 0, NULL, m_pSFParent, NULL, 0, NULL, &pcm);
2341 if (FAILED(hr))
2342 return hr;
2343 *ppvOut = pcm;
2344 }
2345 break;
2346
2347 case SVGIO_SELECTION:
2348 GetSelections();
2349 hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, riid, 0, ppvOut);
2350 break;
2351 }
2352
2353 TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut);
2354
2355 return hr;
2356 }
2357
2358 HRESULT STDMETHODCALLTYPE CDefView::GetCurrentViewMode(UINT *pViewMode)
2359 {
2360 TRACE("(%p)->(%p), stub\n", this, pViewMode);
2361
2362 if (!pViewMode)
2363 return E_INVALIDARG;
2364
2365 *pViewMode = m_FolderSettings.ViewMode;
2366 return S_OK;
2367 }
2368
2369 HRESULT STDMETHODCALLTYPE CDefView::SetCurrentViewMode(UINT ViewMode)
2370 {
2371 DWORD dwStyle;
2372 TRACE("(%p)->(%u), stub\n", this, ViewMode);
2373
2374 /* It's not redundant to check FVM_AUTO because it's a (UINT)-1 */
2375 if (((INT)ViewMode < FVM_FIRST || (INT)ViewMode > FVM_LAST) && ((INT)ViewMode != FVM_AUTO))
2376 return E_INVALIDARG;
2377
2378 /* Windows before Vista uses LVM_SETVIEW and possibly
2379 LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview,
2380 while later versions seem to accomplish this through other
2381 means. */
2382 switch (ViewMode)
2383 {
2384 case FVM_ICON:
2385 dwStyle = LVS_ICON;
2386 break;
2387 case FVM_DETAILS:
2388 dwStyle = LVS_REPORT;
2389 break;
2390 case FVM_SMALLICON:
2391 dwStyle = LVS_SMALLICON;
2392 break;
2393 case FVM_LIST:
2394 dwStyle = LVS_LIST;
2395 break;
2396 default:
2397 {
2398 FIXME("ViewMode %d not implemented\n", ViewMode);
2399 dwStyle = LVS_LIST;
2400 break;
2401 }
2402 }
2403
2404 SetStyle(dwStyle, LVS_TYPEMASK);
2405
2406 /* This will not necessarily be the actual mode set above.
2407 This mimics the behavior of Windows XP. */
2408 m_FolderSettings.ViewMode = ViewMode;
2409
2410 return S_OK;
2411 }
2412
2413 HRESULT STDMETHODCALLTYPE CDefView::GetFolder(REFIID riid, void **ppv)
2414 {
2415 if (m_pSFParent == NULL)
2416 return E_FAIL;
2417
2418 return m_pSFParent->QueryInterface(riid, ppv);
2419 }
2420
2421 HRESULT STDMETHODCALLTYPE CDefView::Item(int iItemIndex, PITEMID_CHILD *ppidl)
2422 {
2423 PCUITEMID_CHILD pidl = _PidlByItem(iItemIndex);
2424 if (pidl)
2425 {
2426 *ppidl = ILClone(pidl);
2427 return S_OK;
2428 }
2429
2430 *ppidl = 0;
2431 return E_INVALIDARG;
2432 }
2433
2434 HRESULT STDMETHODCALLTYPE CDefView::ItemCount(UINT uFlags, int *pcItems)
2435 {
2436 TRACE("(%p)->(%u %p)\n", this, uFlags, pcItems);
2437
2438 if (uFlags != SVGIO_ALLVIEW)
2439 FIXME("some flags unsupported, %x\n", uFlags & ~SVGIO_ALLVIEW);
2440
2441 *pcItems = m_ListView.GetItemCount();
2442
2443 return S_OK;
2444 }
2445
2446 HRESULT STDMETHODCALLTYPE CDefView::Items(UINT uFlags, REFIID riid, void **ppv)
2447 {
2448 return E_NOTIMPL;
2449 }
2450
2451 HRESULT STDMETHODCALLTYPE CDefView::GetSelectionMarkedItem(int *piItem)
2452 {
2453 TRACE("(%p)->(%p)\n", this, piItem);
2454
2455 *piItem = m_ListView.GetSelectionMark();
2456
2457 return S_OK;
2458 }
2459
2460 HRESULT STDMETHODCALLTYPE CDefView::GetFocusedItem(int *piItem)
2461 {
2462 TRACE("(%p)->(%p)\n", this, piItem);
2463
2464 *piItem = m_ListView.GetNextItem(-1, LVNI_FOCUSED);
2465
2466 return S_OK;
2467 }
2468
2469 HRESULT STDMETHODCALLTYPE CDefView::GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt)
2470 {
2471 return E_NOTIMPL;
2472 }
2473
2474 HRESULT STDMETHODCALLTYPE CDefView::GetSpacing(POINT *ppt)
2475 {
2476 TRACE("(%p)->(%p)\n", this, ppt);
2477
2478 if (!m_ListView)
2479 return S_FALSE;
2480
2481 if (ppt)
2482 {
2483 SIZE spacing;
2484 m_ListView.GetItemSpacing(spacing);
2485
2486 ppt->x = spacing.cx;
2487 ppt->y = spacing.cy;
2488 }
2489
2490 return S_OK;
2491 }
2492
2493 HRESULT STDMETHODCALLTYPE CDefView::GetDefaultSpacing(POINT *ppt)
2494 {
2495 return E_NOTIMPL;
2496 }
2497
2498 HRESULT STDMETHODCALLTYPE CDefView::GetAutoArrange()
2499 {
2500 return E_NOTIMPL;
2501 }
2502
2503 HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags)
2504 {
2505 LVITEMW lvItem;
2506
2507 TRACE("(%p)->(%d, %x)\n", this, iItem, dwFlags);
2508
2509 lvItem.state = 0;
2510 lvItem.stateMask = LVIS_SELECTED;
2511
2512 if (dwFlags & SVSI_ENSUREVISIBLE)
2513 m_ListView.EnsureVisible(iItem, 0);
2514
2515 /* all items */
2516 if (dwFlags & SVSI_DESELECTOTHERS)
2517 m_ListView.SetItemState(-1, 0, LVIS_SELECTED);
2518
2519 /* this item */
2520 if (dwFlags & SVSI_SELECT)
2521 lvItem.state |= LVIS_SELECTED;
2522
2523 if (dwFlags & SVSI_FOCUSED)
2524 lvItem.stateMask |= LVIS_FOCUSED;
2525
2526 m_ListView.SetItemState(iItem, lvItem.state, lvItem.stateMask);
2527
2528 if (dwFlags & SVSI_EDIT)
2529 m_ListView.EditLabel(iItem);
2530
2531 return S_OK;
2532 }
2533
2534 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags)
2535 {
2536 return E_NOTIMPL;
2537 }
2538
2539 /**********************************************************
2540 * IShellFolderView implementation
2541 */
2542 HRESULT STDMETHODCALLTYPE CDefView::Rearrange(LPARAM sort)
2543 {
2544 FIXME("(%p)->(%ld) stub\n", this, sort);
2545 return E_NOTIMPL;
2546 }
2547
2548 HRESULT STDMETHODCALLTYPE CDefView::GetArrangeParam(LPARAM *sort)
2549 {
2550 FIXME("(%p)->(%p) stub\n", this, sort);
2551 return E_NOTIMPL;
2552 }
2553
2554 HRESULT STDMETHODCALLTYPE CDefView::ArrangeGrid()
2555 {
2556 FIXME("(%p) stub\n", this);
2557 return E_NOTIMPL;
2558 }
2559
2560 HRESULT STDMETHODCALLTYPE CDefView::AutoArrange()
2561 {
2562 FIXME("(%p) stub\n", this);
2563 return E_NOTIMPL;
2564 }
2565
2566 HRESULT STDMETHODCALLTYPE CDefView::AddObject(PITEMID_CHILD pidl, UINT *item)
2567 {
2568 FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2569 return E_NOTIMPL;
2570 }
2571
2572 HRESULT STDMETHODCALLTYPE CDefView::GetObject(PITEMID_CHILD *pidl, UINT item)
2573 {
2574 TRACE("(%p)->(%p %d)\n", this, pidl, item);
2575 return Item(item, pidl);
2576 }
2577
2578 HRESULT STDMETHODCALLTYPE CDefView::RemoveObject(PITEMID_CHILD pidl, UINT *item)
2579 {
2580
2581 TRACE("(%p)->(%p %p)\n", this, pidl, item);
2582
2583 if (pidl)
2584 {
2585 *item = LV_FindItemByPidl(ILFindLastID(pidl));
2586 m_ListView.DeleteItem(*item);
2587 }
2588 else
2589 {
2590 *item = 0;
2591 m_ListView.DeleteAllItems();
2592 }
2593
2594 return S_OK;
2595 }
2596
2597 HRESULT STDMETHODCALLTYPE CDefView::GetObjectCount(UINT *count)
2598 {
2599 TRACE("(%p)->(%p)\n", this, count);
2600 *count = m_ListView.GetItemCount();
2601 return S_OK;
2602 }
2603
2604 HRESULT STDMETHODCALLTYPE CDefView::SetObjectCount(UINT count, UINT flags)
2605 {
2606 FIXME("(%p)->(%d %x) stub\n", this, count, flags);
2607 return E_NOTIMPL;
2608 }
2609
2610 HRESULT STDMETHODCALLTYPE CDefView::UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item)
2611 {
2612 FIXME("(%p)->(%p %p %p) stub\n", this, pidl_old, pidl_new, item);
2613 return E_NOTIMPL;
2614 }
2615
2616 HRESULT STDMETHODCALLTYPE CDefView::RefreshObject(PITEMID_CHILD pidl, UINT *item)
2617 {
2618 FIXME("(%p)->(%p %p) stub\n", this, pidl, item);
2619 return E_NOTIMPL;
2620 }
2621
2622 HRESULT STDMETHODCALLTYPE CDefView::SetRedraw(BOOL redraw)
2623 {
2624 TRACE("(%p)->(%d)\n", this, redraw);
2625 m_ListView.SetRedraw(redraw);
2626 return S_OK;
2627 }
2628
2629 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedCount(UINT *count)
2630 {
2631 FIXME("(%p)->(%p) stub\n", this, count);
2632 return E_NOTIMPL;
2633 }
2634
2635 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items)
2636 {
2637 TRACE("(%p)->(%p %p)\n", this, pidl, items);
2638
2639 *items = GetSelections();
2640
2641 if (*items)
2642 {
2643 *pidl = static_cast<PCUITEMID_CHILD *>(LocalAlloc(0, *items * sizeof(PCUITEMID_CHILD)));
2644 if (!*pidl)
2645 {
2646 return E_OUTOFMEMORY;
2647 }
2648
2649 /* it's documented that caller shouldn't PIDLs, only array itself */
2650 memcpy(*pidl, m_apidl, *items * sizeof(PCUITEMID_CHILD));
2651 }
2652
2653 return S_OK;
2654 }
2655
2656 HRESULT STDMETHODCALLTYPE CDefView::IsDropOnSource(IDropTarget *drop_target)
2657 {
2658 FIXME("(%p)->(%p) stub\n", this, drop_target);
2659 return E_NOTIMPL;
2660 }
2661
2662 HRESULT STDMETHODCALLTYPE CDefView::GetDragPoint(POINT *pt)
2663 {
2664 FIXME("(%p)->(%p) stub\n", this, pt);
2665 return E_NOTIMPL;
2666 }
2667
2668 HRESULT STDMETHODCALLTYPE CDefView::GetDropPoint(POINT *pt)
2669 {
2670 FIXME("(%p)->(%p) stub\n", this, pt);
2671 return E_NOTIMPL;
2672 }
2673
2674 HRESULT STDMETHODCALLTYPE CDefView::MoveIcons(IDataObject *obj)
2675 {
2676 TRACE("(%p)->(%p)\n", this, obj);
2677 return E_NOTIMPL;
2678 }
2679
2680 HRESULT STDMETHODCALLTYPE CDefView::SetItemPos(PCUITEMID_CHILD pidl, POINT *pt)
2681 {
2682 FIXME("(%p)->(%p %p) stub\n", this, pidl, pt);
2683 return E_NOTIMPL;
2684 }
2685
2686 HRESULT STDMETHODCALLTYPE CDefView::IsBkDropTarget(IDropTarget *drop_target)
2687 {
2688 FIXME("(%p)->(%p) stub\n", this, drop_target);
2689 return E_NOTIMPL;
2690 }
2691
2692 HRESULT STDMETHODCALLTYPE CDefView::SetClipboard(BOOL move)
2693 {
2694 FIXME("(%p)->(%d) stub\n", this, move);
2695 return E_NOTIMPL;
2696 }
2697
2698 HRESULT STDMETHODCALLTYPE CDefView::SetPoints(IDataObject *obj)
2699 {
2700 FIXME("(%p)->(%p) stub\n", this, obj);
2701 return E_NOTIMPL;
2702 }
2703
2704 HRESULT STDMETHODCALLTYPE CDefView::GetItemSpacing(ITEMSPACING *spacing)
2705 {
2706 FIXME("(%p)->(%p) stub\n", this, spacing);
2707 return E_NOTIMPL;
2708 }
2709
2710 HRESULT STDMETHODCALLTYPE CDefView::SetCallback(IShellFolderViewCB *new_cb, IShellFolderViewCB **old_cb)
2711 {
2712 FIXME("(%p)->(%p %p) stub\n", this, new_cb, old_cb);
2713 return E_NOTIMPL;
2714 }
2715
2716 HRESULT STDMETHODCALLTYPE CDefView::Select(UINT flags)
2717 {
2718 FIXME("(%p)->(%d) stub\n", this, flags);
2719 return E_NOTIMPL;
2720 }
2721
2722 HRESULT STDMETHODCALLTYPE CDefView::QuerySupport(UINT *support)
2723 {
2724 TRACE("(%p)->(%p)\n", this, support);
2725 return S_OK;
2726 }
2727
2728 HRESULT STDMETHODCALLTYPE CDefView::SetAutomationObject(IDispatch *disp)
2729 {
2730 FIXME("(%p)->(%p) stub\n", this, disp);
2731 return E_NOTIMPL;
2732 }
2733
2734 /**********************************************************
2735 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2736 */
2737 HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText)
2738 {
2739 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2740 this, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2741
2742 if (!prgCmds)
2743 return E_INVALIDARG;
2744
2745 for (UINT i = 0; i < cCmds; i++)
2746 {
2747 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2748 prgCmds[i].cmdf = 0;
2749 }
2750
2751 return OLECMDERR_E_UNKNOWNGROUP;
2752 }
2753
2754 /**********************************************************
2755 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2756 *
2757 * nCmdID is the OLECMDID_* enumeration
2758 */
2759 HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
2760 {
2761 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2762 this, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2763
2764 if (!pguidCmdGroup)
2765 return OLECMDERR_E_UNKNOWNGROUP;
2766
2767 if (IsEqualCLSID(*pguidCmdGroup, m_Category))
2768 {
2769 if (nCmdID == FCIDM_SHVIEW_AUTOARRANGE)
2770 {
2771 if (V_VT(pvaIn) != VT_INT_PTR)
2772 return OLECMDERR_E_NOTSUPPORTED;
2773
2774
2775 TPMPARAMS params;
2776 params.cbSize = sizeof(params);
2777 params.rcExclude = *(RECT*) V_INTREF(pvaIn);
2778
2779 HMENU hView = m_hView;
2780 #if 0
2781 hView = CreatePopupMenu();
2782 AppendMenuW(hView, MF_STRING, FCIDM_SHVIEW_BIGICON, L"Big!");
2783 AppendMenuW(hView, MF_STRING, FCIDM_SHVIEW_SMALLICON, L"Small!");
2784 AppendMenuW(hView, MF_STRING, FCIDM_SHVIEW_LISTVIEW, L"List!");
2785 AppendMenuW(hView, MF_STRING, FCIDM_SHVIEW_REPORTVIEW, L"Report!");
2786 #endif
2787
2788 if (hView)
2789 {
2790 PrepareShowViewMenu(hView);
2791
2792 TrackPopupMenuEx(hView, TPM_LEFTALIGN | TPM_TOPALIGN, params.rcExclude.left, params.rcExclude.bottom, m_hWndParent, &params);
2793 }
2794
2795 // pvaOut is VT_I4 with value 0x403 (cmd id of the new mode maybe?)
2796 V_VT(pvaOut) = VT_I4;
2797 V_I4(pvaOut) = 0x403;
2798 }
2799 }
2800
2801 if (IsEqualIID(*pguidCmdGroup, CGID_Explorer) &&
2802 (nCmdID == 0x29) &&
2803 (nCmdexecopt == 4) && pvaOut)
2804 return S_OK;
2805
2806 if (IsEqualIID(*pguidCmdGroup, CGID_ShellDocView) &&
2807 (nCmdID == 9) &&
2808 (nCmdexecopt == 0))
2809 return 1;
2810
2811 return OLECMDERR_E_UNKNOWNGROUP;
2812 }
2813
2814 /**********************************************************
2815 * ISVDropTarget implementation
2816 */
2817
2818 /******************************************************************************
2819 * drag_notify_subitem [Internal]
2820 *
2821 * Figure out the shellfolder object, which is currently under the mouse cursor
2822 * and notify it via the IDropTarget interface.
2823 */
2824
2825 #define SCROLLAREAWIDTH 20
2826
2827 HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2828 {
2829 LVHITTESTINFO htinfo;
2830 LONG lResult;
2831 HRESULT hr;
2832 RECT clientRect;
2833
2834 /* Map from global to client coordinates and query the index of the listview-item, which is
2835 * currently under the mouse cursor. */
2836 htinfo.pt.x = pt.x;
2837 htinfo.pt.y = pt.y;
2838 htinfo.flags = LVHT_ONITEM;
2839 ::ScreenToClient(m_ListView, &htinfo.pt);
2840 lResult = m_ListView.HitTest(&htinfo);
2841
2842 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2843 ::GetClientRect(m_ListView, &clientRect);
2844 if (htinfo.pt.x == m_ptLastMousePos.x && htinfo.pt.y == m_ptLastMousePos.y &&
2845 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2846 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2847 {
2848 m_cScrollDelay = (m_cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2849 if (m_cScrollDelay == 0)
2850 {
2851 /* Mouse did hover another 250 ms over the scroll-area */
2852 if (htinfo.pt.x < SCROLLAREAWIDTH)
2853 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEUP, 0);
2854
2855 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2856 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEDOWN, 0);
2857
2858 if (htinfo.pt.y < SCROLLAREAWIDTH)
2859 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEUP, 0);
2860
2861 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2862 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEDOWN, 0);
2863 }
2864 }
2865 else
2866 {
2867 m_cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2868 }
2869
2870 m_ptLastMousePos = htinfo.pt;
2871
2872 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2873 if (m_pCurDropTarget && lResult == m_iDragOverItem)
2874 return m_pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect);
2875
2876 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2877 if (m_pCurDropTarget)
2878 {
2879 m_pCurDropTarget->DragLeave();
2880 m_pCurDropTarget.Release();
2881 }
2882
2883 m_iDragOverItem = lResult;
2884 if (lResult == -1)
2885 {
2886 /* We are not above one of the listview's subitems. Bind to the parent folder's
2887 * DropTarget interface. */
2888 hr = m_pSFParent->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget,&m_pCurDropTarget));
2889 }
2890 else
2891 {
2892 /* Query the relative PIDL of the shellfolder object represented by the currently
2893 * dragged over listview-item ... */
2894 PCUITEMID_CHILD pidl = _PidlByItem(lResult);
2895
2896 /* ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2897 hr = m_pSFParent->GetUIObjectOf(m_ListView, 1, &pidl, IID_NULL_PPV_ARG(IDropTarget, &m_pCurDropTarget));
2898 }
2899
2900 /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */
2901 if (FAILED(hr))
2902 return hr;
2903
2904 /* Notify the item just entered via DragEnter. */
2905 return m_pCurDropTarget->DragEnter(m_pCurDataObject, grfKeyState, pt, pdwEffect);
2906 }
2907
2908 HRESULT WINAPI CDefView::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2909 {
2910 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2911 m_pCurDataObject = pDataObject;
2912 pDataObject->AddRef();
2913
2914 return drag_notify_subitem(grfKeyState, pt, pdwEffect);
2915 }
2916
2917 HRESULT WINAPI CDefView::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2918 {
2919 return drag_notify_subitem(grfKeyState, pt, pdwEffect);
2920 }
2921
2922 HRESULT WINAPI CDefView::DragLeave()
2923 {
2924 if (m_pCurDropTarget)
2925 {
2926 m_pCurDropTarget->DragLeave();
2927 m_pCurDropTarget.Release();
2928 }
2929
2930 if (m_pCurDataObject != NULL)
2931 {
2932 m_pCurDataObject.Release();
2933 }
2934
2935 m_iDragOverItem = 0;
2936
2937 return S_OK;
2938 }
2939
2940 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2941 {
2942 if (m_pCurDropTarget)
2943 {
2944 m_pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect);
2945 m_pCurDropTarget.Release();
2946 }
2947
2948 m_pCurDataObject.Release();
2949 m_iDragOverItem = 0;
2950 return S_OK;
2951 }
2952
2953 /**********************************************************
2954 * ISVDropSource implementation
2955 */
2956
2957 HRESULT WINAPI CDefView::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
2958 {
2959 TRACE("(%p)\n", this);
2960
2961 if (fEscapePressed)
2962 return DRAGDROP_S_CANCEL;
2963 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2964 return DRAGDROP_S_DROP;
2965 else
2966 return S_OK;
2967 }
2968
2969 HRESULT WINAPI CDefView::GiveFeedback(DWORD dwEffect)
2970 {
2971 TRACE("(%p)\n", this);
2972
2973 return DRAGDROP_S_USEDEFAULTCURSORS;
2974 }
2975
2976 /**********************************************************
2977 * ISVViewObject implementation
2978 */
2979
2980 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)
2981 {
2982 FIXME("Stub: this=%p\n", this);
2983
2984 return E_NOTIMPL;
2985 }
2986
2987 HRESULT WINAPI CDefView::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet)
2988 {
2989 FIXME("Stub: this=%p\n", this);
2990
2991 return E_NOTIMPL;
2992 }
2993
2994 HRESULT WINAPI CDefView::Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze)
2995 {
2996 FIXME("Stub: this=%p\n", this);
2997
2998 return E_NOTIMPL;
2999 }
3000
3001 HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze)
3002 {
3003 FIXME("Stub: this=%p\n", this);
3004
3005 return E_NOTIMPL;
3006 }
3007
3008 HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink)
3009 {
3010 FIXME("partial stub: %p %08x %08x %p\n", this, aspects, advf, pAdvSink);
3011
3012 /* FIXME: we set the AdviseSink, but never use it to send any advice */
3013 m_pAdvSink = pAdvSink;
3014 m_dwAspects = aspects;
3015 m_dwAdvf = advf;
3016
3017 return S_OK;
3018 }
3019
3020 HRESULT WINAPI CDefView::GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink)
3021 {
3022 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects, pAdvf, ppAdvSink);
3023
3024 if (ppAdvSink)
3025 {
3026 *ppAdvSink = m_pAdvSink;
3027 m_pAdvSink.p->AddRef();
3028 }
3029
3030 if (pAspects)
3031 *pAspects = m_dwAspects;
3032
3033 if (pAdvf)
3034 *pAdvf = m_dwAdvf;
3035
3036 return S_OK;
3037 }
3038
3039 HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
3040 {
3041 if (IsEqualIID(guidService, SID_IShellBrowser))
3042 return m_pShellBrowser->QueryInterface(riid, ppvObject);
3043 else if(IsEqualIID(guidService, SID_IFolderView))
3044 return QueryInterface(riid, ppvObject);
3045
3046 return E_NOINTERFACE;
3047 }
3048
3049 HRESULT CDefView::_MergeToolbar()
3050 {
3051 CComPtr<IExplorerToolbar> ptb; // [sp+8h] [bp-4h]@1
3052
3053 HRESULT hr = S_OK;
3054
3055 hr = IUnknown_QueryService(m_pShellBrowser, IID_IExplorerToolbar, IID_PPV_ARG(IExplorerToolbar, &ptb));
3056 if (FAILED(hr))
3057 return hr;
3058
3059 m_Category = CGID_DefViewFrame;
3060
3061 hr = ptb->SetCommandTarget(static_cast<IOleCommandTarget*>(this), &m_Category, 0);
3062 if (FAILED(hr))
3063 return hr;
3064
3065 if (hr == S_FALSE)
3066 return S_OK;
3067
3068 #if 0
3069 hr = ptb->AddButtons(&m_Category, buttonsCount, buttons);
3070 if (FAILED(hr))
3071 return hr;
3072 #endif
3073
3074 return S_OK;
3075 }
3076 /**********************************************************
3077 * IShellView_Constructor
3078 */
3079 HRESULT WINAPI IShellView_Constructor(IShellFolder *pFolder, IShellView **newView)
3080 {
3081 return ShellObjectCreatorInit<CDefView>(pFolder, IID_IShellView, newView);
3082 }