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