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