1 /* 2 * ShellView 3 * 4 * Copyright 1998,1999 <juergen.schmied@debitel.net> 5 * Copyright 2022 Russell Johnson <russell.johnson@superdark.net> 6 * 7 * This is the view visualizing the data provided by the shellfolder. 8 * No direct access to data from pidls should be done from here. 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public 12 * License as published by the Free Software Foundation; either 13 * version 2.1 of the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 23 * 24 * FIXME: CheckToolbar: handle the "new folder" and "folder up" button 25 */ 26 27 /* 28 TODO: 29 - Load/Save the view state from/into the stream provided by the ShellBrowser. 30 - When editing starts on item, set edit text to for editing value. 31 - Fix shell view to handle view mode popup exec. 32 - The background context menu should have a pidl just like foreground menus. This 33 causes crashes when dynamic handlers try to use the NULL pidl. 34 - Reorder of columns doesn't work - might be bug in comctl32 35 */ 36 37 #include "precomp.h" 38 39 #include <atlwin.h> 40 #include <ui/rosctrls.h> 41 42 WINE_DEFAULT_DEBUG_CHANNEL(shell); 43 44 typedef struct 45 { 46 BOOL bIsAscending; 47 INT nHeaderID; 48 INT nLastHeaderID; 49 } LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO; 50 51 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111 52 53 /* For the context menu of the def view, the id of the items are based on 1 because we need 54 to call TrackPopupMenu and let it use the 0 value as an indication that the menu was canceled */ 55 #define CONTEXT_MENU_BASE_ID 1 56 57 /* Convert client coordinates to listview coordinates */ 58 static void 59 ClientToListView(HWND hwndLV, POINT *ppt) 60 { 61 POINT Origin = {}; 62 63 /* FIXME: LVM_GETORIGIN is broken. See CORE-17266 */ 64 if (!ListView_GetOrigin(hwndLV, &Origin)) 65 return; 66 67 ppt->x += Origin.x; 68 ppt->y += Origin.y; 69 } 70 71 // Helper struct to automatically cleanup the IContextMenu 72 // We want to explicitly reset the Site, so there are no circular references 73 struct MenuCleanup 74 { 75 CComPtr<IContextMenu> &m_pCM; 76 HMENU &m_hMenu; 77 78 MenuCleanup(CComPtr<IContextMenu> &pCM, HMENU& menu) 79 : m_pCM(pCM), m_hMenu(menu) 80 { 81 } 82 ~MenuCleanup() 83 { 84 if (m_hMenu) 85 { 86 DestroyMenu(m_hMenu); 87 m_hMenu = NULL; 88 } 89 if (m_pCM) 90 { 91 IUnknown_SetSite(m_pCM, NULL); 92 m_pCM.Release(); 93 } 94 } 95 }; 96 97 98 class CDefView : 99 public CWindowImpl<CDefView, CWindow, CControlWinTraits>, 100 public CComObjectRootEx<CComMultiThreadModelNoCS>, 101 public IShellView2, 102 public IFolderView, 103 public IShellFolderView, 104 public IOleCommandTarget, 105 public IDropTarget, 106 public IDropSource, 107 public IViewObject, 108 public IServiceProvider 109 { 110 private: 111 CComPtr<IShellFolder> m_pSFParent; 112 CComPtr<IShellFolder2> m_pSF2Parent; 113 CComPtr<IShellFolderViewCB> m_pShellFolderViewCB; 114 CComPtr<IShellBrowser> m_pShellBrowser; 115 CComPtr<ICommDlgBrowser> m_pCommDlgBrowser; 116 CComPtr<IShellFolderViewDual> m_pShellFolderViewDual; 117 CListView m_ListView; 118 HWND m_hWndParent; 119 FOLDERSETTINGS m_FolderSettings; 120 HMENU m_hMenu; /* Handle to the menu bar of the browser */ 121 HMENU m_hMenuArrangeModes; /* Handle to the popup menu with the arrange modes */ 122 HMENU m_hMenuViewModes; /* Handle to the popup menu with the view modes */ 123 HMENU m_hContextMenu; /* Handle to the open context menu */ 124 BOOL m_bmenuBarInitialized; 125 UINT m_uState; 126 UINT m_cidl; 127 PCUITEMID_CHILD *m_apidl; 128 PIDLIST_ABSOLUTE m_pidlParent; 129 LISTVIEW_SORT_INFO m_sortInfo; 130 ULONG m_hNotify; /* Change notification handle */ 131 HACCEL m_hAccel; 132 DWORD m_dwAspects; 133 DWORD m_dwAdvf; 134 CComPtr<IAdviseSink> m_pAdvSink; 135 // for drag and drop 136 CComPtr<IDataObject> m_pSourceDataObject; 137 CComPtr<IDropTarget> m_pCurDropTarget; /* The sub-item, which is currently dragged over */ 138 CComPtr<IDataObject> m_pCurDataObject; /* The dragged data-object */ 139 LONG m_iDragOverItem; /* Dragged over item's index, iff m_pCurDropTarget != NULL */ 140 UINT m_cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */ 141 POINT m_ptLastMousePos; /* Mouse position at last DragOver call */ 142 POINT m_ptFirstMousePos; /* Mouse position when the drag operation started */ 143 DWORD m_grfKeyState; 144 // 145 CComPtr<IContextMenu> m_pCM; 146 CComPtr<IContextMenu> m_pFileMenu; 147 148 BOOL m_isEditing; 149 BOOL m_isParentFolderSpecial; 150 151 CLSID m_Category; 152 BOOL m_Destroyed; 153 SFVM_CUSTOMVIEWINFO_DATA m_viewinfo_data; 154 155 HICON m_hMyComputerIcon; 156 157 private: 158 HRESULT _MergeToolbar(); 159 BOOL _Sort(); 160 HRESULT _DoFolderViewCB(UINT uMsg, WPARAM wParam, LPARAM lParam); 161 HRESULT _GetSnapToGrid(); 162 void _MoveSelectionOnAutoArrange(POINT pt); 163 INT _FindInsertableIndexFromPoint(POINT pt); 164 void _HandleStatusBarResize(int width); 165 void _ForceStatusBarResize(); 166 void _DoCopyToMoveToFolder(BOOL bCopy); 167 168 public: 169 CDefView(); 170 ~CDefView(); 171 HRESULT WINAPI Initialize(IShellFolder *shellFolder); 172 HRESULT IncludeObject(PCUITEMID_CHILD pidl); 173 HRESULT OnDefaultCommand(); 174 HRESULT OnStateChange(UINT uFlags); 175 void UpdateStatusbar(); 176 void CheckToolbar(); 177 BOOL CreateList(); 178 void UpdateListColors(); 179 BOOL InitList(); 180 static INT CALLBACK ListViewCompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData); 181 182 PCUITEMID_CHILD _PidlByItem(int i); 183 PCUITEMID_CHILD _PidlByItem(LVITEM& lvItem); 184 int LV_FindItemByPidl(PCUITEMID_CHILD pidl); 185 int LV_AddItem(PCUITEMID_CHILD pidl); 186 BOOLEAN LV_DeleteItem(PCUITEMID_CHILD pidl); 187 BOOLEAN LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew); 188 BOOLEAN LV_ProdItem(PCUITEMID_CHILD pidl); 189 static INT CALLBACK fill_list(LPVOID ptr, LPVOID arg); 190 HRESULT FillList(); 191 HRESULT FillFileMenu(); 192 HRESULT FillEditMenu(); 193 HRESULT FillViewMenu(); 194 HRESULT FillArrangeAsMenu(HMENU hmenuArrange); 195 HRESULT CheckViewMode(HMENU hmenuView); 196 UINT GetSelections(); 197 HRESULT OpenSelectedItems(); 198 void OnDeactivate(); 199 void DoActivate(UINT uState); 200 HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); 201 HRESULT InvokeContextMenuCommand(CComPtr<IContextMenu>& pCM, LPCSTR lpVerb, POINT* pt = NULL); 202 LRESULT OnExplorerCommand(UINT uCommand, BOOL bUseSelection); 203 204 // *** IOleWindow methods *** 205 virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd); 206 virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); 207 208 // *** IShellView methods *** 209 virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(MSG *pmsg); 210 virtual HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable); 211 virtual HRESULT STDMETHODCALLTYPE UIActivate(UINT uState); 212 virtual HRESULT STDMETHODCALLTYPE Refresh(); 213 virtual HRESULT STDMETHODCALLTYPE CreateViewWindow(IShellView *psvPrevious, LPCFOLDERSETTINGS pfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd); 214 virtual HRESULT STDMETHODCALLTYPE DestroyViewWindow(); 215 virtual HRESULT STDMETHODCALLTYPE GetCurrentInfo(LPFOLDERSETTINGS pfs); 216 virtual HRESULT STDMETHODCALLTYPE AddPropertySheetPages(DWORD dwReserved, LPFNSVADDPROPSHEETPAGE pfn, LPARAM lparam); 217 virtual HRESULT STDMETHODCALLTYPE SaveViewState(); 218 virtual HRESULT STDMETHODCALLTYPE SelectItem(PCUITEMID_CHILD pidlItem, SVSIF uFlags); 219 virtual HRESULT STDMETHODCALLTYPE GetItemObject(UINT uItem, REFIID riid, void **ppv); 220 221 // *** IShellView2 methods *** 222 virtual HRESULT STDMETHODCALLTYPE GetView(SHELLVIEWID *view_guid, ULONG view_type); 223 virtual HRESULT STDMETHODCALLTYPE CreateViewWindow2(LPSV2CVW2_PARAMS view_params); 224 virtual HRESULT STDMETHODCALLTYPE HandleRename(LPCITEMIDLIST new_pidl); 225 virtual HRESULT STDMETHODCALLTYPE SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point); 226 227 // *** IShellView3 methods *** 228 virtual HRESULT STDMETHODCALLTYPE CreateViewWindow3(IShellBrowser *psb, IShellView *psvPrevious, SV3CVW3_FLAGS view_flags, FOLDERFLAGS mask, FOLDERFLAGS flags, FOLDERVIEWMODE mode, const SHELLVIEWID *view_id, RECT *prcView, HWND *hwnd); 229 230 // *** IFolderView methods *** 231 virtual HRESULT STDMETHODCALLTYPE GetCurrentViewMode(UINT *pViewMode); 232 virtual HRESULT STDMETHODCALLTYPE SetCurrentViewMode(UINT ViewMode); 233 virtual HRESULT STDMETHODCALLTYPE GetFolder(REFIID riid, void **ppv); 234 virtual HRESULT STDMETHODCALLTYPE Item(int iItemIndex, PITEMID_CHILD *ppidl); 235 virtual HRESULT STDMETHODCALLTYPE ItemCount(UINT uFlags, int *pcItems); 236 virtual HRESULT STDMETHODCALLTYPE Items(UINT uFlags, REFIID riid, void **ppv); 237 virtual HRESULT STDMETHODCALLTYPE GetSelectionMarkedItem(int *piItem); 238 virtual HRESULT STDMETHODCALLTYPE GetFocusedItem(int *piItem); 239 virtual HRESULT STDMETHODCALLTYPE GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt); 240 virtual HRESULT STDMETHODCALLTYPE GetSpacing(POINT *ppt); 241 virtual HRESULT STDMETHODCALLTYPE GetDefaultSpacing(POINT *ppt); 242 virtual HRESULT STDMETHODCALLTYPE GetAutoArrange(); 243 virtual HRESULT STDMETHODCALLTYPE SelectItem(int iItem, DWORD dwFlags); 244 virtual HRESULT STDMETHODCALLTYPE SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags); 245 246 // *** IShellFolderView methods *** 247 virtual HRESULT STDMETHODCALLTYPE Rearrange(LPARAM sort); 248 virtual HRESULT STDMETHODCALLTYPE GetArrangeParam(LPARAM *sort); 249 virtual HRESULT STDMETHODCALLTYPE ArrangeGrid(); 250 virtual HRESULT STDMETHODCALLTYPE AutoArrange(); 251 virtual HRESULT STDMETHODCALLTYPE AddObject(PITEMID_CHILD pidl, UINT *item); 252 virtual HRESULT STDMETHODCALLTYPE GetObject(PITEMID_CHILD *pidl, UINT item); 253 virtual HRESULT STDMETHODCALLTYPE RemoveObject(PITEMID_CHILD pidl, UINT *item); 254 virtual HRESULT STDMETHODCALLTYPE GetObjectCount(UINT *count); 255 virtual HRESULT STDMETHODCALLTYPE SetObjectCount(UINT count, UINT flags); 256 virtual HRESULT STDMETHODCALLTYPE UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item); 257 virtual HRESULT STDMETHODCALLTYPE RefreshObject(PITEMID_CHILD pidl, UINT *item); 258 virtual HRESULT STDMETHODCALLTYPE SetRedraw(BOOL redraw); 259 virtual HRESULT STDMETHODCALLTYPE GetSelectedCount(UINT *count); 260 virtual HRESULT STDMETHODCALLTYPE GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items); 261 virtual HRESULT STDMETHODCALLTYPE IsDropOnSource(IDropTarget *drop_target); 262 virtual HRESULT STDMETHODCALLTYPE GetDragPoint(POINT *pt); 263 virtual HRESULT STDMETHODCALLTYPE GetDropPoint(POINT *pt); 264 virtual HRESULT STDMETHODCALLTYPE MoveIcons(IDataObject *obj); 265 virtual HRESULT STDMETHODCALLTYPE SetItemPos(PCUITEMID_CHILD pidl, POINT *pt); 266 virtual HRESULT STDMETHODCALLTYPE IsBkDropTarget(IDropTarget *drop_target); 267 virtual HRESULT STDMETHODCALLTYPE SetClipboard(BOOL move); 268 virtual HRESULT STDMETHODCALLTYPE SetPoints(IDataObject *obj); 269 virtual HRESULT STDMETHODCALLTYPE GetItemSpacing(ITEMSPACING *spacing); 270 virtual HRESULT STDMETHODCALLTYPE SetCallback(IShellFolderViewCB *new_cb, IShellFolderViewCB **old_cb); 271 virtual HRESULT STDMETHODCALLTYPE Select(UINT flags); 272 virtual HRESULT STDMETHODCALLTYPE QuerySupport(UINT *support); 273 virtual HRESULT STDMETHODCALLTYPE SetAutomationObject(IDispatch *disp); 274 275 // *** IOleCommandTarget methods *** 276 virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText); 277 virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut); 278 279 // *** IDropTarget methods *** 280 virtual HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); 281 virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); 282 virtual HRESULT STDMETHODCALLTYPE DragLeave(); 283 virtual HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); 284 285 // *** IDropSource methods *** 286 virtual HRESULT STDMETHODCALLTYPE QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState); 287 virtual HRESULT STDMETHODCALLTYPE GiveFeedback(DWORD dwEffect); 288 289 // *** IViewObject methods *** 290 virtual HRESULT STDMETHODCALLTYPE Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, 291 HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds, 292 BOOL ( STDMETHODCALLTYPE *pfnContinue )(ULONG_PTR dwContinue), ULONG_PTR dwContinue); 293 virtual HRESULT STDMETHODCALLTYPE GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, 294 DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE **ppColorSet); 295 virtual HRESULT STDMETHODCALLTYPE Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze); 296 virtual HRESULT STDMETHODCALLTYPE Unfreeze(DWORD dwFreeze); 297 virtual HRESULT STDMETHODCALLTYPE SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink); 298 virtual HRESULT STDMETHODCALLTYPE GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink); 299 300 // *** IServiceProvider methods *** 301 virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject); 302 303 // Message handlers 304 LRESULT OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 305 LRESULT OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 306 LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 307 LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 308 LRESULT OnPrintClient(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 309 LRESULT OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 310 LRESULT OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 311 LRESULT OnNCCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 312 LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 313 LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 314 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 315 LRESULT OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 316 LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 317 LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 318 LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 319 LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 320 LRESULT OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 321 LRESULT OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 322 LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 323 LRESULT OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 324 325 virtual VOID OnFinalMessage(HWND) override; 326 327 static ATL::CWndClassInfo& GetWndClassInfo() 328 { 329 static ATL::CWndClassInfo wc = 330 { 331 { sizeof(WNDCLASSEX), CS_PARENTDC, StartWindowProc, 332 0, 0, NULL, NULL, 333 LoadCursor(NULL, IDC_ARROW), NULL, NULL, L"SHELLDLL_DefView", NULL 334 }, 335 NULL, NULL, IDC_ARROW, TRUE, 0, _T("") 336 }; 337 return wc; 338 } 339 340 virtual WNDPROC GetWindowProc() 341 { 342 return WindowProc; 343 } 344 345 static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 346 { 347 CDefView *pThis; 348 LRESULT result; 349 350 // Must hold a reference during message handling 351 pThis = reinterpret_cast<CDefView *>(hWnd); 352 pThis->AddRef(); 353 result = CWindowImpl<CDefView, CWindow, CControlWinTraits>::WindowProc(hWnd, uMsg, wParam, lParam); 354 pThis->Release(); 355 return result; 356 } 357 358 BEGIN_MSG_MAP(CDefView) 359 MESSAGE_HANDLER(WM_SIZE, OnSize) 360 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) 361 MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus) 362 MESSAGE_HANDLER(WM_NCCREATE, OnNCCreate) 363 MESSAGE_HANDLER(WM_CREATE, OnCreate) 364 MESSAGE_HANDLER(WM_ACTIVATE, OnActivate) 365 MESSAGE_HANDLER(WM_NOTIFY, OnNotify) 366 MESSAGE_HANDLER(WM_COMMAND, OnCommand) 367 MESSAGE_HANDLER(SHV_CHANGE_NOTIFY, OnChangeNotify) 368 MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu) 369 MESSAGE_HANDLER(WM_DRAWITEM, OnCustomItem) 370 MESSAGE_HANDLER(WM_MEASUREITEM, OnCustomItem) 371 MESSAGE_HANDLER(WM_SHOWWINDOW, OnShowWindow) 372 MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode) 373 MESSAGE_HANDLER(WM_DESTROY, OnDestroy) 374 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) 375 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPrintClient) 376 MESSAGE_HANDLER(WM_SYSCOLORCHANGE, OnSysColorChange) 377 MESSAGE_HANDLER(CWM_GETISHELLBROWSER, OnGetShellBrowser) 378 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) 379 MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup) 380 END_MSG_MAP() 381 382 BEGIN_COM_MAP(CDefView) 383 // Windows returns E_NOINTERFACE for IOleWindow 384 // COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow) 385 COM_INTERFACE_ENTRY_IID(IID_IShellView, IShellView) 386 COM_INTERFACE_ENTRY_IID(IID_CDefView, IShellView) 387 COM_INTERFACE_ENTRY_IID(IID_IShellView2, IShellView2) 388 COM_INTERFACE_ENTRY_IID(IID_IFolderView, IFolderView) 389 COM_INTERFACE_ENTRY_IID(IID_IShellFolderView, IShellFolderView) 390 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) 391 COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget) 392 COM_INTERFACE_ENTRY_IID(IID_IDropSource, IDropSource) 393 COM_INTERFACE_ENTRY_IID(IID_IViewObject, IViewObject) 394 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider) 395 END_COM_MAP() 396 }; 397 398 /*menu items */ 399 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500) 400 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501) 401 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502) 402 403 #define ID_LISTVIEW 1 404 405 /*windowsx.h */ 406 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp) 407 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp) 408 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp) 409 410 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask); 411 412 CDefView::CDefView() : 413 m_ListView(), 414 m_hWndParent(NULL), 415 m_hMenu(NULL), 416 m_hMenuArrangeModes(NULL), 417 m_hMenuViewModes(NULL), 418 m_hContextMenu(NULL), 419 m_bmenuBarInitialized(FALSE), 420 m_uState(0), 421 m_cidl(0), 422 m_apidl(NULL), 423 m_pidlParent(NULL), 424 m_hNotify(0), 425 m_hAccel(NULL), 426 m_dwAspects(0), 427 m_dwAdvf(0), 428 m_iDragOverItem(0), 429 m_cScrollDelay(0), 430 m_isEditing(FALSE), 431 m_isParentFolderSpecial(FALSE), 432 m_Destroyed(FALSE) 433 { 434 ZeroMemory(&m_FolderSettings, sizeof(m_FolderSettings)); 435 ZeroMemory(&m_sortInfo, sizeof(m_sortInfo)); 436 ZeroMemory(&m_ptLastMousePos, sizeof(m_ptLastMousePos)); 437 ZeroMemory(&m_Category, sizeof(m_Category)); 438 m_viewinfo_data.clrText = GetSysColor(COLOR_WINDOWTEXT); 439 m_viewinfo_data.clrTextBack = GetSysColor(COLOR_WINDOW); 440 m_viewinfo_data.hbmBack = NULL; 441 442 m_hMyComputerIcon = LoadIconW(shell32_hInstance, MAKEINTRESOURCEW(IDI_SHELL_COMPUTER_DESKTOP)); 443 } 444 445 CDefView::~CDefView() 446 { 447 TRACE(" destroying IShellView(%p)\n", this); 448 449 _DoFolderViewCB(SFVM_VIEWRELEASE, 0, 0); 450 451 if (m_viewinfo_data.hbmBack) 452 { 453 ::DeleteObject(m_viewinfo_data.hbmBack); 454 m_viewinfo_data.hbmBack = NULL; 455 } 456 457 if (m_hWnd) 458 { 459 DestroyViewWindow(); 460 } 461 462 SHFree(m_apidl); 463 } 464 465 HRESULT WINAPI CDefView::Initialize(IShellFolder *shellFolder) 466 { 467 m_pSFParent = shellFolder; 468 shellFolder->QueryInterface(IID_PPV_ARG(IShellFolder2, &m_pSF2Parent)); 469 470 return S_OK; 471 } 472 473 /********************************************************** 474 * 475 * ##### helperfunctions for communication with ICommDlgBrowser ##### 476 */ 477 HRESULT CDefView::IncludeObject(PCUITEMID_CHILD pidl) 478 { 479 HRESULT ret = S_OK; 480 481 if (m_pCommDlgBrowser.p != NULL) 482 { 483 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl); 484 ret = m_pCommDlgBrowser->IncludeObject(this, pidl); 485 TRACE("-- returns 0x%08x\n", ret); 486 } 487 488 return ret; 489 } 490 491 HRESULT CDefView::OnDefaultCommand() 492 { 493 HRESULT ret = S_FALSE; 494 495 if (m_pCommDlgBrowser.p != NULL) 496 { 497 TRACE("ICommDlgBrowser::OnDefaultCommand\n"); 498 ret = m_pCommDlgBrowser->OnDefaultCommand(this); 499 TRACE("-- returns 0x%08x\n", ret); 500 } 501 502 return ret; 503 } 504 505 HRESULT CDefView::OnStateChange(UINT uFlags) 506 { 507 HRESULT ret = S_FALSE; 508 509 if (m_pCommDlgBrowser.p != NULL) 510 { 511 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags); 512 ret = m_pCommDlgBrowser->OnStateChange(this, uFlags); 513 TRACE("--\n"); 514 } 515 516 return ret; 517 } 518 /********************************************************** 519 * set the toolbar of the filedialog buttons 520 * 521 * - activates the buttons from the shellbrowser according to 522 * the view state 523 */ 524 void CDefView::CheckToolbar() 525 { 526 LRESULT result; 527 528 TRACE("\n"); 529 530 if (m_pCommDlgBrowser != NULL) 531 { 532 m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_CHECKBUTTON, 533 FCIDM_TB_SMALLICON, (m_FolderSettings.ViewMode == FVM_LIST) ? TRUE : FALSE, &result); 534 m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_CHECKBUTTON, 535 FCIDM_TB_REPORTVIEW, (m_FolderSettings.ViewMode == FVM_DETAILS) ? TRUE : FALSE, &result); 536 m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON, 537 FCIDM_TB_SMALLICON, TRUE, &result); 538 m_pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON, 539 FCIDM_TB_REPORTVIEW, TRUE, &result); 540 } 541 } 542 543 void CDefView::UpdateStatusbar() 544 { 545 WCHAR szFormat[MAX_PATH] = {0}; 546 WCHAR szPartText[MAX_PATH] = {0}; 547 UINT cSelectedItems; 548 549 if (!m_ListView) 550 return; 551 552 cSelectedItems = m_ListView.GetSelectedCount(); 553 if (cSelectedItems) 554 { 555 LoadStringW(shell32_hInstance, IDS_OBJECTS_SELECTED, szFormat, _countof(szFormat)); 556 StringCchPrintfW(szPartText, _countof(szPartText), szFormat, cSelectedItems); 557 } 558 else 559 { 560 LoadStringW(shell32_hInstance, IDS_OBJECTS, szFormat, _countof(szFormat)); 561 StringCchPrintfW(szPartText, _countof(szPartText), szFormat, m_ListView.GetItemCount()); 562 } 563 564 LRESULT lResult; 565 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 0, (LPARAM)szPartText, &lResult); 566 567 /* Don't bother with the extra processing if we only have one StatusBar part. */ 568 if (!m_isParentFolderSpecial) 569 { 570 DWORD uTotalFileSize = 0; 571 WORD uFileFlags = LVNI_ALL; 572 LPARAM pIcon = NULL; 573 INT nItem = -1; 574 bool bIsOnlyFoldersSelected = true; 575 576 /* If we have something selected then only count selected file sizes. */ 577 if (cSelectedItems) 578 { 579 uFileFlags = LVNI_SELECTED; 580 } 581 582 while ((nItem = m_ListView.GetNextItem(nItem, uFileFlags)) >= 0) 583 { 584 PCUITEMID_CHILD pidl = _PidlByItem(nItem); 585 586 uTotalFileSize += _ILGetFileSize(pidl, NULL, 0); 587 588 if (!_ILIsFolder(pidl)) 589 { 590 bIsOnlyFoldersSelected = false; 591 } 592 } 593 594 /* Don't show the file size text if there is 0 bytes in the folder 595 * OR we only have folders selected. */ 596 if ((cSelectedItems && !bIsOnlyFoldersSelected) || uTotalFileSize) 597 { 598 StrFormatByteSizeW(uTotalFileSize, szPartText, _countof(szPartText)); 599 } 600 else 601 { 602 *szPartText = 0; 603 } 604 605 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 1, (LPARAM)szPartText, &lResult); 606 607 /* If we are in a Recycle Bin folder then show no text for the location part. */ 608 if (!_ILIsBitBucket(m_pidlParent)) 609 { 610 LoadStringW(shell32_hInstance, IDS_MYCOMPUTER, szPartText, _countof(szPartText)); 611 pIcon = (LPARAM)m_hMyComputerIcon; 612 } 613 614 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETICON, 2, pIcon, &lResult); 615 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXT, 2, (LPARAM)szPartText, &lResult); 616 } 617 } 618 619 /********************************************************** 620 * 621 * ##### helperfunctions for initializing the view ##### 622 */ 623 624 /********************************************************** 625 * ShellView_CreateList() 626 * 627 * - creates the list view window 628 */ 629 BOOL CDefView::CreateList() 630 { 631 HRESULT hr; 632 DWORD dwStyle, dwExStyle, ListExStyle; 633 UINT ViewMode; 634 635 TRACE("%p\n", this); 636 637 dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 638 LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_AUTOARRANGE; // FIXME: Why is LVS_AUTOARRANGE here? 639 dwExStyle = WS_EX_CLIENTEDGE; 640 ListExStyle = 0; 641 642 if (m_FolderSettings.fFlags & FWF_DESKTOP) 643 { 644 m_FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL; 645 dwStyle |= LVS_ALIGNLEFT; 646 } 647 else 648 { 649 dwStyle |= LVS_SHOWSELALWAYS; // MSDN says FWF_SHOWSELALWAYS is deprecated, always turn on for folders. 650 dwStyle |= (m_FolderSettings.fFlags & FWF_ALIGNLEFT) ? LVS_ALIGNLEFT : LVS_ALIGNTOP; 651 ListExStyle = LVS_EX_DOUBLEBUFFER; 652 } 653 654 ViewMode = m_FolderSettings.ViewMode; 655 hr = _DoFolderViewCB(SFVM_DEFVIEWMODE, 0, (LPARAM)&ViewMode); 656 if (SUCCEEDED(hr)) 657 { 658 if (ViewMode >= FVM_FIRST && ViewMode <= FVM_LAST) 659 m_FolderSettings.ViewMode = ViewMode; 660 else 661 ERR("Ignoring invalid ViewMode from SFVM_DEFVIEWMODE: %u (was: %u)\n", ViewMode, m_FolderSettings.ViewMode); 662 } 663 664 switch (m_FolderSettings.ViewMode) 665 { 666 case FVM_ICON: 667 dwStyle |= LVS_ICON; 668 break; 669 670 case FVM_DETAILS: 671 dwStyle |= LVS_REPORT; 672 break; 673 674 case FVM_SMALLICON: 675 dwStyle |= LVS_SMALLICON; 676 break; 677 678 case FVM_LIST: 679 dwStyle |= LVS_LIST; 680 break; 681 682 default: 683 dwStyle |= LVS_LIST; 684 break; 685 } 686 687 if (m_FolderSettings.fFlags & FWF_AUTOARRANGE) 688 dwStyle |= LVS_AUTOARRANGE; 689 690 if (m_FolderSettings.fFlags & FWF_SNAPTOGRID) 691 ListExStyle |= LVS_EX_SNAPTOGRID; 692 693 if (m_FolderSettings.fFlags & FWF_SINGLESEL) 694 dwStyle |= LVS_SINGLESEL; 695 696 if (m_FolderSettings.fFlags & FWF_FULLROWSELECT) 697 ListExStyle |= LVS_EX_FULLROWSELECT; 698 699 if (m_FolderSettings.fFlags & FWF_SINGLECLICKACTIVATE) 700 ListExStyle |= LVS_EX_TRACKSELECT | LVS_EX_ONECLICKACTIVATE; 701 702 if (m_FolderSettings.fFlags & FWF_NOCOLUMNHEADER) 703 dwStyle |= LVS_NOCOLUMNHEADER; 704 705 #if 0 706 // FIXME: Because this is a negative, everyone gets the new flag by default unless they 707 // opt out. This code should be enabled when the shell looks like Vista instead of 2003. 708 if (!(m_FolderSettings.fFlags & FWF_NOHEADERINALLVIEWS)) 709 ListExStyle |= LVS_EX_HEADERINALLVIEWS; 710 #endif 711 712 if (m_FolderSettings.fFlags & FWF_NOCLIENTEDGE) 713 dwExStyle &= ~WS_EX_CLIENTEDGE; 714 715 RECT rcListView = {0,0,0,0}; 716 m_ListView.Create(m_hWnd, rcListView, L"FolderView", dwStyle, dwExStyle, ID_LISTVIEW); 717 718 if (!m_ListView) 719 return FALSE; 720 721 m_ListView.SetExtendedListViewStyle(ListExStyle); 722 723 m_sortInfo.bIsAscending = TRUE; 724 m_sortInfo.nHeaderID = -1; 725 m_sortInfo.nLastHeaderID = -1; 726 727 /* UpdateShellSettings(); */ 728 return TRUE; 729 } 730 731 void CDefView::UpdateListColors() 732 { 733 if (m_FolderSettings.fFlags & FWF_DESKTOP) 734 { 735 /* Check if drop shadows option is enabled */ 736 BOOL bDropShadow = FALSE; 737 DWORD cbDropShadow = sizeof(bDropShadow); 738 739 /* 740 * The desktop ListView always take the default desktop colours, by 741 * remaining transparent and letting user32/win32k paint itself the 742 * desktop background color, if any. 743 */ 744 m_ListView.SetBkColor(CLR_NONE); 745 746 SHGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", 747 L"ListviewShadow", NULL, &bDropShadow, &cbDropShadow); 748 if (bDropShadow) 749 { 750 /* Set the icon background transparent */ 751 m_ListView.SetTextBkColor(CLR_NONE); 752 m_ListView.SetTextColor(RGB(255, 255, 255)); 753 m_ListView.SetExtendedListViewStyle(LVS_EX_TRANSPARENTSHADOWTEXT, LVS_EX_TRANSPARENTSHADOWTEXT); 754 } 755 else 756 { 757 /* Set the icon background as the same colour as the desktop */ 758 COLORREF crDesktop = GetSysColor(COLOR_DESKTOP); 759 m_ListView.SetTextBkColor(crDesktop); 760 if (GetRValue(crDesktop) + GetGValue(crDesktop) + GetBValue(crDesktop) > 128 * 3) 761 m_ListView.SetTextColor(RGB(0, 0, 0)); 762 else 763 m_ListView.SetTextColor(RGB(255, 255, 255)); 764 m_ListView.SetExtendedListViewStyle(0, LVS_EX_TRANSPARENTSHADOWTEXT); 765 } 766 } 767 else 768 { 769 // text background color 770 COLORREF clrTextBack = m_viewinfo_data.clrTextBack; 771 m_ListView.SetTextBkColor(clrTextBack); 772 773 // text color 774 COLORREF clrText; 775 if (m_viewinfo_data.clrText != CLR_INVALID) 776 clrText = m_viewinfo_data.clrText; 777 else 778 clrText = GetSysColor(COLOR_WINDOWTEXT); 779 780 m_ListView.SetTextColor(clrText); 781 782 // Background is painted by the parent via WM_PRINTCLIENT. 783 m_ListView.SetExtendedListViewStyle(LVS_EX_TRANSPARENTBKGND, LVS_EX_TRANSPARENTBKGND); 784 } 785 } 786 787 /********************************************************** 788 * ShellView_InitList() 789 * 790 * - adds all needed columns to the shellview 791 */ 792 BOOL CDefView::InitList() 793 { 794 SHELLDETAILS sd; 795 WCHAR szTemp[50]; 796 HIMAGELIST big_icons, small_icons; 797 798 TRACE("%p\n", this); 799 800 m_ListView.DeleteAllItems(); 801 802 m_hMenuArrangeModes = CreateMenu(); 803 804 if (m_pSF2Parent) 805 { 806 for (int i = 0; 1; i++) 807 { 808 if (FAILED(m_pSF2Parent->GetDetailsOf(NULL, i, &sd))) 809 break; 810 StrRetToStrNW( szTemp, 50, &sd.str, NULL); 811 m_ListView.InsertColumn(i, szTemp, sd.fmt, sd.cxChar * 8); 812 813 InsertMenuW(m_hMenuArrangeModes, -1, MF_STRING, 0x30 + i, szTemp); 814 } 815 816 InsertMenuW(m_hMenuArrangeModes, -1, MF_BYPOSITION | MF_SEPARATOR, 0, 0); 817 } 818 else 819 { 820 FIXME("no m_pSF2Parent\n"); 821 } 822 823 Shell_GetImageLists(&big_icons, &small_icons); 824 m_ListView.SetImageList(big_icons, LVSIL_NORMAL); 825 m_ListView.SetImageList(small_icons, LVSIL_SMALL); 826 827 return TRUE; 828 } 829 830 /************************************************************************* 831 * ShellView_ListViewCompareItems 832 * 833 * Compare Function for the Listview (FileOpen Dialog) 834 * 835 * PARAMS 836 * lParam1 [I] the first ItemIdList to compare with 837 * lParam2 [I] the second ItemIdList to compare with 838 * lpData [I] The column ID for the header Ctrl to process 839 * 840 * RETURNS 841 * A negative value if the first item should precede the second, 842 * a positive value if the first item should follow the second, 843 * or zero if the two items are equivalent 844 */ 845 INT CALLBACK CDefView::ListViewCompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData) 846 { 847 PCUIDLIST_RELATIVE pidl1 = reinterpret_cast<PCUIDLIST_RELATIVE>(lParam1); 848 PCUIDLIST_RELATIVE pidl2 = reinterpret_cast<PCUIDLIST_RELATIVE>(lParam2); 849 CDefView *pThis = reinterpret_cast<CDefView*>(lpData); 850 851 HRESULT hres = pThis->m_pSFParent->CompareIDs(pThis->m_sortInfo.nHeaderID, pidl1, pidl2); 852 if (FAILED_UNEXPECTEDLY(hres)) 853 return 0; 854 855 SHORT nDiff = HRESULT_CODE(hres); 856 if (!pThis->m_sortInfo.bIsAscending) 857 nDiff = -nDiff; 858 return nDiff; 859 } 860 861 BOOL CDefView::_Sort() 862 { 863 HWND hHeader; 864 HDITEM hColumn; 865 866 if (m_ListView.GetWindowLongPtr(GWL_STYLE) & LVS_NOSORTHEADER) 867 return TRUE; 868 869 hHeader = (HWND)m_ListView.SendMessage(LVM_GETHEADER, 0, 0); 870 ZeroMemory(&hColumn, sizeof(hColumn)); 871 872 /* If the sorting column changed, remove the sorting style from the old column */ 873 if ( (m_sortInfo.nLastHeaderID != -1) && 874 (m_sortInfo.nLastHeaderID != m_sortInfo.nHeaderID) ) 875 { 876 hColumn.mask = HDI_FORMAT; 877 Header_GetItem(hHeader, m_sortInfo.nLastHeaderID, &hColumn); 878 hColumn.fmt &= ~(HDF_SORTUP | HDF_SORTDOWN); 879 Header_SetItem(hHeader, m_sortInfo.nLastHeaderID, &hColumn); 880 } 881 882 /* Set the sorting style to the new column */ 883 hColumn.mask = HDI_FORMAT; 884 Header_GetItem(hHeader, m_sortInfo.nHeaderID, &hColumn); 885 886 hColumn.fmt &= (m_sortInfo.bIsAscending ? ~HDF_SORTDOWN : ~HDF_SORTUP ); 887 hColumn.fmt |= (m_sortInfo.bIsAscending ? HDF_SORTUP : HDF_SORTDOWN); 888 Header_SetItem(hHeader, m_sortInfo.nHeaderID, &hColumn); 889 890 /* Sort the list, using the current values of nHeaderID and bIsAscending */ 891 m_sortInfo.nLastHeaderID = m_sortInfo.nHeaderID; 892 return m_ListView.SortItems(ListViewCompareItems, this); 893 } 894 895 PCUITEMID_CHILD CDefView::_PidlByItem(int i) 896 { 897 if (!m_ListView) 898 return nullptr; 899 return reinterpret_cast<PCUITEMID_CHILD>(m_ListView.GetItemData(i)); 900 } 901 902 PCUITEMID_CHILD CDefView::_PidlByItem(LVITEM& lvItem) 903 { 904 if (!m_ListView) 905 return nullptr; 906 return reinterpret_cast<PCUITEMID_CHILD>(lvItem.lParam); 907 } 908 909 /********************************************************** 910 * LV_FindItemByPidl() 911 */ 912 int CDefView::LV_FindItemByPidl(PCUITEMID_CHILD pidl) 913 { 914 ASSERT(m_ListView); 915 916 int cItems = m_ListView.GetItemCount(); 917 918 for (int i = 0; i<cItems; i++) 919 { 920 PCUITEMID_CHILD currentpidl = _PidlByItem(i); 921 if (ILIsEqual(pidl, currentpidl)) 922 return i; 923 } 924 return -1; 925 } 926 927 /********************************************************** 928 * LV_AddItem() 929 */ 930 int CDefView::LV_AddItem(PCUITEMID_CHILD pidl) 931 { 932 LVITEMW lvItem; 933 934 TRACE("(%p)(pidl=%p)\n", this, pidl); 935 936 ASSERT(m_ListView); 937 938 if (_DoFolderViewCB(SFVM_ADDINGOBJECT, 0, (LPARAM)pidl) == S_FALSE) 939 return -1; 940 941 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/ 942 lvItem.iItem = m_ListView.GetItemCount(); /*add the item to the end of the list*/ 943 lvItem.iSubItem = 0; 944 lvItem.lParam = reinterpret_cast<LPARAM>(ILClone(pidl)); /*set the item's data*/ 945 lvItem.pszText = LPSTR_TEXTCALLBACKW; /*get text on a callback basis*/ 946 lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/ 947 lvItem.stateMask = LVIS_CUT; 948 949 return m_ListView.InsertItem(&lvItem); 950 } 951 952 /********************************************************** 953 * LV_DeleteItem() 954 */ 955 BOOLEAN CDefView::LV_DeleteItem(PCUITEMID_CHILD pidl) 956 { 957 int nIndex; 958 959 TRACE("(%p)(pidl=%p)\n", this, pidl); 960 961 ASSERT(m_ListView); 962 963 nIndex = LV_FindItemByPidl(pidl); 964 if (nIndex < 0) 965 return FALSE; 966 967 return m_ListView.DeleteItem(nIndex); 968 } 969 970 /********************************************************** 971 * LV_RenameItem() 972 */ 973 BOOLEAN CDefView::LV_RenameItem(PCUITEMID_CHILD pidlOld, PCUITEMID_CHILD pidlNew) 974 { 975 int nItem; 976 LVITEMW lvItem; 977 978 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", this, pidlOld, pidlNew); 979 980 ASSERT(m_ListView); 981 982 nItem = LV_FindItemByPidl(pidlOld); 983 984 if ( -1 != nItem ) 985 { 986 lvItem.mask = LVIF_PARAM; /* only the pidl */ 987 lvItem.iItem = nItem; 988 lvItem.iSubItem = 0; 989 m_ListView.GetItem(&lvItem); 990 991 LPVOID oldPidl = reinterpret_cast<LPVOID>(lvItem.lParam); /* Store the old pidl until the new item is replaced */ 992 993 lvItem.mask = LVIF_PARAM | LVIF_IMAGE | LVIF_TEXT; 994 lvItem.iItem = nItem; 995 lvItem.iSubItem = 0; 996 lvItem.lParam = reinterpret_cast<LPARAM>(ILClone(pidlNew)); /* set the item's data */ 997 lvItem.pszText = LPSTR_TEXTCALLBACKW; 998 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0); 999 m_ListView.SetItem(&lvItem); 1000 m_ListView.Update(nItem); 1001 1002 SHFree(oldPidl); /* Now that the new item is in place, we can safely release the old pidl */ 1003 1004 return TRUE; /* FIXME: better handling */ 1005 } 1006 1007 return FALSE; 1008 } 1009 1010 /********************************************************** 1011 * LV_ProdItem() 1012 */ 1013 BOOLEAN CDefView::LV_ProdItem(PCUITEMID_CHILD pidl) 1014 { 1015 int nItem; 1016 LVITEMW lvItem; 1017 1018 TRACE("(%p)(pidl=%p)\n", this, pidl); 1019 1020 ASSERT(m_ListView); 1021 1022 nItem = LV_FindItemByPidl(pidl); 1023 1024 if (-1 != nItem) 1025 { 1026 lvItem.mask = LVIF_IMAGE; 1027 lvItem.iItem = nItem; 1028 lvItem.iSubItem = 0; 1029 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0); 1030 m_ListView.SetItem(&lvItem); 1031 m_ListView.Update(nItem); 1032 return TRUE; 1033 } 1034 1035 return FALSE; 1036 } 1037 1038 /********************************************************** 1039 * ShellView_FillList() 1040 * 1041 * - gets the objectlist from the shellfolder 1042 * - sorts the list 1043 * - fills the list into the view 1044 */ 1045 INT CALLBACK CDefView::fill_list(LPVOID ptr, LPVOID arg) 1046 { 1047 PITEMID_CHILD pidl = static_cast<PITEMID_CHILD>(ptr); 1048 CDefView *pThis = static_cast<CDefView *>(arg); 1049 1050 /* in a commdlg This works as a filemask*/ 1051 if (pThis->IncludeObject(pidl) == S_OK && pThis->m_ListView) 1052 pThis->LV_AddItem(pidl); 1053 1054 SHFree(pidl); 1055 return TRUE; 1056 } 1057 1058 HRESULT CDefView::FillList() 1059 { 1060 CComPtr<IEnumIDList> pEnumIDList; 1061 PITEMID_CHILD pidl; 1062 DWORD dwFetched; 1063 HRESULT hRes; 1064 HDPA hdpa; 1065 DWORD dFlags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS; 1066 DWORD dwValue, cbValue; 1067 1068 TRACE("%p\n", this); 1069 1070 /* determine if there is a setting to show all the hidden files/folders */ 1071 dwValue = 1; 1072 cbValue = sizeof(dwValue); 1073 SHGetValueW(HKEY_CURRENT_USER, 1074 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", 1075 L"Hidden", NULL, &dwValue, &cbValue); 1076 if (dwValue == 1) 1077 { 1078 dFlags |= SHCONTF_INCLUDEHIDDEN; 1079 m_ListView.SendMessageW(LVM_SETCALLBACKMASK, LVIS_CUT, 0); 1080 } 1081 1082 dwValue = 0; 1083 cbValue = sizeof(dwValue); 1084 SHGetValueW(HKEY_CURRENT_USER, 1085 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", 1086 L"ShowSuperHidden", NULL, &dwValue, &cbValue); 1087 if (dwValue) 1088 { 1089 dFlags |= SHCONTF_INCLUDESUPERHIDDEN; 1090 m_ListView.SendMessageW(LVM_SETCALLBACKMASK, LVIS_CUT, 0); 1091 } 1092 1093 /* get the itemlist from the shfolder */ 1094 hRes = m_pSFParent->EnumObjects(m_hWnd, dFlags, &pEnumIDList); 1095 if (hRes != S_OK) 1096 { 1097 if (hRes == S_FALSE) 1098 return(NOERROR); 1099 return(hRes); 1100 } 1101 1102 /* create a pointer array */ 1103 hdpa = DPA_Create(16); 1104 if (!hdpa) 1105 { 1106 return(E_OUTOFMEMORY); 1107 } 1108 1109 /* copy the items into the array*/ 1110 while((S_OK == pEnumIDList->Next(1, &pidl, &dwFetched)) && dwFetched) 1111 { 1112 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1) 1113 { 1114 SHFree(pidl); 1115 } 1116 } 1117 1118 /*turn the listview's redrawing off*/ 1119 m_ListView.SetRedraw(FALSE); 1120 1121 DPA_DestroyCallback( hdpa, fill_list, this); 1122 1123 /* sort the array */ 1124 if (m_pSF2Parent) 1125 { 1126 m_pSF2Parent->GetDefaultColumn(NULL, (ULONG*)&m_sortInfo.nHeaderID, NULL); 1127 } 1128 else 1129 { 1130 FIXME("no m_pSF2Parent\n"); 1131 } 1132 m_sortInfo.bIsAscending = TRUE; 1133 _Sort(); 1134 1135 if (m_viewinfo_data.hbmBack) 1136 { 1137 ::DeleteObject(m_viewinfo_data.hbmBack); 1138 m_viewinfo_data.hbmBack = NULL; 1139 } 1140 1141 // load custom background image and custom text color 1142 m_viewinfo_data.cbSize = sizeof(m_viewinfo_data); 1143 _DoFolderViewCB(SFVM_GET_CUSTOMVIEWINFO, 0, (LPARAM)&m_viewinfo_data); 1144 1145 /*turn the listview's redrawing back on and force it to draw*/ 1146 m_ListView.SetRedraw(TRUE); 1147 1148 UpdateListColors(); 1149 1150 if (!(m_FolderSettings.fFlags & FWF_DESKTOP)) 1151 { 1152 // redraw now 1153 m_ListView.InvalidateRect(NULL, TRUE); 1154 } 1155 1156 _DoFolderViewCB(SFVM_LISTREFRESHED, 0, 0); 1157 1158 return S_OK; 1159 } 1160 1161 LRESULT CDefView::OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1162 { 1163 if (m_ListView.IsWindow()) 1164 m_ListView.UpdateWindow(); 1165 bHandled = FALSE; 1166 return 0; 1167 } 1168 1169 LRESULT CDefView::OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1170 { 1171 return m_ListView.SendMessageW(uMsg, 0, 0); 1172 } 1173 1174 LRESULT CDefView::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1175 { 1176 if (!m_Destroyed) 1177 { 1178 m_Destroyed = TRUE; 1179 if (m_hMenu) 1180 { 1181 DestroyMenu(m_hMenu); 1182 m_hMenu = NULL; 1183 } 1184 RevokeDragDrop(m_hWnd); 1185 SHChangeNotifyDeregister(m_hNotify); 1186 m_hNotify = NULL; 1187 SHFree(m_pidlParent); 1188 m_pidlParent = NULL; 1189 } 1190 bHandled = FALSE; 1191 return 0; 1192 } 1193 1194 LRESULT CDefView::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1195 { 1196 /* redirect to parent */ 1197 if (m_FolderSettings.fFlags & (FWF_DESKTOP | FWF_TRANSPARENT)) 1198 return SendMessageW(GetParent(), WM_ERASEBKGND, wParam, lParam); 1199 1200 bHandled = FALSE; 1201 return 0; 1202 } 1203 1204 static VOID 1205 DrawTileBitmap(HDC hDC, LPCRECT prc, HBITMAP hbm, INT nWidth, INT nHeight, INT dx, INT dy) 1206 { 1207 INT x0 = prc->left, y0 = prc->top, x1 = prc->right, y1 = prc->bottom; 1208 x0 += dx; 1209 y0 += dy; 1210 1211 HDC hMemDC = CreateCompatibleDC(hDC); 1212 HGDIOBJ hbmOld = SelectObject(hMemDC, hbm); 1213 1214 for (INT y = y0; y < y1; y += nHeight) 1215 { 1216 for (INT x = x0; x < x1; x += nWidth) 1217 { 1218 BitBlt(hDC, x, y, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY); 1219 } 1220 } 1221 1222 SelectObject(hMemDC, hbmOld); 1223 DeleteDC(hMemDC); 1224 } 1225 1226 LRESULT CDefView::OnPrintClient(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1227 { 1228 HDC hDC = (HDC)wParam; 1229 1230 RECT rc; 1231 ::GetClientRect(m_ListView, &rc); 1232 1233 if (m_viewinfo_data.hbmBack) 1234 { 1235 BITMAP bm; 1236 if (::GetObject(m_viewinfo_data.hbmBack, sizeof(BITMAP), &bm)) 1237 { 1238 INT dx = -(::GetScrollPos(m_ListView, SB_HORZ) % bm.bmWidth); 1239 INT dy = -(::GetScrollPos(m_ListView, SB_VERT) % bm.bmHeight); 1240 DrawTileBitmap(hDC, &rc, m_viewinfo_data.hbmBack, bm.bmWidth, bm.bmHeight, dx, dy); 1241 } 1242 } 1243 else 1244 { 1245 FillRect(hDC, &rc, GetSysColorBrush(COLOR_WINDOW)); 1246 } 1247 1248 bHandled = TRUE; 1249 1250 return TRUE; 1251 } 1252 1253 LRESULT CDefView::OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1254 { 1255 /* Update desktop labels color */ 1256 UpdateListColors(); 1257 1258 /* Forward WM_SYSCOLORCHANGE to common controls */ 1259 return m_ListView.SendMessageW(uMsg, 0, 0); 1260 } 1261 1262 LRESULT CDefView::OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1263 { 1264 return reinterpret_cast<LRESULT>(m_pShellBrowser.p); 1265 } 1266 1267 LRESULT CDefView::OnNCCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1268 { 1269 this->AddRef(); 1270 bHandled = FALSE; 1271 return 0; 1272 } 1273 1274 VOID CDefView::OnFinalMessage(HWND) 1275 { 1276 this->Release(); 1277 } 1278 1279 /********************************************************** 1280 * ShellView_OnCreate() 1281 */ 1282 LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1283 { 1284 CComPtr<IDropTarget> pdt; 1285 CComPtr<IPersistFolder2> ppf2; 1286 1287 TRACE("%p\n", this); 1288 1289 if (SUCCEEDED(QueryInterface(IID_PPV_ARG(IDropTarget, &pdt)))) 1290 { 1291 if (FAILED(RegisterDragDrop(m_hWnd, pdt))) 1292 ERR("Registering Drag Drop Failed\n"); 1293 } 1294 1295 /* register for receiving notifications */ 1296 m_pSFParent->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2)); 1297 if (ppf2) 1298 { 1299 ppf2->GetCurFolder(&m_pidlParent); 1300 } 1301 1302 if (CreateList()) 1303 { 1304 if (InitList()) 1305 { 1306 FillList(); 1307 } 1308 } 1309 1310 if (m_FolderSettings.fFlags & FWF_DESKTOP) 1311 { 1312 HWND hwndSB; 1313 m_pShellBrowser->GetWindow(&hwndSB); 1314 SetShellWindowEx(hwndSB, m_ListView); 1315 } 1316 1317 SHChangeNotifyEntry ntreg[1]; 1318 ntreg[0].fRecursive = FALSE; 1319 ntreg[0].pidl = m_pidlParent; 1320 m_hNotify = SHChangeNotifyRegister(m_hWnd, 1321 SHCNRF_InterruptLevel | SHCNRF_ShellLevel | 1322 SHCNRF_NewDelivery, 1323 SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1324 1, ntreg); 1325 1326 /* _DoFolderViewCB(SFVM_GETNOTIFY, ?? ??) */ 1327 1328 m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_SHELLVIEW)); 1329 1330 BOOL bPreviousParentSpecial = m_isParentFolderSpecial; 1331 1332 /* A folder is special if it is the Desktop folder, 1333 * a network folder, or a Control Panel folder. */ 1334 m_isParentFolderSpecial = _ILIsDesktop(m_pidlParent) || _ILIsNetHood(m_pidlParent) 1335 || _ILIsControlPanel(ILFindLastID(m_pidlParent)); 1336 1337 /* Only force StatusBar part refresh if the state 1338 * changed from the previous folder. */ 1339 if (bPreviousParentSpecial != m_isParentFolderSpecial) 1340 { 1341 /* This handles changing StatusBar parts. */ 1342 _ForceStatusBarResize(); 1343 } 1344 1345 UpdateStatusbar(); 1346 1347 return S_OK; 1348 } 1349 1350 /********************************************************** 1351 * #### Handling of the menus #### 1352 */ 1353 1354 extern "C" DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID); 1355 1356 HMENU GetSubmenuByID(HMENU hmenu, UINT id) 1357 { 1358 MENUITEMINFOW mii = {sizeof(mii), MIIM_SUBMENU}; 1359 if (::GetMenuItemInfoW(hmenu, id, FALSE, &mii)) 1360 return mii.hSubMenu; 1361 1362 return NULL; 1363 } 1364 1365 /* ReallyGetMenuItemID returns the id of an item even if it opens a submenu, 1366 GetMenuItemID returns -1 if the specified item opens a submenu */ 1367 UINT ReallyGetMenuItemID(HMENU hmenu, int i) 1368 { 1369 MENUITEMINFOW mii = {sizeof(mii), MIIM_ID}; 1370 if (::GetMenuItemInfoW(hmenu, i, TRUE, &mii)) 1371 return mii.wID; 1372 1373 return UINT_MAX; 1374 } 1375 1376 HRESULT CDefView::FillFileMenu() 1377 { 1378 HMENU hFileMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_FILE); 1379 if (!hFileMenu) 1380 return E_FAIL; 1381 1382 /* Cleanup the items added previously */ 1383 for (int i = GetMenuItemCount(hFileMenu) - 1; i >= 0; i--) 1384 { 1385 UINT id = GetMenuItemID(hFileMenu, i); 1386 if (id < FCIDM_BROWSERFIRST || id > FCIDM_BROWSERLAST) 1387 DeleteMenu(hFileMenu, i, MF_BYPOSITION); 1388 } 1389 1390 /* In case we still have this left over, clean it up! */ 1391 if (m_pFileMenu) 1392 { 1393 IUnknown_SetSite(m_pFileMenu, NULL); 1394 m_pFileMenu.Release(); 1395 } 1396 /* Store the context menu in m_pFileMenu and keep it in order to invoke the selected command later on */ 1397 HRESULT hr = GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IContextMenu, &m_pFileMenu)); 1398 if (FAILED_UNEXPECTEDLY(hr)) 1399 return hr; 1400 1401 HMENU hmenu = CreatePopupMenu(); 1402 1403 hr = m_pFileMenu->QueryContextMenu(hmenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0); 1404 if (FAILED_UNEXPECTEDLY(hr)) 1405 return hr; 1406 1407 // TODO: filter or something 1408 1409 Shell_MergeMenus(hFileMenu, hmenu, 0, 0, 0xFFFF, MM_ADDSEPARATOR | MM_SUBMENUSHAVEIDS); 1410 1411 ::DestroyMenu(hmenu); 1412 1413 return S_OK; 1414 } 1415 1416 HRESULT CDefView::FillEditMenu() 1417 { 1418 HMENU hEditMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_EDIT); 1419 if (!hEditMenu) 1420 return E_FAIL; 1421 1422 HMENU hmenuContents = ::LoadMenuW(shell32_hInstance, L"MENU_003"); 1423 if (!hmenuContents) 1424 return E_FAIL; 1425 1426 Shell_MergeMenus(hEditMenu, hmenuContents, 0, 0, 0xFFFF, 0); 1427 1428 ::DestroyMenu(hmenuContents); 1429 1430 return S_OK; 1431 } 1432 1433 HRESULT CDefView::FillViewMenu() 1434 { 1435 HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW); 1436 if (!hViewMenu) 1437 return E_FAIL; 1438 1439 m_hMenuViewModes = ::LoadMenuW(shell32_hInstance, L"MENU_001"); 1440 if (!m_hMenuViewModes) 1441 return E_FAIL; 1442 1443 UINT i = SHMenuIndexFromID(hViewMenu, FCIDM_MENU_VIEW_SEP_OPTIONS); 1444 Shell_MergeMenus(hViewMenu, m_hMenuViewModes, i, 0, 0xFFFF, MM_ADDSEPARATOR | MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS); 1445 1446 return S_OK; 1447 } 1448 1449 HRESULT CDefView::FillArrangeAsMenu(HMENU hmenuArrange) 1450 { 1451 /* We only need to fill this once */ 1452 if (GetMenuItemID(hmenuArrange, 0) == FCIDM_SHVIEW_AUTOARRANGE) 1453 { 1454 Shell_MergeMenus(hmenuArrange, m_hMenuArrangeModes, 0, 0, 0xFFFF,0); 1455 } 1456 1457 /* Also check the menu item according to which we sort */ 1458 CheckMenuRadioItem(hmenuArrange, 1459 0x30, 1460 0x100, 1461 m_sortInfo.nHeaderID + 0x30, 1462 MF_BYCOMMAND); 1463 1464 if (m_FolderSettings.ViewMode == FVM_DETAILS || m_FolderSettings.ViewMode == FVM_LIST) 1465 { 1466 EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_BYCOMMAND | MF_GRAYED); 1467 EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_ALIGNTOGRID, MF_BYCOMMAND | MF_GRAYED); 1468 } 1469 else 1470 { 1471 EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_BYCOMMAND); 1472 EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_ALIGNTOGRID, MF_BYCOMMAND); 1473 1474 if (GetAutoArrange() == S_OK) 1475 CheckMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_CHECKED); 1476 else 1477 CheckMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_UNCHECKED); 1478 1479 if (_GetSnapToGrid() == S_OK) 1480 CheckMenuItem(hmenuArrange, FCIDM_SHVIEW_ALIGNTOGRID, MF_CHECKED); 1481 else 1482 CheckMenuItem(hmenuArrange, FCIDM_SHVIEW_ALIGNTOGRID, MF_UNCHECKED); 1483 } 1484 1485 1486 return S_OK; 1487 } 1488 1489 HRESULT CDefView::CheckViewMode(HMENU hmenuView) 1490 { 1491 if (m_FolderSettings.ViewMode >= FVM_FIRST && m_FolderSettings.ViewMode <= FVM_LAST) 1492 { 1493 UINT iItemFirst = FCIDM_SHVIEW_BIGICON; 1494 UINT iItemLast = iItemFirst + FVM_LAST - FVM_FIRST; 1495 UINT iItem = iItemFirst + m_FolderSettings.ViewMode - FVM_FIRST; 1496 CheckMenuRadioItem(hmenuView, iItemFirst, iItemLast, iItem, MF_BYCOMMAND); 1497 } 1498 1499 return S_OK; 1500 } 1501 1502 /********************************************************** 1503 * ShellView_GetSelections() 1504 * 1505 * - fills the m_apidl list with the selected objects 1506 * 1507 * RETURNS 1508 * number of selected items 1509 */ 1510 UINT CDefView::GetSelections() 1511 { 1512 SHFree(m_apidl); 1513 1514 m_cidl = m_ListView.GetSelectedCount(); 1515 m_apidl = static_cast<PCUITEMID_CHILD*>(SHAlloc(m_cidl * sizeof(PCUITEMID_CHILD))); 1516 if (!m_apidl) 1517 { 1518 m_cidl = 0; 1519 return 0; 1520 } 1521 1522 TRACE("-- Items selected =%u\n", m_cidl); 1523 1524 ASSERT(m_ListView); 1525 1526 UINT i = 0; 1527 int lvIndex = -1; 1528 while ((lvIndex = m_ListView.GetNextItem(lvIndex, LVNI_SELECTED)) > -1) 1529 { 1530 m_apidl[i] = _PidlByItem(lvIndex); 1531 i++; 1532 if (i == m_cidl) 1533 break; 1534 TRACE("-- selected Item found\n"); 1535 } 1536 1537 return m_cidl; 1538 } 1539 1540 HRESULT CDefView::InvokeContextMenuCommand(CComPtr<IContextMenu>& pCM, LPCSTR lpVerb, POINT* pt) 1541 { 1542 CMINVOKECOMMANDINFOEX cmi; 1543 1544 ZeroMemory(&cmi, sizeof(cmi)); 1545 cmi.cbSize = sizeof(cmi); 1546 cmi.hwnd = m_hWnd; 1547 cmi.lpVerb = lpVerb; 1548 1549 if (GetKeyState(VK_SHIFT) & 0x8000) 1550 cmi.fMask |= CMIC_MASK_SHIFT_DOWN; 1551 1552 if (GetKeyState(VK_CONTROL) & 0x8000) 1553 cmi.fMask |= CMIC_MASK_CONTROL_DOWN; 1554 1555 if (pt) 1556 { 1557 cmi.fMask |= CMIC_MASK_PTINVOKE; 1558 cmi.ptInvoke = *pt; 1559 } 1560 1561 HRESULT hr = pCM->InvokeCommand((LPCMINVOKECOMMANDINFO)&cmi); 1562 // Most of our callers will do this, but in case they don't do that (File menu!) 1563 IUnknown_SetSite(pCM, NULL); 1564 pCM.Release(); 1565 1566 if (FAILED_UNEXPECTEDLY(hr)) 1567 return hr; 1568 1569 return S_OK; 1570 } 1571 1572 /********************************************************** 1573 * ShellView_OpenSelectedItems() 1574 */ 1575 HRESULT CDefView::OpenSelectedItems() 1576 { 1577 HMENU hMenu; 1578 UINT uCommand; 1579 HRESULT hResult; 1580 1581 m_cidl = m_ListView.GetSelectedCount(); 1582 if (m_cidl == 0) 1583 return S_OK; 1584 1585 hResult = OnDefaultCommand(); 1586 if (hResult == S_OK) 1587 return hResult; 1588 1589 hMenu = CreatePopupMenu(); 1590 if (!hMenu) 1591 return E_FAIL; 1592 1593 CComPtr<IContextMenu> pCM; 1594 hResult = GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IContextMenu, &pCM)); 1595 MenuCleanup _(pCM, hMenu); 1596 if (FAILED_UNEXPECTEDLY(hResult)) 1597 return hResult; 1598 1599 hResult = pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_DEFAULTONLY); 1600 if (FAILED_UNEXPECTEDLY(hResult)) 1601 return hResult; 1602 1603 uCommand = GetMenuDefaultItem(hMenu, FALSE, 0); 1604 if (uCommand == (UINT)-1) 1605 { 1606 ERR("GetMenuDefaultItem returned -1\n"); 1607 return E_FAIL; 1608 } 1609 1610 InvokeContextMenuCommand(pCM, MAKEINTRESOURCEA(uCommand), NULL); 1611 1612 return hResult; 1613 } 1614 1615 /********************************************************** 1616 * ShellView_DoContextMenu() 1617 */ 1618 LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1619 { 1620 POINT pt; 1621 UINT uCommand; 1622 HRESULT hResult; 1623 1624 TRACE("(%p)\n", this); 1625 1626 if (m_hContextMenu != NULL) 1627 { 1628 ERR("HACK: Aborting context menu in nested call!\n"); 1629 return 0; 1630 } 1631 1632 m_hContextMenu = CreatePopupMenu(); 1633 if (!m_hContextMenu) 1634 return E_FAIL; 1635 1636 if (lParam != ~0) // unless app key (menu key) was pressed 1637 { 1638 pt.x = GET_X_LPARAM(lParam); 1639 pt.y = GET_Y_LPARAM(lParam); 1640 1641 LV_HITTESTINFO hittest = { pt }; 1642 ScreenToClient(&hittest.pt); 1643 m_ListView.HitTest(&hittest); 1644 1645 // Right-Clicked item is selected? If selected, no selection change. 1646 // If not selected, then reset the selection and select the item. 1647 if ((hittest.flags & LVHT_ONITEM) && 1648 m_ListView.GetItemState(hittest.iItem, LVIS_SELECTED) != LVIS_SELECTED) 1649 { 1650 SelectItem(hittest.iItem, SVSI_SELECT | SVSI_DESELECTOTHERS | SVSI_ENSUREVISIBLE); 1651 } 1652 } 1653 1654 m_cidl = m_ListView.GetSelectedCount(); 1655 /* In case we still have this left over, clean it up! */ 1656 hResult = GetItemObject( m_cidl ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM)); 1657 MenuCleanup _(m_pCM, m_hContextMenu); 1658 if (FAILED_UNEXPECTEDLY(hResult)) 1659 return 0; 1660 1661 /* Use 1 as the first id as we want 0 the mean that the user canceled the menu */ 1662 hResult = m_pCM->QueryContextMenu(m_hContextMenu, 0, CONTEXT_MENU_BASE_ID, FCIDM_SHVIEWLAST, CMF_NORMAL); 1663 if (FAILED_UNEXPECTEDLY(hResult)) 1664 return 0; 1665 1666 /* There is no position requested, so try to find one */ 1667 if (lParam == ~0) 1668 { 1669 HWND hFocus = ::GetFocus(); 1670 int lvIndex = -1; 1671 1672 if (hFocus == m_ListView.m_hWnd || m_ListView.IsChild(hFocus)) 1673 { 1674 /* Is there an item focused and selected? */ 1675 lvIndex = m_ListView.GetNextItem(-1, LVIS_SELECTED|LVIS_FOCUSED); 1676 /* If not, find the first selected item */ 1677 if (lvIndex < 0) 1678 lvIndex = m_ListView.GetNextItem(-1, LVIS_SELECTED); 1679 } 1680 1681 /* We got something */ 1682 if (lvIndex > -1) 1683 { 1684 /* Let's find the center of the icon */ 1685 RECT rc = { LVIR_ICON }; 1686 m_ListView.SendMessage(LVM_GETITEMRECT, lvIndex, (LPARAM)&rc); 1687 pt.x = (rc.right + rc.left) / 2; 1688 pt.y = (rc.bottom + rc.top) / 2; 1689 } 1690 else 1691 { 1692 /* We have to drop it somewhere.. */ 1693 pt.x = pt.y = 0; 1694 } 1695 1696 m_ListView.ClientToScreen(&pt); 1697 } 1698 1699 // This runs the message loop, calling back to us with f.e. WM_INITPOPUP (hence why m_hContextMenu and m_pCM exist) 1700 uCommand = TrackPopupMenu(m_hContextMenu, 1701 TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, 1702 pt.x, pt.y, 0, m_hWnd, NULL); 1703 if (uCommand == 0) 1704 return 0; 1705 1706 if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK) 1707 return 0; 1708 1709 InvokeContextMenuCommand(m_pCM, MAKEINTRESOURCEA(uCommand - CONTEXT_MENU_BASE_ID), &pt); 1710 1711 return 0; 1712 } 1713 1714 LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection) 1715 { 1716 HRESULT hResult; 1717 HMENU hMenu = NULL; 1718 1719 CComPtr<IContextMenu> pCM; 1720 hResult = GetItemObject( bUseSelection ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &pCM)); 1721 if (FAILED_UNEXPECTEDLY(hResult)) 1722 return 0; 1723 1724 MenuCleanup _(pCM, hMenu); 1725 1726 if ((uCommand != FCIDM_SHVIEW_DELETE) && (uCommand != FCIDM_SHVIEW_RENAME)) 1727 { 1728 hMenu = CreatePopupMenu(); 1729 if (!hMenu) 1730 return 0; 1731 1732 hResult = pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL); 1733 if (FAILED_UNEXPECTEDLY(hResult)) 1734 return 0; 1735 } 1736 1737 if (bUseSelection) 1738 { 1739 // FIXME: we should cache this.... 1740 SFGAOF rfg = SFGAO_BROWSABLE | SFGAO_CANCOPY | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_FILESYSTEM | SFGAO_FOLDER; 1741 hResult = m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &rfg); 1742 if (FAILED_UNEXPECTEDLY(hResult)) 1743 return 0; 1744 1745 if (!(rfg & SFGAO_CANMOVE) && uCommand == FCIDM_SHVIEW_CUT) 1746 return 0; 1747 if (!(rfg & SFGAO_CANCOPY) && uCommand == FCIDM_SHVIEW_COPY) 1748 return 0; 1749 if (!(rfg & SFGAO_CANDELETE) && uCommand == FCIDM_SHVIEW_DELETE) 1750 return 0; 1751 if (!(rfg & SFGAO_CANRENAME) && uCommand == FCIDM_SHVIEW_RENAME) 1752 return 0; 1753 if (!(rfg & SFGAO_HASPROPSHEET) && uCommand == FCIDM_SHVIEW_PROPERTIES) 1754 return 0; 1755 } 1756 1757 // FIXME: We should probably use the objects position? 1758 InvokeContextMenuCommand(pCM, MAKEINTRESOURCEA(uCommand), NULL); 1759 return 0; 1760 } 1761 1762 /********************************************************** 1763 * ##### message handling ##### 1764 */ 1765 1766 /********************************************************** 1767 * ShellView_OnSize() 1768 */ 1769 LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1770 { 1771 WORD wWidth, wHeight; 1772 1773 wWidth = LOWORD(lParam); 1774 wHeight = HIWORD(lParam); 1775 1776 TRACE("%p width=%u height=%u\n", this, wWidth, wHeight); 1777 1778 // WM_SIZE can come before WM_CREATE 1779 if (!m_ListView) 1780 return 0; 1781 1782 /* Resize the ListView to fit our window */ 1783 ::MoveWindow(m_ListView, 0, 0, wWidth, wHeight, TRUE); 1784 1785 _DoFolderViewCB(SFVM_SIZE, 0, 0); 1786 1787 _HandleStatusBarResize(wWidth); 1788 UpdateStatusbar(); 1789 1790 return 0; 1791 } 1792 1793 /********************************************************** 1794 * ShellView_OnDeactivate() 1795 * 1796 * NOTES 1797 * internal 1798 */ 1799 void CDefView::OnDeactivate() 1800 { 1801 TRACE("%p\n", this); 1802 1803 if (m_uState != SVUIA_DEACTIVATE) 1804 { 1805 // TODO: cleanup menu after deactivation 1806 1807 m_uState = SVUIA_DEACTIVATE; 1808 } 1809 } 1810 1811 void CDefView::DoActivate(UINT uState) 1812 { 1813 TRACE("%p uState=%x\n", this, uState); 1814 1815 /*don't do anything if the state isn't really changing */ 1816 if (m_uState == uState) 1817 { 1818 return; 1819 } 1820 1821 if (uState == SVUIA_DEACTIVATE) 1822 { 1823 OnDeactivate(); 1824 } 1825 else 1826 { 1827 if(m_hMenu && !m_bmenuBarInitialized) 1828 { 1829 FillEditMenu(); 1830 FillViewMenu(); 1831 m_pShellBrowser->SetMenuSB(m_hMenu, 0, m_hWnd); 1832 m_bmenuBarInitialized = TRUE; 1833 } 1834 1835 if (SVUIA_ACTIVATE_FOCUS == uState) 1836 { 1837 m_ListView.SetFocus(); 1838 } 1839 } 1840 1841 m_uState = uState; 1842 TRACE("--\n"); 1843 } 1844 1845 void CDefView::_DoCopyToMoveToFolder(BOOL bCopy) 1846 { 1847 if (!GetSelections()) 1848 return; 1849 1850 SFGAOF rfg = SFGAO_CANCOPY | SFGAO_CANMOVE | SFGAO_FILESYSTEM; 1851 HRESULT hr = m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &rfg); 1852 if (FAILED_UNEXPECTEDLY(hr)) 1853 return; 1854 1855 if (!bCopy && !(rfg & SFGAO_CANMOVE)) 1856 return; 1857 if (bCopy && !(rfg & SFGAO_CANCOPY)) 1858 return; 1859 1860 CComPtr<IContextMenu> pCM; 1861 hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, IID_IContextMenu, 0, (void **)&pCM); 1862 if (FAILED_UNEXPECTEDLY(hr)) 1863 return; 1864 1865 InvokeContextMenuCommand(pCM, (bCopy ? "copyto" : "moveto"), NULL); 1866 } 1867 1868 /********************************************************** 1869 * ShellView_OnActivate() 1870 */ 1871 LRESULT CDefView::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1872 { 1873 DoActivate(SVUIA_ACTIVATE_FOCUS); 1874 return 0; 1875 } 1876 1877 /********************************************************** 1878 * ShellView_OnSetFocus() 1879 * 1880 */ 1881 LRESULT CDefView::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1882 { 1883 TRACE("%p\n", this); 1884 1885 /* Tell the browser one of our windows has received the focus. This 1886 should always be done before merging menus (OnActivate merges the 1887 menus) if one of our windows has the focus.*/ 1888 1889 m_pShellBrowser->OnViewWindowActive(this); 1890 DoActivate(SVUIA_ACTIVATE_FOCUS); 1891 1892 /* Set the focus to the listview */ 1893 m_ListView.SetFocus(); 1894 1895 /* Notify the ICommDlgBrowser interface */ 1896 OnStateChange(CDBOSC_SETFOCUS); 1897 1898 return 0; 1899 } 1900 1901 /********************************************************** 1902 * ShellView_OnKillFocus() 1903 */ 1904 LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1905 { 1906 TRACE("(%p) stub\n", this); 1907 1908 DoActivate(SVUIA_ACTIVATE_NOFOCUS); 1909 /* Notify the ICommDlgBrowser */ 1910 OnStateChange(CDBOSC_KILLFOCUS); 1911 1912 return 0; 1913 } 1914 1915 /********************************************************** 1916 * ShellView_OnCommand() 1917 * 1918 * NOTES 1919 * the CmdID's are the ones from the context menu 1920 */ 1921 LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1922 { 1923 DWORD dwCmdID; 1924 DWORD dwCmd; 1925 HWND hwndCmd; 1926 int nCount; 1927 1928 dwCmdID = GET_WM_COMMAND_ID(wParam, lParam); 1929 dwCmd = GET_WM_COMMAND_CMD(wParam, lParam); 1930 hwndCmd = GET_WM_COMMAND_HWND(wParam, lParam); 1931 1932 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n", this, dwCmdID, dwCmd, hwndCmd); 1933 1934 switch (dwCmdID) 1935 { 1936 case FCIDM_SHVIEW_SMALLICON: 1937 m_FolderSettings.ViewMode = FVM_SMALLICON; 1938 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON); 1939 CheckToolbar(); 1940 break; 1941 1942 case FCIDM_SHVIEW_BIGICON: 1943 m_FolderSettings.ViewMode = FVM_ICON; 1944 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_ICON); 1945 CheckToolbar(); 1946 break; 1947 1948 case FCIDM_SHVIEW_LISTVIEW: 1949 m_FolderSettings.ViewMode = FVM_LIST; 1950 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_LIST); 1951 CheckToolbar(); 1952 break; 1953 1954 case FCIDM_SHVIEW_REPORTVIEW: 1955 m_FolderSettings.ViewMode = FVM_DETAILS; 1956 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_REPORT); 1957 CheckToolbar(); 1958 break; 1959 1960 /* the menu-ID's for sorting are 0x30... see shrec.rc */ 1961 case 0x30: 1962 case 0x31: 1963 case 0x32: 1964 case 0x33: 1965 m_sortInfo.nHeaderID = dwCmdID - 0x30; 1966 m_sortInfo.bIsAscending = TRUE; 1967 _Sort(); 1968 break; 1969 1970 case FCIDM_SHVIEW_SNAPTOGRID: 1971 m_ListView.Arrange(LVA_SNAPTOGRID); 1972 break; 1973 case FCIDM_SHVIEW_ALIGNTOGRID: 1974 if (_GetSnapToGrid() == S_OK) 1975 m_ListView.SetExtendedListViewStyle(0, LVS_EX_SNAPTOGRID); 1976 else 1977 ArrangeGrid(); 1978 break; 1979 case FCIDM_SHVIEW_AUTOARRANGE: 1980 if (GetAutoArrange() == S_OK) 1981 m_ListView.ModifyStyle(LVS_AUTOARRANGE, 0); 1982 else 1983 AutoArrange(); 1984 break; 1985 case FCIDM_SHVIEW_SELECTALL: 1986 m_ListView.SetItemState(-1, LVIS_SELECTED, LVIS_SELECTED); 1987 break; 1988 1989 case FCIDM_SHVIEW_INVERTSELECTION: 1990 nCount = m_ListView.GetItemCount(); 1991 for (int i=0; i < nCount; i++) 1992 m_ListView.SetItemState(i, m_ListView.GetItemState(i, LVIS_SELECTED) ? 0 : LVIS_SELECTED, LVIS_SELECTED); 1993 break; 1994 1995 case FCIDM_SHVIEW_REFRESH: 1996 Refresh(); 1997 break; 1998 1999 case FCIDM_SHVIEW_DELETE: 2000 case FCIDM_SHVIEW_CUT: 2001 case FCIDM_SHVIEW_COPY: 2002 case FCIDM_SHVIEW_RENAME: 2003 case FCIDM_SHVIEW_PROPERTIES: 2004 if (SHRestricted(REST_NOVIEWCONTEXTMENU)) 2005 return 0; 2006 2007 return OnExplorerCommand(dwCmdID, TRUE); 2008 2009 case FCIDM_SHVIEW_COPYTO: 2010 case FCIDM_SHVIEW_MOVETO: 2011 _DoCopyToMoveToFolder(dwCmdID == FCIDM_SHVIEW_COPYTO); 2012 return 0; 2013 2014 case FCIDM_SHVIEW_INSERT: 2015 case FCIDM_SHVIEW_UNDO: 2016 case FCIDM_SHVIEW_INSERTLINK: 2017 case FCIDM_SHVIEW_NEWFOLDER: 2018 return OnExplorerCommand(dwCmdID, FALSE); 2019 default: 2020 { 2021 /* WM_COMMAND messages from the file menu are routed to the CDefView so as to let m_pFileMenu handle the command */ 2022 if (m_pFileMenu && dwCmd == 0) 2023 { 2024 HMENU Dummy = NULL; 2025 MenuCleanup _(m_pFileMenu, Dummy); 2026 InvokeContextMenuCommand(m_pFileMenu, MAKEINTRESOURCEA(dwCmdID), NULL); 2027 } 2028 } 2029 } 2030 2031 return 0; 2032 } 2033 2034 static BOOL 2035 SelectExtOnRename(void) 2036 { 2037 HKEY hKey; 2038 LONG error; 2039 DWORD dwValue = FALSE, cbValue; 2040 2041 error = RegOpenKeyExW(HKEY_CURRENT_USER, 2042 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer", 2043 0, KEY_READ, &hKey); 2044 if (error) 2045 return dwValue; 2046 2047 cbValue = sizeof(dwValue); 2048 RegQueryValueExW(hKey, L"SelectExtOnRename", NULL, NULL, (LPBYTE)&dwValue, &cbValue); 2049 2050 RegCloseKey(hKey); 2051 return !!dwValue; 2052 } 2053 2054 /********************************************************** 2055 * ShellView_OnNotify() 2056 */ 2057 2058 LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 2059 { 2060 UINT CtlID; 2061 LPNMHDR lpnmh; 2062 LPNMLISTVIEW lpnmlv; 2063 NMLVDISPINFOW *lpdi; 2064 PCUITEMID_CHILD pidl; 2065 BOOL unused; 2066 2067 CtlID = wParam; 2068 lpnmh = (LPNMHDR)lParam; 2069 lpnmlv = (LPNMLISTVIEW)lpnmh; 2070 lpdi = (NMLVDISPINFOW *)lpnmh; 2071 2072 TRACE("%p CtlID=%u lpnmh->code=%x\n", this, CtlID, lpnmh->code); 2073 2074 switch (lpnmh->code) 2075 { 2076 case NM_SETFOCUS: 2077 TRACE("-- NM_SETFOCUS %p\n", this); 2078 OnSetFocus(0, 0, 0, unused); 2079 break; 2080 2081 case NM_KILLFOCUS: 2082 TRACE("-- NM_KILLFOCUS %p\n", this); 2083 OnDeactivate(); 2084 /* Notify the ICommDlgBrowser interface */ 2085 OnStateChange(CDBOSC_KILLFOCUS); 2086 break; 2087 2088 case NM_CUSTOMDRAW: 2089 TRACE("-- NM_CUSTOMDRAW %p\n", this); 2090 return CDRF_DODEFAULT; 2091 2092 case NM_RELEASEDCAPTURE: 2093 TRACE("-- NM_RELEASEDCAPTURE %p\n", this); 2094 break; 2095 2096 case NM_CLICK: 2097 TRACE("-- NM_CLICK %p\n", this); 2098 break; 2099 2100 case NM_RCLICK: 2101 TRACE("-- NM_RCLICK %p\n", this); 2102 break; 2103 2104 case NM_DBLCLK: 2105 TRACE("-- NM_DBLCLK %p\n", this); 2106 OpenSelectedItems(); 2107 break; 2108 2109 case NM_RETURN: 2110 TRACE("-- NM_RETURN %p\n", this); 2111 OpenSelectedItems(); 2112 break; 2113 2114 case HDN_ENDTRACKW: 2115 TRACE("-- HDN_ENDTRACKW %p\n", this); 2116 /*nColumn1 = m_ListView.GetColumnWidth(0); 2117 nColumn2 = m_ListView.GetColumnWidth(1);*/ 2118 break; 2119 2120 case LVN_DELETEITEM: 2121 TRACE("-- LVN_DELETEITEM %p\n", this); 2122 2123 /*delete the pidl because we made a copy of it*/ 2124 SHFree(reinterpret_cast<LPVOID>(lpnmlv->lParam)); 2125 2126 break; 2127 2128 case LVN_DELETEALLITEMS: 2129 TRACE("-- LVN_DELETEALLITEMS %p\n", this); 2130 return FALSE; 2131 2132 case LVN_INSERTITEM: 2133 TRACE("-- LVN_INSERTITEM (STUB)%p\n", this); 2134 break; 2135 2136 case LVN_ITEMACTIVATE: 2137 TRACE("-- LVN_ITEMACTIVATE %p\n", this); 2138 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */ 2139 break; 2140 2141 case LVN_COLUMNCLICK: 2142 m_sortInfo.nHeaderID = lpnmlv->iSubItem; 2143 if (m_sortInfo.nLastHeaderID == m_sortInfo.nHeaderID) 2144 m_sortInfo.bIsAscending = !m_sortInfo.bIsAscending; 2145 else 2146 m_sortInfo.bIsAscending = TRUE; 2147 _Sort(); 2148 break; 2149 2150 case LVN_GETDISPINFOA: 2151 case LVN_GETDISPINFOW: 2152 TRACE("-- LVN_GETDISPINFO %p\n", this); 2153 pidl = _PidlByItem(lpdi->item); 2154 2155 if (lpdi->item.mask & LVIF_TEXT) /* text requested */ 2156 { 2157 if (m_pSF2Parent) 2158 { 2159 SHELLDETAILS sd; 2160 if (FAILED_UNEXPECTEDLY(m_pSF2Parent->GetDetailsOf(pidl, lpdi->item.iSubItem, &sd))) 2161 break; 2162 2163 if (lpnmh->code == LVN_GETDISPINFOA) 2164 { 2165 /* shouldn't happen */ 2166 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh; 2167 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL); 2168 TRACE("-- text=%s\n", lpdiA->item.pszText); 2169 } 2170 else /* LVN_GETDISPINFOW */ 2171 { 2172 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL); 2173 TRACE("-- text=%s\n", debugstr_w(lpdi->item.pszText)); 2174 } 2175 } 2176 else 2177 { 2178 FIXME("no m_pSF2Parent\n"); 2179 } 2180 } 2181 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */ 2182 { 2183 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0); 2184 } 2185 if(lpdi->item.mask & LVIF_STATE) 2186 { 2187 ULONG attributes = SFGAO_HIDDEN; 2188 if (SUCCEEDED(m_pSFParent->GetAttributesOf(1, &pidl, &attributes))) 2189 { 2190 if (attributes & SFGAO_HIDDEN) 2191 { 2192 lpdi->item.state |= LVIS_CUT; 2193 } 2194 } 2195 } 2196 lpdi->item.mask |= LVIF_DI_SETITEM; 2197 break; 2198 2199 case LVN_ITEMCHANGED: 2200 TRACE("-- LVN_ITEMCHANGED %p\n", this); 2201 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */ 2202 UpdateStatusbar(); 2203 _DoFolderViewCB(SFVM_SELECTIONCHANGED, NULL/* FIXME */, NULL/* FIXME */); 2204 break; 2205 2206 case LVN_BEGINDRAG: 2207 case LVN_BEGINRDRAG: 2208 TRACE("-- LVN_BEGINDRAG\n"); 2209 2210 if (GetSelections()) 2211 { 2212 CComPtr<IDataObject> pda; 2213 DWORD dwAttributes = SFGAO_CANCOPY | SFGAO_CANLINK; 2214 DWORD dwEffect = DROPEFFECT_MOVE; 2215 2216 if (SUCCEEDED(m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IDataObject, &pda)))) 2217 { 2218 LPNMLISTVIEW params = (LPNMLISTVIEW)lParam; 2219 2220 if (SUCCEEDED(m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &dwAttributes))) 2221 { 2222 dwEffect |= dwAttributes & (SFGAO_CANCOPY | SFGAO_CANLINK); 2223 } 2224 2225 CComPtr<IAsyncOperation> piaso; 2226 if (SUCCEEDED(pda->QueryInterface(IID_PPV_ARG(IAsyncOperation, &piaso)))) 2227 { 2228 piaso->SetAsyncMode(TRUE); 2229 } 2230 2231 DWORD dwEffect2; 2232 2233 m_pSourceDataObject = pda; 2234 m_ptFirstMousePos = params->ptAction; 2235 ClientToScreen(&m_ptFirstMousePos); 2236 ::ClientToListView(m_ListView, &m_ptFirstMousePos); 2237 2238 HIMAGELIST big_icons, small_icons; 2239 Shell_GetImageLists(&big_icons, &small_icons); 2240 PCUITEMID_CHILD pidl = _PidlByItem(params->iItem); 2241 int iIcon = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0); 2242 POINT ptItem; 2243 m_ListView.GetItemPosition(params->iItem, &ptItem); 2244 2245 ImageList_BeginDrag(big_icons, iIcon, params->ptAction.x - ptItem.x, params->ptAction.y - ptItem.y); 2246 2247 DoDragDrop(pda, this, dwEffect, &dwEffect2); 2248 2249 m_pSourceDataObject.Release(); 2250 } 2251 } 2252 break; 2253 2254 case LVN_BEGINLABELEDITW: 2255 { 2256 DWORD dwAttr = SFGAO_CANRENAME; 2257 pidl = _PidlByItem(lpdi->item); 2258 2259 TRACE("-- LVN_BEGINLABELEDITW %p\n", this); 2260 2261 m_pSFParent->GetAttributesOf(1, &pidl, &dwAttr); 2262 if (SFGAO_CANRENAME & dwAttr) 2263 { 2264 HWND hEdit = reinterpret_cast<HWND>(m_ListView.SendMessage(LVM_GETEDITCONTROL)); 2265 SHLimitInputEdit(hEdit, m_pSFParent); 2266 2267 /* smartass-renaming: See CORE-15242 */ 2268 if (!(dwAttr & SFGAO_FOLDER) && (dwAttr & SFGAO_FILESYSTEM) && 2269 (lpdi->item.mask & LVIF_TEXT) && !SelectExtOnRename()) 2270 { 2271 WCHAR szFullPath[MAX_PATH]; 2272 PIDLIST_ABSOLUTE pidlFull = ILCombine(m_pidlParent, pidl); 2273 SHGetPathFromIDListW(pidlFull, szFullPath); 2274 2275 if (!SHELL_FS_HideExtension(szFullPath)) 2276 { 2277 LPWSTR pszText = lpdi->item.pszText; 2278 LPWSTR pchDotExt = PathFindExtensionW(pszText); 2279 ::PostMessageW(hEdit, EM_SETSEL, 0, pchDotExt - pszText); 2280 ::PostMessageW(hEdit, EM_SCROLLCARET, 0, 0); 2281 } 2282 2283 ILFree(pidlFull); 2284 } 2285 2286 m_isEditing = TRUE; 2287 return FALSE; 2288 } 2289 2290 return TRUE; 2291 } 2292 2293 case LVN_ENDLABELEDITW: 2294 { 2295 TRACE("-- LVN_ENDLABELEDITW %p\n", this); 2296 2297 m_isEditing = FALSE; 2298 2299 if (lpdi->item.pszText) 2300 { 2301 HRESULT hr; 2302 LVITEMW lvItem; 2303 2304 pidl = _PidlByItem(lpdi->item); 2305 PITEMID_CHILD pidlNew = NULL; 2306 hr = m_pSFParent->SetNameOf(0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidlNew); 2307 2308 if (SUCCEEDED(hr) && pidlNew) 2309 { 2310 lvItem.mask = LVIF_PARAM|LVIF_IMAGE; 2311 lvItem.iItem = lpdi->item.iItem; 2312 lvItem.iSubItem = 0; 2313 lvItem.lParam = reinterpret_cast<LPARAM>(pidlNew); 2314 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0); 2315 m_ListView.SetItem(&lvItem); 2316 m_ListView.Update(lpdi->item.iItem); 2317 return TRUE; 2318 } 2319 } 2320 2321 return FALSE; 2322 } 2323 2324 default: 2325 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh->code); 2326 break; 2327 } 2328 2329 return 0; 2330 } 2331 2332 /* 2333 * This is just a quick hack to make the desktop work correctly. 2334 * ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the way that 2335 * a folder should know if it should update upon a change notification. 2336 * It is exported by merged folders at a minimum. 2337 */ 2338 static BOOL ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2) 2339 { 2340 if (!pidl1 || !pidl2) 2341 return FALSE; 2342 if (ILIsParent(pidl1, pidl2, TRUE)) 2343 return TRUE; 2344 2345 if (_ILIsDesktop(pidl1)) 2346 { 2347 PIDLIST_ABSOLUTE deskpidl; 2348 SHGetFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, &deskpidl); 2349 if (ILIsParent(deskpidl, pidl2, TRUE)) 2350 { 2351 ILFree(deskpidl); 2352 return TRUE; 2353 } 2354 ILFree(deskpidl); 2355 SHGetFolderLocation(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, &deskpidl); 2356 if (ILIsParent(deskpidl, pidl2, TRUE)) 2357 { 2358 ILFree(deskpidl); 2359 return TRUE; 2360 } 2361 ILFree(deskpidl); 2362 } 2363 2364 WCHAR szPath1[MAX_PATH], szPath2[MAX_PATH]; 2365 LPITEMIDLIST pidl2Clone = ILClone(pidl2); 2366 ILRemoveLastID(pidl2Clone); 2367 if (SHGetPathFromIDListW(pidl1, szPath1) && 2368 SHGetPathFromIDListW(pidl2Clone, szPath2)) 2369 { 2370 if (lstrcmpiW(szPath1, szPath2) == 0) 2371 { 2372 ILFree(pidl2Clone); 2373 return TRUE; 2374 } 2375 } 2376 ILFree(pidl2Clone); 2377 2378 return FALSE; 2379 } 2380 2381 /********************************************************** 2382 * ShellView_OnChange() 2383 */ 2384 LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 2385 { 2386 // The change notify can come before WM_CREATE. 2387 if (!m_ListView) 2388 return FALSE; 2389 2390 HANDLE hChange = (HANDLE)wParam; 2391 DWORD dwProcID = (DWORD)lParam; 2392 PIDLIST_ABSOLUTE *Pidls; 2393 LONG lEvent; 2394 HANDLE hLock = SHChangeNotification_Lock(hChange, dwProcID, &Pidls, &lEvent); 2395 if (hLock == NULL) 2396 { 2397 ERR("hLock == NULL\n"); 2398 return FALSE; 2399 } 2400 2401 BOOL bParent0 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[0]); 2402 BOOL bParent1 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[1]); 2403 2404 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam); 2405 2406 lEvent &= ~SHCNE_INTERRUPT; 2407 switch (lEvent) 2408 { 2409 case SHCNE_MKDIR: 2410 case SHCNE_CREATE: 2411 if (bParent0) 2412 { 2413 if (LV_FindItemByPidl(ILFindLastID(Pidls[0])) == -1) 2414 { 2415 LV_AddItem(ILFindLastID(Pidls[0])); 2416 } 2417 else 2418 { 2419 LV_ProdItem(ILFindLastID(Pidls[0])); 2420 } 2421 } 2422 break; 2423 2424 case SHCNE_RMDIR: 2425 case SHCNE_DELETE: 2426 if (bParent0) 2427 LV_DeleteItem(ILFindLastID(Pidls[0])); 2428 break; 2429 2430 case SHCNE_RENAMEFOLDER: 2431 case SHCNE_RENAMEITEM: 2432 if (bParent0 && bParent1) 2433 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[1])); 2434 else if (bParent0) 2435 LV_DeleteItem(ILFindLastID(Pidls[0])); 2436 else if (bParent1) 2437 LV_AddItem(ILFindLastID(Pidls[1])); 2438 break; 2439 2440 case SHCNE_UPDATEITEM: 2441 if (bParent0) 2442 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0])); 2443 break; 2444 2445 case SHCNE_UPDATEDIR: 2446 Refresh(); 2447 break; 2448 } 2449 2450 SHChangeNotification_Unlock(hLock); 2451 return TRUE; 2452 } 2453 2454 HRESULT SHGetMenuIdFromMenuMsg(UINT uMsg, LPARAM lParam, UINT *CmdId); 2455 HRESULT SHSetMenuIdInMenuMsg(UINT uMsg, LPARAM lParam, UINT CmdId); 2456 2457 /********************************************************** 2458 * CDefView::OnCustomItem 2459 */ 2460 LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 2461 { 2462 if (!m_pCM) 2463 { 2464 /* no menu */ 2465 ERR("no context menu!!!\n"); 2466 return FALSE; 2467 } 2468 2469 /* The lParam of WM_DRAWITEM WM_MEASUREITEM contain a menu id and this also needs to 2470 be changed to a menu identifier offset */ 2471 UINT CmdID; 2472 HRESULT hres = SHGetMenuIdFromMenuMsg(uMsg, lParam, &CmdID); 2473 if (SUCCEEDED(hres)) 2474 SHSetMenuIdInMenuMsg(uMsg, lParam, CmdID - CONTEXT_MENU_BASE_ID); 2475 2476 /* Forward the message to the IContextMenu2 */ 2477 LRESULT result; 2478 hres = SHForwardContextMenuMsg(m_pCM, uMsg, wParam, lParam, &result, TRUE); 2479 2480 return (SUCCEEDED(hres)); 2481 } 2482 2483 LRESULT CDefView::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 2484 { 2485 /* Wallpaper setting affects drop shadows effect */ 2486 if (wParam == SPI_SETDESKWALLPAPER || wParam == 0) 2487 UpdateListColors(); 2488 2489 return S_OK; 2490 } 2491 2492 /********************************************************** 2493 * CDefView::OnInitMenuPopup 2494 */ 2495 LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 2496 { 2497 HMENU hmenu = (HMENU) wParam; 2498 int nPos = LOWORD(lParam); 2499 UINT menuItemId; 2500 2501 if (m_pCM) 2502 { 2503 OnCustomItem(uMsg, wParam, lParam, bHandled); 2504 } 2505 2506 HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW); 2507 2508 if (GetSelections() == 0) 2509 { 2510 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_CUT, MF_GRAYED); 2511 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPY, MF_GRAYED); 2512 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME, MF_GRAYED); 2513 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPYTO, MF_GRAYED); 2514 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_MOVETO, MF_GRAYED); 2515 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_DELETE, MF_GRAYED); 2516 } 2517 else 2518 { 2519 // FIXME: Check copyable 2520 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_CUT, MF_ENABLED); 2521 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPY, MF_ENABLED); 2522 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME, MF_ENABLED); 2523 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPYTO, MF_ENABLED); 2524 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_MOVETO, MF_ENABLED); 2525 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_DELETE, MF_ENABLED); 2526 } 2527 2528 /* Lets try to find out what the hell wParam is */ 2529 if (hmenu == GetSubMenu(m_hMenu, nPos)) 2530 menuItemId = ReallyGetMenuItemID(m_hMenu, nPos); 2531 else if (hViewMenu && hmenu == GetSubMenu(hViewMenu, nPos)) 2532 menuItemId = ReallyGetMenuItemID(hViewMenu, nPos); 2533 else if (m_hContextMenu && hmenu == GetSubMenu(m_hContextMenu, nPos)) 2534 menuItemId = ReallyGetMenuItemID(m_hContextMenu, nPos); 2535 else 2536 return FALSE; 2537 2538 switch (menuItemId) 2539 { 2540 case FCIDM_MENU_FILE: 2541 FillFileMenu(); 2542 break; 2543 case FCIDM_MENU_VIEW: 2544 case FCIDM_SHVIEW_VIEW: 2545 CheckViewMode(hmenu); 2546 break; 2547 case FCIDM_SHVIEW_ARRANGE: 2548 FillArrangeAsMenu(hmenu); 2549 break; 2550 } 2551 2552 return FALSE; 2553 } 2554 2555 /********************************************************** 2556 * 2557 * 2558 * The INTERFACE of the IShellView object 2559 * 2560 * 2561 ********************************************************** 2562 */ 2563 2564 /********************************************************** 2565 * ShellView_GetWindow 2566 */ 2567 HRESULT WINAPI CDefView::GetWindow(HWND *phWnd) 2568 { 2569 TRACE("(%p)\n", this); 2570 2571 *phWnd = m_hWnd; 2572 2573 return S_OK; 2574 } 2575 2576 HRESULT WINAPI CDefView::ContextSensitiveHelp(BOOL fEnterMode) 2577 { 2578 FIXME("(%p) stub\n", this); 2579 2580 return E_NOTIMPL; 2581 } 2582 2583 /********************************************************** 2584 * IShellView_TranslateAccelerator 2585 * 2586 * FIXME: 2587 * use the accel functions 2588 */ 2589 HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg) 2590 { 2591 if (m_isEditing) 2592 return S_FALSE; 2593 2594 if (lpmsg->message >= WM_KEYFIRST && lpmsg->message <= WM_KEYLAST) 2595 { 2596 if (::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg) != 0) 2597 return S_OK; 2598 2599 TRACE("-- key=0x%04lx\n", lpmsg->wParam) ; 2600 } 2601 2602 return m_pShellBrowser->TranslateAcceleratorSB(lpmsg, 0); 2603 } 2604 2605 HRESULT WINAPI CDefView::EnableModeless(BOOL fEnable) 2606 { 2607 FIXME("(%p) stub\n", this); 2608 2609 return E_NOTIMPL; 2610 } 2611 2612 HRESULT WINAPI CDefView::UIActivate(UINT uState) 2613 { 2614 TRACE("(%p)->(state=%x) stub\n", this, uState); 2615 2616 /* don't do anything if the state isn't really changing */ 2617 if (m_uState == uState) 2618 { 2619 return S_OK; 2620 } 2621 2622 /* OnActivate handles the menu merging and internal state */ 2623 DoActivate(uState); 2624 2625 /* only do This if we are active */ 2626 if (uState != SVUIA_DEACTIVATE) 2627 { 2628 _ForceStatusBarResize(); 2629 2630 /* Set the text for the status bar */ 2631 UpdateStatusbar(); 2632 } 2633 2634 return S_OK; 2635 } 2636 2637 HRESULT WINAPI CDefView::Refresh() 2638 { 2639 TRACE("(%p)\n", this); 2640 2641 _DoFolderViewCB(SFVM_LISTREFRESHED, TRUE, 0); 2642 2643 m_ListView.DeleteAllItems(); 2644 FillList(); 2645 2646 return S_OK; 2647 } 2648 2649 HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd) 2650 { 2651 return CreateViewWindow3(psb, lpPrevView, SV3CVW3_DEFAULT, 2652 (FOLDERFLAGS)lpfs->fFlags, (FOLDERFLAGS)lpfs->fFlags, (FOLDERVIEWMODE)lpfs->ViewMode, NULL, prcView, phWnd); 2653 } 2654 2655 HRESULT WINAPI CDefView::DestroyViewWindow() 2656 { 2657 TRACE("(%p)\n", this); 2658 2659 /* Make absolutely sure all our UI is cleaned up */ 2660 UIActivate(SVUIA_DEACTIVATE); 2661 2662 if (m_hAccel) 2663 { 2664 // "Accelerator tables loaded from resources are freed automatically when the application terminates." -- MSDN 2665 m_hAccel = NULL; 2666 } 2667 2668 if (m_hMenuArrangeModes) 2669 { 2670 DestroyMenu(m_hMenuArrangeModes); 2671 m_hMenuArrangeModes = NULL; 2672 } 2673 2674 if (m_hMenuViewModes) 2675 { 2676 DestroyMenu(m_hMenuViewModes); 2677 m_hMenuViewModes = NULL; 2678 } 2679 2680 if (m_hMenu) 2681 { 2682 DestroyMenu(m_hMenu); 2683 m_hMenu = NULL; 2684 } 2685 2686 if (m_ListView) 2687 { 2688 m_ListView.DestroyWindow(); 2689 } 2690 2691 if (m_hWnd) 2692 { 2693 _DoFolderViewCB(SFVM_WINDOWCLOSING, (WPARAM)m_hWnd, 0); 2694 DestroyWindow(); 2695 } 2696 2697 m_pShellBrowser.Release(); 2698 m_pCommDlgBrowser.Release(); 2699 2700 return S_OK; 2701 } 2702 2703 HRESULT WINAPI CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs) 2704 { 2705 TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs, 2706 m_FolderSettings.ViewMode, m_FolderSettings.fFlags); 2707 2708 if (!lpfs) 2709 return E_INVALIDARG; 2710 2711 *lpfs = m_FolderSettings; 2712 return S_OK; 2713 } 2714 2715 HRESULT WINAPI CDefView::AddPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam) 2716 { 2717 FIXME("(%p) stub\n", this); 2718 2719 return E_NOTIMPL; 2720 } 2721 2722 HRESULT WINAPI CDefView::SaveViewState() 2723 { 2724 FIXME("(%p) stub\n", this); 2725 2726 return S_OK; 2727 } 2728 2729 HRESULT WINAPI CDefView::SelectItem(PCUITEMID_CHILD pidl, UINT uFlags) 2730 { 2731 int i; 2732 2733 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl, uFlags); 2734 2735 if (!m_ListView) 2736 { 2737 ERR("!m_ListView\n"); 2738 return E_FAIL; 2739 } 2740 2741 i = LV_FindItemByPidl(pidl); 2742 if (i == -1) 2743 return S_OK; 2744 2745 LVITEMW lvItem = {0}; 2746 lvItem.mask = LVIF_STATE; 2747 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED; 2748 2749 while (m_ListView.GetItem(&lvItem)) 2750 { 2751 if (lvItem.iItem == i) 2752 { 2753 if (uFlags & SVSI_SELECT) 2754 lvItem.state |= LVIS_SELECTED; 2755 else 2756 lvItem.state &= ~LVIS_SELECTED; 2757 2758 if (uFlags & SVSI_FOCUSED) 2759 lvItem.state |= LVIS_FOCUSED; 2760 else 2761 lvItem.state &= ~LVIS_FOCUSED; 2762 } 2763 else 2764 { 2765 if (uFlags & SVSI_DESELECTOTHERS) 2766 { 2767 lvItem.state &= ~LVIS_SELECTED; 2768 } 2769 lvItem.state &= ~LVIS_FOCUSED; 2770 } 2771 2772 m_ListView.SetItem(&lvItem); 2773 lvItem.iItem++; 2774 } 2775 2776 if (uFlags & SVSI_ENSUREVISIBLE) 2777 m_ListView.EnsureVisible(i, FALSE); 2778 2779 if((uFlags & SVSI_EDIT) == SVSI_EDIT) 2780 m_ListView.EditLabel(i); 2781 2782 return S_OK; 2783 } 2784 2785 HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut) 2786 { 2787 HRESULT hr = E_NOINTERFACE; 2788 2789 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem, debugstr_guid(&riid), ppvOut); 2790 2791 if (!ppvOut) 2792 return E_INVALIDARG; 2793 2794 *ppvOut = NULL; 2795 2796 switch (uItem) 2797 { 2798 case SVGIO_BACKGROUND: 2799 if (IsEqualIID(riid, IID_IContextMenu)) 2800 { 2801 hr = CDefViewBckgrndMenu_CreateInstance(m_pSF2Parent, riid, ppvOut); 2802 if (FAILED_UNEXPECTEDLY(hr)) 2803 return hr; 2804 2805 IUnknown_SetSite(*((IUnknown**)ppvOut), (IShellView *)this); 2806 } 2807 else if (IsEqualIID(riid, IID_IDispatch)) 2808 { 2809 if (m_pShellFolderViewDual == NULL) 2810 { 2811 hr = CDefViewDual_Constructor(riid, (LPVOID*)&m_pShellFolderViewDual); 2812 if (FAILED_UNEXPECTEDLY(hr)) 2813 return hr; 2814 } 2815 hr = m_pShellFolderViewDual->QueryInterface(riid, ppvOut); 2816 } 2817 break; 2818 2819 case SVGIO_SELECTION: 2820 GetSelections(); 2821 hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, riid, 0, ppvOut); 2822 if (FAILED_UNEXPECTEDLY(hr)) 2823 return hr; 2824 2825 if (IsEqualIID(riid, IID_IContextMenu)) 2826 IUnknown_SetSite(*((IUnknown**)ppvOut), (IShellView *)this); 2827 2828 break; 2829 } 2830 2831 TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut); 2832 2833 return hr; 2834 } 2835 2836 HRESULT STDMETHODCALLTYPE CDefView::GetCurrentViewMode(UINT *pViewMode) 2837 { 2838 TRACE("(%p)->(%p), stub\n", this, pViewMode); 2839 2840 if (!pViewMode) 2841 return E_INVALIDARG; 2842 2843 *pViewMode = m_FolderSettings.ViewMode; 2844 return S_OK; 2845 } 2846 2847 HRESULT STDMETHODCALLTYPE CDefView::SetCurrentViewMode(UINT ViewMode) 2848 { 2849 DWORD dwStyle; 2850 TRACE("(%p)->(%u), stub\n", this, ViewMode); 2851 2852 /* It's not redundant to check FVM_AUTO because it's a (UINT)-1 */ 2853 if (((INT)ViewMode < FVM_FIRST || (INT)ViewMode > FVM_LAST) && ((INT)ViewMode != FVM_AUTO)) 2854 return E_INVALIDARG; 2855 2856 /* Windows before Vista uses LVM_SETVIEW and possibly 2857 LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview, 2858 while later versions seem to accomplish this through other 2859 means. */ 2860 switch (ViewMode) 2861 { 2862 case FVM_ICON: 2863 dwStyle = LVS_ICON; 2864 break; 2865 case FVM_DETAILS: 2866 dwStyle = LVS_REPORT; 2867 break; 2868 case FVM_SMALLICON: 2869 dwStyle = LVS_SMALLICON; 2870 break; 2871 case FVM_LIST: 2872 dwStyle = LVS_LIST; 2873 break; 2874 default: 2875 { 2876 FIXME("ViewMode %d not implemented\n", ViewMode); 2877 dwStyle = LVS_LIST; 2878 break; 2879 } 2880 } 2881 2882 m_ListView.ModifyStyle(LVS_TYPEMASK, dwStyle); 2883 2884 /* This will not necessarily be the actual mode set above. 2885 This mimics the behavior of Windows XP. */ 2886 m_FolderSettings.ViewMode = ViewMode; 2887 2888 return S_OK; 2889 } 2890 2891 HRESULT STDMETHODCALLTYPE CDefView::GetFolder(REFIID riid, void **ppv) 2892 { 2893 if (m_pSFParent == NULL) 2894 return E_FAIL; 2895 2896 return m_pSFParent->QueryInterface(riid, ppv); 2897 } 2898 2899 HRESULT STDMETHODCALLTYPE CDefView::Item(int iItemIndex, PITEMID_CHILD *ppidl) 2900 { 2901 PCUITEMID_CHILD pidl = _PidlByItem(iItemIndex); 2902 if (pidl) 2903 { 2904 *ppidl = ILClone(pidl); 2905 return S_OK; 2906 } 2907 2908 *ppidl = 0; 2909 return E_INVALIDARG; 2910 } 2911 2912 HRESULT STDMETHODCALLTYPE CDefView::ItemCount(UINT uFlags, int *pcItems) 2913 { 2914 TRACE("(%p)->(%u %p)\n", this, uFlags, pcItems); 2915 2916 if (uFlags != SVGIO_ALLVIEW) 2917 FIXME("some flags unsupported, %x\n", uFlags & ~SVGIO_ALLVIEW); 2918 2919 *pcItems = m_ListView.GetItemCount(); 2920 2921 return S_OK; 2922 } 2923 2924 HRESULT STDMETHODCALLTYPE CDefView::Items(UINT uFlags, REFIID riid, void **ppv) 2925 { 2926 return E_NOTIMPL; 2927 } 2928 2929 HRESULT STDMETHODCALLTYPE CDefView::GetSelectionMarkedItem(int *piItem) 2930 { 2931 TRACE("(%p)->(%p)\n", this, piItem); 2932 2933 *piItem = m_ListView.GetSelectionMark(); 2934 2935 return S_OK; 2936 } 2937 2938 HRESULT STDMETHODCALLTYPE CDefView::GetFocusedItem(int *piItem) 2939 { 2940 TRACE("(%p)->(%p)\n", this, piItem); 2941 2942 *piItem = m_ListView.GetNextItem(-1, LVNI_FOCUSED); 2943 2944 return S_OK; 2945 } 2946 2947 HRESULT STDMETHODCALLTYPE CDefView::GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt) 2948 { 2949 if (!m_ListView) 2950 { 2951 ERR("!m_ListView\n"); 2952 return E_FAIL; 2953 } 2954 2955 int lvIndex = LV_FindItemByPidl(pidl); 2956 if (lvIndex == -1 || ppt == NULL) 2957 return E_INVALIDARG; 2958 2959 m_ListView.GetItemPosition(lvIndex, ppt); 2960 return S_OK; 2961 } 2962 2963 HRESULT STDMETHODCALLTYPE CDefView::GetSpacing(POINT *ppt) 2964 { 2965 TRACE("(%p)->(%p)\n", this, ppt); 2966 2967 if (!m_ListView) 2968 { 2969 ERR("!m_ListView\n"); 2970 return S_FALSE; 2971 } 2972 2973 if (ppt) 2974 { 2975 SIZE spacing; 2976 m_ListView.GetItemSpacing(spacing); 2977 2978 ppt->x = spacing.cx; 2979 ppt->y = spacing.cy; 2980 } 2981 2982 return S_OK; 2983 } 2984 2985 HRESULT STDMETHODCALLTYPE CDefView::GetDefaultSpacing(POINT *ppt) 2986 { 2987 return E_NOTIMPL; 2988 } 2989 2990 HRESULT STDMETHODCALLTYPE CDefView::GetAutoArrange() 2991 { 2992 return ((m_ListView.GetStyle() & LVS_AUTOARRANGE) ? S_OK : S_FALSE); 2993 } 2994 2995 HRESULT CDefView::_GetSnapToGrid() 2996 { 2997 DWORD dwExStyle = (DWORD)m_ListView.SendMessage(LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); 2998 return ((dwExStyle & LVS_EX_SNAPTOGRID) ? S_OK : S_FALSE); 2999 } 3000 3001 HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags) 3002 { 3003 LVITEMW lvItem; 3004 3005 TRACE("(%p)->(%d, %x)\n", this, iItem, dwFlags); 3006 3007 lvItem.state = 0; 3008 lvItem.stateMask = LVIS_SELECTED; 3009 3010 if (dwFlags & SVSI_ENSUREVISIBLE) 3011 m_ListView.EnsureVisible(iItem, 0); 3012 3013 /* all items */ 3014 if (dwFlags & SVSI_DESELECTOTHERS) 3015 m_ListView.SetItemState(-1, 0, LVIS_SELECTED); 3016 3017 /* this item */ 3018 if (dwFlags & SVSI_SELECT) 3019 lvItem.state |= LVIS_SELECTED; 3020 3021 if (dwFlags & SVSI_FOCUSED) 3022 lvItem.stateMask |= LVIS_FOCUSED; 3023 3024 m_ListView.SetItemState(iItem, lvItem.state, lvItem.stateMask); 3025 3026 if ((dwFlags & SVSI_EDIT) == SVSI_EDIT) 3027 m_ListView.EditLabel(iItem); 3028 3029 return S_OK; 3030 } 3031 3032 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags) 3033 { 3034 ASSERT(m_ListView); 3035 3036 /* Reset the selection */ 3037 m_ListView.SetItemState(-1, 0, LVIS_SELECTED); 3038 3039 int lvIndex; 3040 for (UINT i = 0 ; i < m_cidl; i++) 3041 { 3042 lvIndex = LV_FindItemByPidl(apidl[i]); 3043 if (lvIndex != -1) 3044 { 3045 SelectItem(lvIndex, dwFlags); 3046 m_ListView.SetItemPosition(lvIndex, &apt[i]); 3047 } 3048 } 3049 3050 return S_OK; 3051 } 3052 3053 /********************************************************** 3054 * IShellView2 implementation 3055 */ 3056 3057 HRESULT STDMETHODCALLTYPE CDefView::GetView(SHELLVIEWID *view_guid, ULONG view_type) 3058 { 3059 FIXME("(%p)->(%p, %lu) stub\n", this, view_guid, view_type); 3060 return E_NOTIMPL; 3061 } 3062 3063 HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow2(LPSV2CVW2_PARAMS view_params) 3064 { 3065 return CreateViewWindow3(view_params->psbOwner, view_params->psvPrev, 3066 SV3CVW3_DEFAULT, (FOLDERFLAGS)view_params->pfs->fFlags, (FOLDERFLAGS)view_params->pfs->fFlags, 3067 (FOLDERVIEWMODE)view_params->pfs->ViewMode, view_params->pvid, view_params->prcView, &view_params->hwndView); 3068 } 3069 3070 HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow3(IShellBrowser *psb, IShellView *psvPrevious, SV3CVW3_FLAGS view_flags, FOLDERFLAGS mask, FOLDERFLAGS flags, FOLDERVIEWMODE mode, const SHELLVIEWID *view_id, RECT *prcView, HWND *hwnd) 3071 { 3072 OLEMENUGROUPWIDTHS omw = { { 0, 0, 0, 0, 0, 0 } }; 3073 3074 *hwnd = NULL; 3075 3076 TRACE("(%p)->(shlview=%p shlbrs=%p rec=%p hwnd=%p vmode=%x flags=%x)\n", this, psvPrevious, psb, prcView, hwnd, mode, flags); 3077 if (prcView != NULL) 3078 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom); 3079 3080 /* Validate the Shell Browser */ 3081 if (psb == NULL || m_hWnd) 3082 return E_UNEXPECTED; 3083 3084 if (view_flags != SV3CVW3_DEFAULT) 3085 FIXME("unsupported view flags 0x%08x\n", view_flags); 3086 3087 /* Set up the member variables */ 3088 m_pShellBrowser = psb; 3089 m_FolderSettings.ViewMode = mode; 3090 m_FolderSettings.fFlags = mask & flags; 3091 3092 if (view_id) 3093 { 3094 if (IsEqualIID(*view_id, VID_LargeIcons)) 3095 m_FolderSettings.ViewMode = FVM_ICON; 3096 else if (IsEqualIID(*view_id, VID_SmallIcons)) 3097 m_FolderSettings.ViewMode = FVM_SMALLICON; 3098 else if (IsEqualIID(*view_id, VID_List)) 3099 m_FolderSettings.ViewMode = FVM_LIST; 3100 else if (IsEqualIID(*view_id, VID_Details)) 3101 m_FolderSettings.ViewMode = FVM_DETAILS; 3102 else if (IsEqualIID(*view_id, VID_Thumbnails)) 3103 m_FolderSettings.ViewMode = FVM_THUMBNAIL; 3104 else if (IsEqualIID(*view_id, VID_Tile)) 3105 m_FolderSettings.ViewMode = FVM_TILE; 3106 else if (IsEqualIID(*view_id, VID_ThumbStrip)) 3107 m_FolderSettings.ViewMode = FVM_THUMBSTRIP; 3108 else 3109 FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_id)); 3110 } 3111 3112 /* Get our parent window */ 3113 m_pShellBrowser->GetWindow(&m_hWndParent); 3114 3115 /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */ 3116 m_pCommDlgBrowser = NULL; 3117 if (SUCCEEDED(m_pShellBrowser->QueryInterface(IID_PPV_ARG(ICommDlgBrowser, &m_pCommDlgBrowser)))) 3118 { 3119 TRACE("-- CommDlgBrowser\n"); 3120 } 3121 3122 Create(m_hWndParent, prcView, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP, 0, 0U); 3123 if (m_hWnd == NULL) 3124 return E_FAIL; 3125 3126 *hwnd = m_hWnd; 3127 3128 CheckToolbar(); 3129 3130 if (!*hwnd) 3131 return E_FAIL; 3132 3133 _DoFolderViewCB(SFVM_WINDOWCREATED, (WPARAM)m_hWnd, 0); 3134 3135 SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); 3136 UpdateWindow(); 3137 3138 if (!m_hMenu) 3139 { 3140 m_hMenu = CreateMenu(); 3141 m_pShellBrowser->InsertMenusSB(m_hMenu, &omw); 3142 TRACE("-- after fnInsertMenusSB\n"); 3143 } 3144 3145 _MergeToolbar(); 3146 3147 return S_OK; 3148 } 3149 3150 HRESULT STDMETHODCALLTYPE CDefView::HandleRename(LPCITEMIDLIST new_pidl) 3151 { 3152 FIXME("(%p)->(%p) stub\n", this, new_pidl); 3153 return E_NOTIMPL; 3154 } 3155 3156 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point) 3157 { 3158 FIXME("(%p)->(%p, %u, %p) stub\n", this, item, flags, point); 3159 return E_NOTIMPL; 3160 } 3161 3162 /********************************************************** 3163 * IShellFolderView implementation 3164 */ 3165 HRESULT STDMETHODCALLTYPE CDefView::Rearrange(LPARAM sort) 3166 { 3167 FIXME("(%p)->(%ld) stub\n", this, sort); 3168 return E_NOTIMPL; 3169 } 3170 3171 HRESULT STDMETHODCALLTYPE CDefView::GetArrangeParam(LPARAM *sort) 3172 { 3173 FIXME("(%p)->(%p) stub\n", this, sort); 3174 return E_NOTIMPL; 3175 } 3176 3177 HRESULT STDMETHODCALLTYPE CDefView::ArrangeGrid() 3178 { 3179 m_ListView.SetExtendedListViewStyle(LVS_EX_SNAPTOGRID, LVS_EX_SNAPTOGRID); 3180 return S_OK; 3181 } 3182 3183 HRESULT STDMETHODCALLTYPE CDefView::AutoArrange() 3184 { 3185 m_ListView.ModifyStyle(0, LVS_AUTOARRANGE); 3186 m_ListView.Arrange(LVA_DEFAULT); 3187 return S_OK; 3188 } 3189 3190 HRESULT STDMETHODCALLTYPE CDefView::AddObject(PITEMID_CHILD pidl, UINT *item) 3191 { 3192 TRACE("(%p)->(%p %p)\n", this, pidl, item); 3193 if (!m_ListView) 3194 { 3195 ERR("!m_ListView\n"); 3196 return E_FAIL; 3197 } 3198 *item = LV_AddItem(pidl); 3199 return (int)*item >= 0 ? S_OK : E_OUTOFMEMORY; 3200 } 3201 3202 HRESULT STDMETHODCALLTYPE CDefView::GetObject(PITEMID_CHILD *pidl, UINT item) 3203 { 3204 TRACE("(%p)->(%p %d)\n", this, pidl, item); 3205 return Item(item, pidl); 3206 } 3207 3208 HRESULT STDMETHODCALLTYPE CDefView::RemoveObject(PITEMID_CHILD pidl, UINT *item) 3209 { 3210 TRACE("(%p)->(%p %p)\n", this, pidl, item); 3211 3212 if (!m_ListView) 3213 { 3214 ERR("!m_ListView\n"); 3215 return E_FAIL; 3216 } 3217 3218 if (pidl) 3219 { 3220 *item = LV_FindItemByPidl(ILFindLastID(pidl)); 3221 m_ListView.DeleteItem(*item); 3222 } 3223 else 3224 { 3225 *item = 0; 3226 m_ListView.DeleteAllItems(); 3227 } 3228 3229 return S_OK; 3230 } 3231 3232 HRESULT STDMETHODCALLTYPE CDefView::GetObjectCount(UINT *count) 3233 { 3234 TRACE("(%p)->(%p)\n", this, count); 3235 *count = m_ListView.GetItemCount(); 3236 return S_OK; 3237 } 3238 3239 HRESULT STDMETHODCALLTYPE CDefView::SetObjectCount(UINT count, UINT flags) 3240 { 3241 FIXME("(%p)->(%d %x) stub\n", this, count, flags); 3242 return E_NOTIMPL; 3243 } 3244 3245 HRESULT STDMETHODCALLTYPE CDefView::UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item) 3246 { 3247 FIXME("(%p)->(%p %p %p) stub\n", this, pidl_old, pidl_new, item); 3248 return E_NOTIMPL; 3249 } 3250 3251 HRESULT STDMETHODCALLTYPE CDefView::RefreshObject(PITEMID_CHILD pidl, UINT *item) 3252 { 3253 FIXME("(%p)->(%p %p) stub\n", this, pidl, item); 3254 return E_NOTIMPL; 3255 } 3256 3257 HRESULT STDMETHODCALLTYPE CDefView::SetRedraw(BOOL redraw) 3258 { 3259 TRACE("(%p)->(%d)\n", this, redraw); 3260 if (m_ListView) 3261 m_ListView.SetRedraw(redraw); 3262 return S_OK; 3263 } 3264 3265 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedCount(UINT *count) 3266 { 3267 FIXME("(%p)->(%p) stub\n", this, count); 3268 return E_NOTIMPL; 3269 } 3270 3271 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items) 3272 { 3273 TRACE("(%p)->(%p %p)\n", this, pidl, items); 3274 3275 *items = GetSelections(); 3276 3277 if (*items) 3278 { 3279 *pidl = static_cast<PCUITEMID_CHILD *>(LocalAlloc(0, *items * sizeof(PCUITEMID_CHILD))); 3280 if (!*pidl) 3281 { 3282 return E_OUTOFMEMORY; 3283 } 3284 3285 /* it's documented that caller shouldn't PIDLs, only array itself */ 3286 memcpy(*pidl, m_apidl, *items * sizeof(PCUITEMID_CHILD)); 3287 } 3288 3289 return S_OK; 3290 } 3291 3292 HRESULT STDMETHODCALLTYPE CDefView::IsDropOnSource(IDropTarget *drop_target) 3293 { 3294 if ((m_iDragOverItem == -1 || m_pCurDropTarget == NULL) && 3295 (m_pSourceDataObject.p)) 3296 { 3297 return S_OK; 3298 } 3299 3300 return S_FALSE; 3301 } 3302 3303 HRESULT STDMETHODCALLTYPE CDefView::GetDragPoint(POINT *pt) 3304 { 3305 if (!pt) 3306 return E_INVALIDARG; 3307 3308 *pt = m_ptFirstMousePos; 3309 return S_OK; 3310 } 3311 3312 HRESULT STDMETHODCALLTYPE CDefView::GetDropPoint(POINT *pt) 3313 { 3314 FIXME("(%p)->(%p) stub\n", this, pt); 3315 return E_NOTIMPL; 3316 } 3317 3318 HRESULT STDMETHODCALLTYPE CDefView::MoveIcons(IDataObject *obj) 3319 { 3320 TRACE("(%p)->(%p)\n", this, obj); 3321 return E_NOTIMPL; 3322 } 3323 3324 HRESULT STDMETHODCALLTYPE CDefView::SetItemPos(PCUITEMID_CHILD pidl, POINT *pt) 3325 { 3326 FIXME("(%p)->(%p %p) stub\n", this, pidl, pt); 3327 return E_NOTIMPL; 3328 } 3329 3330 HRESULT STDMETHODCALLTYPE CDefView::IsBkDropTarget(IDropTarget *drop_target) 3331 { 3332 FIXME("(%p)->(%p) stub\n", this, drop_target); 3333 return E_NOTIMPL; 3334 } 3335 3336 HRESULT STDMETHODCALLTYPE CDefView::SetClipboard(BOOL move) 3337 { 3338 FIXME("(%p)->(%d) stub\n", this, move); 3339 return E_NOTIMPL; 3340 } 3341 3342 HRESULT STDMETHODCALLTYPE CDefView::SetPoints(IDataObject *obj) 3343 { 3344 FIXME("(%p)->(%p) stub\n", this, obj); 3345 return E_NOTIMPL; 3346 } 3347 3348 HRESULT STDMETHODCALLTYPE CDefView::GetItemSpacing(ITEMSPACING *spacing) 3349 { 3350 FIXME("(%p)->(%p) stub\n", this, spacing); 3351 return E_NOTIMPL; 3352 } 3353 3354 HRESULT STDMETHODCALLTYPE CDefView::SetCallback(IShellFolderViewCB *new_cb, IShellFolderViewCB **old_cb) 3355 { 3356 if (old_cb) 3357 *old_cb = m_pShellFolderViewCB.Detach(); 3358 3359 m_pShellFolderViewCB = new_cb; 3360 return S_OK; 3361 } 3362 3363 HRESULT STDMETHODCALLTYPE CDefView::Select(UINT flags) 3364 { 3365 FIXME("(%p)->(%d) stub\n", this, flags); 3366 return E_NOTIMPL; 3367 } 3368 3369 HRESULT STDMETHODCALLTYPE CDefView::QuerySupport(UINT *support) 3370 { 3371 TRACE("(%p)->(%p)\n", this, support); 3372 return S_OK; 3373 } 3374 3375 HRESULT STDMETHODCALLTYPE CDefView::SetAutomationObject(IDispatch *disp) 3376 { 3377 FIXME("(%p)->(%p) stub\n", this, disp); 3378 return E_NOTIMPL; 3379 } 3380 3381 /********************************************************** 3382 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget) 3383 */ 3384 HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText) 3385 { 3386 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n", 3387 this, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText); 3388 3389 if (!prgCmds) 3390 return E_INVALIDARG; 3391 3392 for (UINT i = 0; i < cCmds; i++) 3393 { 3394 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID); 3395 prgCmds[i].cmdf = 0; 3396 } 3397 3398 return OLECMDERR_E_UNKNOWNGROUP; 3399 } 3400 3401 /********************************************************** 3402 * ISVOleCmdTarget_Exec (IOleCommandTarget) 3403 * 3404 * nCmdID is the OLECMDID_* enumeration 3405 */ 3406 HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 3407 { 3408 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n", 3409 this, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut); 3410 3411 if (!pguidCmdGroup) 3412 return OLECMDERR_E_UNKNOWNGROUP; 3413 3414 if (IsEqualCLSID(*pguidCmdGroup, m_Category)) 3415 { 3416 if (nCmdID == FCIDM_SHVIEW_AUTOARRANGE) 3417 { 3418 if (V_VT(pvaIn) != VT_INT_PTR) 3419 return OLECMDERR_E_NOTSUPPORTED; 3420 3421 TPMPARAMS params; 3422 params.cbSize = sizeof(params); 3423 params.rcExclude = *(RECT*) V_INTREF(pvaIn); 3424 3425 if (m_hMenuViewModes) 3426 { 3427 /* Duplicate all but the last two items of the view modes menu */ 3428 HMENU hmenuViewPopup = CreatePopupMenu(); 3429 Shell_MergeMenus(hmenuViewPopup, m_hMenuViewModes, 0, 0, 0xFFFF, 0); 3430 DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION); 3431 DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION); 3432 CheckViewMode(hmenuViewPopup); 3433 TrackPopupMenuEx(hmenuViewPopup, TPM_LEFTALIGN | TPM_TOPALIGN, params.rcExclude.left, params.rcExclude.bottom, m_hWndParent, ¶ms); 3434 ::DestroyMenu(hmenuViewPopup); 3435 } 3436 3437 // pvaOut is VT_I4 with value 0x403 (cmd id of the new mode maybe?) 3438 V_VT(pvaOut) = VT_I4; 3439 V_I4(pvaOut) = 0x403; 3440 } 3441 } 3442 3443 if (IsEqualIID(*pguidCmdGroup, CGID_Explorer) && 3444 (nCmdID == 0x29) && 3445 (nCmdexecopt == 4) && pvaOut) 3446 return S_OK; 3447 3448 if (IsEqualIID(*pguidCmdGroup, CGID_ShellDocView) && 3449 (nCmdID == 9) && 3450 (nCmdexecopt == 0)) 3451 return 1; 3452 3453 return OLECMDERR_E_UNKNOWNGROUP; 3454 } 3455 3456 /********************************************************** 3457 * ISVDropTarget implementation 3458 */ 3459 3460 /****************************************************************************** 3461 * drag_notify_subitem [Internal] 3462 * 3463 * Figure out the shellfolder object, which is currently under the mouse cursor 3464 * and notify it via the IDropTarget interface. 3465 */ 3466 3467 #define SCROLLAREAWIDTH 20 3468 3469 HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 3470 { 3471 LONG lResult; 3472 HRESULT hr; 3473 RECT clientRect; 3474 3475 /* The key state on drop doesn't have MK_LBUTTON or MK_RBUTTON because it 3476 reflects the key state after the user released the button, so we need 3477 to remember the last key state when the button was pressed */ 3478 m_grfKeyState = grfKeyState; 3479 3480 /* Map from global to client coordinates and query the index of the listview-item, which is 3481 * currently under the mouse cursor. */ 3482 LVHITTESTINFO htinfo = {{pt.x, pt.y}, LVHT_ONITEM}; 3483 ScreenToClient(&htinfo.pt); 3484 lResult = m_ListView.HitTest(&htinfo); 3485 3486 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */ 3487 ::GetClientRect(m_ListView, &clientRect); 3488 if (htinfo.pt.x == m_ptLastMousePos.x && htinfo.pt.y == m_ptLastMousePos.y && 3489 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH || 3490 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH )) 3491 { 3492 m_cScrollDelay = (m_cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */ 3493 if (m_cScrollDelay == 0) 3494 { 3495 /* Mouse did hover another 250 ms over the scroll-area */ 3496 if (htinfo.pt.x < SCROLLAREAWIDTH) 3497 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEUP, 0); 3498 3499 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH) 3500 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEDOWN, 0); 3501 3502 if (htinfo.pt.y < SCROLLAREAWIDTH) 3503 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEUP, 0); 3504 3505 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH) 3506 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEDOWN, 0); 3507 } 3508 } 3509 else 3510 { 3511 m_cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */ 3512 } 3513 3514 m_ptLastMousePos = htinfo.pt; 3515 ::ClientToListView(m_ListView, &m_ptLastMousePos); 3516 3517 /* We need to check if we drag the selection over itself */ 3518 if (lResult != -1 && m_pSourceDataObject.p != NULL) 3519 { 3520 PCUITEMID_CHILD pidl = _PidlByItem(lResult); 3521 3522 for (UINT i = 0; i < m_cidl; i++) 3523 { 3524 if (pidl == m_apidl[i]) 3525 { 3526 /* The item that is being draged is hovering itself. */ 3527 lResult = -1; 3528 break; 3529 } 3530 } 3531 } 3532 3533 /* If we are still over the previous sub-item, notify it via DragOver and return. */ 3534 if (m_pCurDropTarget && lResult == m_iDragOverItem) 3535 return m_pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect); 3536 3537 /* We've left the previous sub-item, notify it via DragLeave and Release it. */ 3538 if (m_pCurDropTarget) 3539 { 3540 PCUITEMID_CHILD pidl = _PidlByItem(m_iDragOverItem); 3541 if (pidl) 3542 SelectItem(pidl, 0); 3543 3544 m_pCurDropTarget->DragLeave(); 3545 m_pCurDropTarget.Release(); 3546 } 3547 3548 m_iDragOverItem = lResult; 3549 3550 if (lResult == -1) 3551 { 3552 /* We are not above one of the listview's subitems. Bind to the parent folder's 3553 * DropTarget interface. */ 3554 hr = m_pSFParent->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget,&m_pCurDropTarget)); 3555 } 3556 else 3557 { 3558 /* Query the relative PIDL of the shellfolder object represented by the currently 3559 * dragged over listview-item ... */ 3560 PCUITEMID_CHILD pidl = _PidlByItem(lResult); 3561 3562 /* ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object */ 3563 hr = m_pSFParent->GetUIObjectOf(m_ListView, 1, &pidl, IID_NULL_PPV_ARG(IDropTarget, &m_pCurDropTarget)); 3564 } 3565 3566 IUnknown_SetSite(m_pCurDropTarget, (IShellView *)this); 3567 3568 /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */ 3569 if (FAILED(hr)) 3570 { 3571 *pdwEffect = DROPEFFECT_NONE; 3572 return hr; 3573 } 3574 3575 if (m_iDragOverItem != -1) 3576 { 3577 SelectItem(m_iDragOverItem, SVSI_SELECT); 3578 } 3579 3580 /* Notify the item just entered via DragEnter. */ 3581 return m_pCurDropTarget->DragEnter(m_pCurDataObject, grfKeyState, pt, pdwEffect); 3582 } 3583 3584 HRESULT WINAPI CDefView::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 3585 { 3586 if (*pdwEffect == DROPEFFECT_NONE) 3587 return S_OK; 3588 3589 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */ 3590 m_pCurDataObject = pDataObject; 3591 3592 HRESULT hr = drag_notify_subitem(grfKeyState, pt, pdwEffect); 3593 if (SUCCEEDED(hr)) 3594 { 3595 POINT ptClient = {pt.x, pt.y}; 3596 ScreenToClient(&ptClient); 3597 ImageList_DragEnter(m_hWnd, ptClient.x, ptClient.y); 3598 } 3599 3600 return hr; 3601 } 3602 3603 HRESULT WINAPI CDefView::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 3604 { 3605 POINT ptClient = {pt.x, pt.y}; 3606 ScreenToClient(&ptClient); 3607 ImageList_DragMove(ptClient.x, ptClient.y); 3608 return drag_notify_subitem(grfKeyState, pt, pdwEffect); 3609 } 3610 3611 HRESULT WINAPI CDefView::DragLeave() 3612 { 3613 ImageList_DragLeave(m_hWnd); 3614 3615 if (m_pCurDropTarget) 3616 { 3617 m_pCurDropTarget->DragLeave(); 3618 m_pCurDropTarget.Release(); 3619 } 3620 3621 if (m_pCurDataObject != NULL) 3622 { 3623 m_pCurDataObject.Release(); 3624 } 3625 3626 m_iDragOverItem = 0; 3627 3628 return S_OK; 3629 } 3630 3631 INT CDefView::_FindInsertableIndexFromPoint(POINT pt) 3632 { 3633 RECT rcBound; 3634 INT i, nCount = m_ListView.GetItemCount(); 3635 DWORD dwSpacing; 3636 INT dx, dy; 3637 BOOL bSmall = ((m_ListView.GetStyle() & LVS_TYPEMASK) != LVS_ICON); 3638 3639 /* FIXME: LVM_GETORIGIN is broken. See CORE-17266 */ 3640 pt.x += m_ListView.GetScrollPos(SB_HORZ); 3641 pt.y += m_ListView.GetScrollPos(SB_VERT); 3642 3643 if (m_ListView.GetStyle() & LVS_ALIGNLEFT) 3644 { 3645 // vertically 3646 for (i = 0; i < nCount; ++i) 3647 { 3648 dwSpacing = ListView_GetItemSpacing(m_ListView, bSmall); 3649 dx = LOWORD(dwSpacing); 3650 dy = HIWORD(dwSpacing); 3651 ListView_GetItemRect(m_ListView, i, &rcBound, LVIR_SELECTBOUNDS); 3652 rcBound.right = rcBound.left + dx; 3653 rcBound.bottom = rcBound.top + dy; 3654 if (pt.x < rcBound.right && pt.y < (rcBound.top + rcBound.bottom) / 2) 3655 { 3656 return i; 3657 } 3658 } 3659 for (i = nCount - 1; i >= 0; --i) 3660 { 3661 ListView_GetItemRect(m_ListView, i, &rcBound, LVIR_SELECTBOUNDS); 3662 if (rcBound.left < pt.x && rcBound.top < pt.y) 3663 { 3664 return i + 1; 3665 } 3666 } 3667 } 3668 else 3669 { 3670 // horizontally 3671 for (i = 0; i < nCount; ++i) 3672 { 3673 dwSpacing = ListView_GetItemSpacing(m_ListView, bSmall); 3674 dx = LOWORD(dwSpacing); 3675 dy = HIWORD(dwSpacing); 3676 ListView_GetItemRect(m_ListView, i, &rcBound, LVIR_SELECTBOUNDS); 3677 rcBound.right = rcBound.left + dx; 3678 rcBound.bottom = rcBound.top + dy; 3679 if (pt.y < rcBound.bottom && pt.x < rcBound.left) 3680 { 3681 return i; 3682 } 3683 if (pt.y < rcBound.bottom && pt.x < rcBound.right) 3684 { 3685 return i + 1; 3686 } 3687 } 3688 for (i = nCount - 1; i >= 0; --i) 3689 { 3690 ListView_GetItemRect(m_ListView, i, &rcBound, LVIR_SELECTBOUNDS); 3691 if (rcBound.left < pt.x && rcBound.top < pt.y) 3692 { 3693 return i + 1; 3694 } 3695 } 3696 } 3697 3698 return nCount; 3699 } 3700 3701 void CDefView::_HandleStatusBarResize(int nWidth) 3702 { 3703 LRESULT lResult; 3704 3705 if (m_isParentFolderSpecial) 3706 { 3707 int nPartArray[] = {-1}; 3708 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, _countof(nPartArray), (LPARAM)nPartArray, &lResult); 3709 return; 3710 } 3711 3712 int nFileSizePartLength = 125; 3713 const int nLocationPartLength = 150; 3714 const int nRightPartsLength = nFileSizePartLength + nLocationPartLength; 3715 int nObjectsPartLength = nWidth - nRightPartsLength; 3716 3717 /* If the window is small enough just divide each part into thirds 3718 * This is the behavior of Windows Server 2003. */ 3719 if (nObjectsPartLength <= nLocationPartLength) 3720 nObjectsPartLength = nFileSizePartLength = nWidth / 3; 3721 3722 int nPartArray[] = {nObjectsPartLength, nObjectsPartLength + nFileSizePartLength, -1}; 3723 3724 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, _countof(nPartArray), (LPARAM)nPartArray, &lResult); 3725 } 3726 3727 void CDefView::_ForceStatusBarResize() 3728 { 3729 /* Get the handle for the status bar */ 3730 HWND fStatusBar; 3731 m_pShellBrowser->GetControlWindow(FCW_STATUS, &fStatusBar); 3732 3733 /* Get the size of our status bar */ 3734 RECT statusBarSize; 3735 ::GetWindowRect(fStatusBar, &statusBarSize); 3736 3737 /* Resize the status bar */ 3738 _HandleStatusBarResize(statusBarSize.right - statusBarSize.left); 3739 } 3740 3741 typedef CSimpleMap<LPARAM, INT> CLParamIndexMap; 3742 3743 static INT CALLBACK 3744 SelectionMoveCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) 3745 { 3746 CLParamIndexMap *pmap = (CLParamIndexMap *)lParamSort; 3747 INT i1 = pmap->Lookup(lParam1), i2 = pmap->Lookup(lParam2); 3748 if (i1 < i2) 3749 return -1; 3750 if (i1 > i2) 3751 return 1; 3752 return 0; 3753 } 3754 3755 void CDefView::_MoveSelectionOnAutoArrange(POINT pt) 3756 { 3757 // get insertable index from position 3758 INT iPosition = _FindInsertableIndexFromPoint(pt); 3759 3760 // create identity mapping of indexes 3761 CSimpleArray<INT> array; 3762 INT nCount = m_ListView.GetItemCount(); 3763 for (INT i = 0; i < nCount; ++i) 3764 { 3765 array.Add(i); 3766 } 3767 3768 // re-ordering mapping 3769 INT iItem = -1; 3770 while ((iItem = m_ListView.GetNextItem(iItem, LVNI_SELECTED)) >= 0) 3771 { 3772 INT iFrom = iItem, iTo = iPosition; 3773 if (iFrom < iTo) 3774 --iTo; 3775 if (iFrom >= nCount) 3776 iFrom = nCount - 1; 3777 if (iTo >= nCount) 3778 iTo = nCount - 1; 3779 3780 // shift indexes by swapping (like a bucket relay) 3781 if (iFrom < iTo) 3782 { 3783 for (INT i = iFrom; i < iTo; ++i) 3784 { 3785 // swap array[i] and array[i + 1] 3786 INT tmp = array[i]; 3787 array[i] = array[i + 1]; 3788 array[i + 1] = tmp; 3789 } 3790 } 3791 else 3792 { 3793 for (INT i = iFrom; i > iTo; --i) 3794 { 3795 // swap array[i] and array[i - 1] 3796 INT tmp = array[i]; 3797 array[i] = array[i - 1]; 3798 array[i - 1] = tmp; 3799 } 3800 } 3801 } 3802 3803 // create mapping (ListView's lParam to index) from array 3804 CLParamIndexMap map; 3805 for (INT i = 0; i < nCount; ++i) 3806 { 3807 LPARAM lParam = m_ListView.GetItemData(array[i]); 3808 map.Add(lParam, i); 3809 } 3810 3811 // finally sort 3812 m_ListView.SortItems(SelectionMoveCompareFunc, &map); 3813 } 3814 3815 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 3816 { 3817 ImageList_DragLeave(m_hWnd); 3818 ImageList_EndDrag(); 3819 3820 if ((IsDropOnSource(NULL) == S_OK) && 3821 (*pdwEffect & DROPEFFECT_MOVE) && 3822 (m_grfKeyState & MK_LBUTTON)) 3823 { 3824 if (m_pCurDropTarget) 3825 { 3826 m_pCurDropTarget->DragLeave(); 3827 m_pCurDropTarget.Release(); 3828 } 3829 3830 POINT ptDrop = { pt.x, pt.y }; 3831 ::ScreenToClient(m_ListView, &ptDrop); 3832 ::ClientToListView(m_ListView, &ptDrop); 3833 m_ptLastMousePos = ptDrop; 3834 3835 m_ListView.SetRedraw(FALSE); 3836 if (m_ListView.GetStyle() & LVS_AUTOARRANGE) 3837 { 3838 _MoveSelectionOnAutoArrange(m_ptLastMousePos); 3839 } 3840 else 3841 { 3842 POINT ptItem; 3843 INT iItem = -1; 3844 while ((iItem = m_ListView.GetNextItem(iItem, LVNI_SELECTED)) >= 0) 3845 { 3846 if (m_ListView.GetItemPosition(iItem, &ptItem)) 3847 { 3848 ptItem.x += m_ptLastMousePos.x - m_ptFirstMousePos.x; 3849 ptItem.y += m_ptLastMousePos.y - m_ptFirstMousePos.y; 3850 m_ListView.SetItemPosition(iItem, &ptItem); 3851 } 3852 } 3853 } 3854 m_ListView.SetRedraw(TRUE); 3855 } 3856 else if (m_pCurDropTarget) 3857 { 3858 m_pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect); 3859 m_pCurDropTarget.Release(); 3860 } 3861 3862 m_pCurDataObject.Release(); 3863 m_iDragOverItem = 0; 3864 return S_OK; 3865 } 3866 3867 /********************************************************** 3868 * ISVDropSource implementation 3869 */ 3870 3871 HRESULT WINAPI CDefView::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) 3872 { 3873 TRACE("(%p)\n", this); 3874 3875 if (fEscapePressed) 3876 return DRAGDROP_S_CANCEL; 3877 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON)) 3878 return DRAGDROP_S_DROP; 3879 else 3880 return S_OK; 3881 } 3882 3883 HRESULT WINAPI CDefView::GiveFeedback(DWORD dwEffect) 3884 { 3885 TRACE("(%p)\n", this); 3886 3887 return DRAGDROP_S_USEDEFAULTCURSORS; 3888 } 3889 3890 /********************************************************** 3891 * ISVViewObject implementation 3892 */ 3893 3894 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) 3895 { 3896 FIXME("Stub: this=%p\n", this); 3897 3898 return E_NOTIMPL; 3899 } 3900 3901 HRESULT WINAPI CDefView::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet) 3902 { 3903 FIXME("Stub: this=%p\n", this); 3904 3905 return E_NOTIMPL; 3906 } 3907 3908 HRESULT WINAPI CDefView::Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze) 3909 { 3910 FIXME("Stub: this=%p\n", this); 3911 3912 return E_NOTIMPL; 3913 } 3914 3915 HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze) 3916 { 3917 FIXME("Stub: this=%p\n", this); 3918 3919 return E_NOTIMPL; 3920 } 3921 3922 HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink) 3923 { 3924 FIXME("partial stub: %p 0x%08x 0x%08x %p\n", this, aspects, advf, pAdvSink); 3925 3926 /* FIXME: we set the AdviseSink, but never use it to send any advice */ 3927 m_pAdvSink = pAdvSink; 3928 m_dwAspects = aspects; 3929 m_dwAdvf = advf; 3930 3931 return S_OK; 3932 } 3933 3934 HRESULT WINAPI CDefView::GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink) 3935 { 3936 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects, pAdvf, ppAdvSink); 3937 3938 if (ppAdvSink) 3939 { 3940 *ppAdvSink = m_pAdvSink; 3941 m_pAdvSink.p->AddRef(); 3942 } 3943 3944 if (pAspects) 3945 *pAspects = m_dwAspects; 3946 3947 if (pAdvf) 3948 *pAdvf = m_dwAdvf; 3949 3950 return S_OK; 3951 } 3952 3953 HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) 3954 { 3955 if (IsEqualIID(guidService, SID_IShellBrowser)) 3956 return m_pShellBrowser->QueryInterface(riid, ppvObject); 3957 else if(IsEqualIID(guidService, SID_IFolderView)) 3958 return QueryInterface(riid, ppvObject); 3959 3960 return E_NOINTERFACE; 3961 } 3962 3963 HRESULT CDefView::_MergeToolbar() 3964 { 3965 CComPtr<IExplorerToolbar> ptb; 3966 HRESULT hr = S_OK; 3967 3968 hr = IUnknown_QueryService(m_pShellBrowser, IID_IExplorerToolbar, IID_PPV_ARG(IExplorerToolbar, &ptb)); 3969 if (FAILED(hr)) 3970 return hr; 3971 3972 m_Category = CGID_DefViewFrame; 3973 3974 hr = ptb->SetCommandTarget(static_cast<IOleCommandTarget*>(this), &m_Category, 0); 3975 if (FAILED(hr)) 3976 return hr; 3977 3978 if (hr == S_FALSE) 3979 return S_OK; 3980 3981 #if 0 3982 hr = ptb->AddButtons(&m_Category, buttonsCount, buttons); 3983 if (FAILED(hr)) 3984 return hr; 3985 #endif 3986 3987 return S_OK; 3988 } 3989 3990 HRESULT CDefView::_DoFolderViewCB(UINT uMsg, WPARAM wParam, LPARAM lParam) 3991 { 3992 HRESULT hr = E_NOTIMPL; 3993 3994 if (m_pShellFolderViewCB) 3995 { 3996 hr = m_pShellFolderViewCB->MessageSFVCB(uMsg, wParam, lParam); 3997 } 3998 3999 return hr; 4000 } 4001 4002 HRESULT CDefView_CreateInstance(IShellFolder *pFolder, REFIID riid, LPVOID * ppvOut) 4003 { 4004 return ShellObjectCreatorInit<CDefView>(pFolder, riid, ppvOut); 4005 } 4006 4007 HRESULT WINAPI SHCreateShellFolderViewEx( 4008 LPCSFV psvcbi, /* [in] shelltemplate struct */ 4009 IShellView **ppsv) /* [out] IShellView pointer */ 4010 { 4011 CComPtr<IShellView> psv; 4012 HRESULT hRes; 4013 4014 TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n", 4015 psvcbi->pshf, psvcbi->pidl, psvcbi->pfnCallback, 4016 psvcbi->fvm, psvcbi->psvOuter); 4017 4018 *ppsv = NULL; 4019 hRes = CDefView_CreateInstance(psvcbi->pshf, IID_PPV_ARG(IShellView, &psv)); 4020 if (FAILED_UNEXPECTEDLY(hRes)) 4021 return hRes; 4022 4023 *ppsv = psv.Detach(); 4024 return hRes; 4025 } 4026 4027 HRESULT WINAPI SHCreateShellFolderView(const SFV_CREATE *pcsfv, 4028 IShellView **ppsv) 4029 { 4030 CComPtr<IShellView> psv; 4031 HRESULT hRes; 4032 4033 if (!ppsv) 4034 return E_INVALIDARG; 4035 4036 *ppsv = NULL; 4037 4038 if (!pcsfv || pcsfv->cbSize != sizeof(*pcsfv)) 4039 return E_INVALIDARG; 4040 4041 TRACE("sf=%p outer=%p callback=%p\n", 4042 pcsfv->pshf, pcsfv->psvOuter, pcsfv->psfvcb); 4043 4044 hRes = CDefView_CreateInstance(pcsfv->pshf, IID_PPV_ARG(IShellView, &psv)); 4045 if (FAILED(hRes)) 4046 return hRes; 4047 4048 if (pcsfv->psfvcb) 4049 { 4050 CComPtr<IShellFolderView> sfv; 4051 if (SUCCEEDED(psv->QueryInterface(IID_PPV_ARG(IShellFolderView, &sfv)))) 4052 { 4053 sfv->SetCallback(pcsfv->psfvcb, NULL); 4054 } 4055 } 4056 4057 *ppsv = psv.Detach(); 4058 return hRes; 4059 } 4060