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