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