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