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