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