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; 1577 1578 hMenu = CreatePopupMenu(); 1579 if (!hMenu) 1580 return 0; 1581 1582 hResult = GetItemObject( bUseSelection ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM)); 1583 if (FAILED_UNEXPECTEDLY( hResult)) 1584 goto cleanup; 1585 1586 hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL); 1587 if (FAILED_UNEXPECTEDLY( hResult)) 1588 goto cleanup; 1589 1590 if (bUseSelection) 1591 { 1592 // FIXME: we should cache this.... 1593 SFGAOF rfg = SFGAO_BROWSABLE | SFGAO_CANCOPY | SFGAO_CANLINK | SFGAO_CANMOVE | SFGAO_CANDELETE | SFGAO_CANRENAME | SFGAO_HASPROPSHEET | SFGAO_FILESYSTEM | SFGAO_FOLDER; 1594 hResult = m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &rfg); 1595 if (FAILED_UNEXPECTEDLY(hResult)) 1596 return 0; 1597 1598 if (!(rfg & SFGAO_CANMOVE) && uCommand == FCIDM_SHVIEW_CUT) 1599 return 0; 1600 if (!(rfg & SFGAO_CANCOPY) && uCommand == FCIDM_SHVIEW_COPY) 1601 return 0; 1602 if (!(rfg & SFGAO_CANDELETE) && uCommand == FCIDM_SHVIEW_DELETE) 1603 return 0; 1604 if (!(rfg & SFGAO_CANRENAME) && uCommand == FCIDM_SHVIEW_RENAME) 1605 return 0; 1606 if (!(rfg & SFGAO_HASPROPSHEET) && uCommand == FCIDM_SHVIEW_PROPERTIES) 1607 return 0; 1608 } 1609 1610 InvokeContextMenuCommand(uCommand); 1611 1612 cleanup: 1613 if (m_pCM) 1614 { 1615 IUnknown_SetSite(m_pCM, NULL); 1616 m_pCM.Release(); 1617 } 1618 1619 if (hMenu) 1620 DestroyMenu(hMenu); 1621 1622 return 0; 1623 } 1624 1625 /********************************************************** 1626 * ##### message handling ##### 1627 */ 1628 1629 /********************************************************** 1630 * ShellView_OnSize() 1631 */ 1632 LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1633 { 1634 WORD wWidth, wHeight; 1635 1636 wWidth = LOWORD(lParam); 1637 wHeight = HIWORD(lParam); 1638 1639 TRACE("%p width=%u height=%u\n", this, wWidth, wHeight); 1640 1641 /* Resize the ListView to fit our window */ 1642 if (m_ListView) 1643 { 1644 ::MoveWindow(m_ListView, 0, 0, wWidth, wHeight, TRUE); 1645 } 1646 1647 _DoFolderViewCB(SFVM_SIZE, 0, 0); 1648 1649 return 0; 1650 } 1651 1652 /********************************************************** 1653 * ShellView_OnDeactivate() 1654 * 1655 * NOTES 1656 * internal 1657 */ 1658 void CDefView::OnDeactivate() 1659 { 1660 TRACE("%p\n", this); 1661 1662 if (m_uState != SVUIA_DEACTIVATE) 1663 { 1664 // TODO: cleanup menu after deactivation 1665 1666 m_uState = SVUIA_DEACTIVATE; 1667 } 1668 } 1669 1670 void CDefView::DoActivate(UINT uState) 1671 { 1672 TRACE("%p uState=%x\n", this, uState); 1673 1674 /*don't do anything if the state isn't really changing */ 1675 if (m_uState == uState) 1676 { 1677 return; 1678 } 1679 1680 if (uState == SVUIA_DEACTIVATE) 1681 { 1682 OnDeactivate(); 1683 } 1684 else 1685 { 1686 if(m_hMenu && !m_bmenuBarInitialized) 1687 { 1688 FillEditMenu(); 1689 FillViewMenu(); 1690 m_pShellBrowser->SetMenuSB(m_hMenu, 0, m_hWnd); 1691 m_bmenuBarInitialized = TRUE; 1692 } 1693 1694 if (SVUIA_ACTIVATE_FOCUS == uState) 1695 { 1696 m_ListView.SetFocus(); 1697 } 1698 } 1699 1700 m_uState = uState; 1701 TRACE("--\n"); 1702 } 1703 1704 /********************************************************** 1705 * ShellView_OnActivate() 1706 */ 1707 LRESULT CDefView::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1708 { 1709 DoActivate(SVUIA_ACTIVATE_FOCUS); 1710 return 0; 1711 } 1712 1713 /********************************************************** 1714 * ShellView_OnSetFocus() 1715 * 1716 */ 1717 LRESULT CDefView::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1718 { 1719 TRACE("%p\n", this); 1720 1721 /* Tell the browser one of our windows has received the focus. This 1722 should always be done before merging menus (OnActivate merges the 1723 menus) if one of our windows has the focus.*/ 1724 1725 m_pShellBrowser->OnViewWindowActive(this); 1726 DoActivate(SVUIA_ACTIVATE_FOCUS); 1727 1728 /* Set the focus to the listview */ 1729 m_ListView.SetFocus(); 1730 1731 /* Notify the ICommDlgBrowser interface */ 1732 OnStateChange(CDBOSC_SETFOCUS); 1733 1734 return 0; 1735 } 1736 1737 /********************************************************** 1738 * ShellView_OnKillFocus() 1739 */ 1740 LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1741 { 1742 TRACE("(%p) stub\n", this); 1743 1744 DoActivate(SVUIA_ACTIVATE_NOFOCUS); 1745 /* Notify the ICommDlgBrowser */ 1746 OnStateChange(CDBOSC_KILLFOCUS); 1747 1748 return 0; 1749 } 1750 1751 /********************************************************** 1752 * ShellView_OnCommand() 1753 * 1754 * NOTES 1755 * the CmdID's are the ones from the context menu 1756 */ 1757 LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1758 { 1759 DWORD dwCmdID; 1760 DWORD dwCmd; 1761 HWND hwndCmd; 1762 int nCount; 1763 1764 dwCmdID = GET_WM_COMMAND_ID(wParam, lParam); 1765 dwCmd = GET_WM_COMMAND_CMD(wParam, lParam); 1766 hwndCmd = GET_WM_COMMAND_HWND(wParam, lParam); 1767 1768 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n", this, dwCmdID, dwCmd, hwndCmd); 1769 1770 switch (dwCmdID) 1771 { 1772 case FCIDM_SHVIEW_SMALLICON: 1773 m_FolderSettings.ViewMode = FVM_SMALLICON; 1774 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON); 1775 CheckToolbar(); 1776 break; 1777 1778 case FCIDM_SHVIEW_BIGICON: 1779 m_FolderSettings.ViewMode = FVM_ICON; 1780 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_ICON); 1781 CheckToolbar(); 1782 break; 1783 1784 case FCIDM_SHVIEW_LISTVIEW: 1785 m_FolderSettings.ViewMode = FVM_LIST; 1786 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_LIST); 1787 CheckToolbar(); 1788 break; 1789 1790 case FCIDM_SHVIEW_REPORTVIEW: 1791 m_FolderSettings.ViewMode = FVM_DETAILS; 1792 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_REPORT); 1793 CheckToolbar(); 1794 break; 1795 1796 /* the menu-ID's for sorting are 0x30... see shrec.rc */ 1797 case 0x30: 1798 case 0x31: 1799 case 0x32: 1800 case 0x33: 1801 m_sortInfo.nHeaderID = dwCmdID - 0x30; 1802 m_sortInfo.bIsAscending = TRUE; 1803 _Sort(); 1804 break; 1805 1806 case FCIDM_SHVIEW_SNAPTOGRID: 1807 m_ListView.Arrange(LVA_SNAPTOGRID); 1808 break; 1809 case FCIDM_SHVIEW_ALIGNTOGRID: 1810 if (_GetSnapToGrid() == S_OK) 1811 m_ListView.SetExtendedListViewStyle(0, LVS_EX_SNAPTOGRID); 1812 else 1813 ArrangeGrid(); 1814 break; 1815 case FCIDM_SHVIEW_AUTOARRANGE: 1816 if (GetAutoArrange() == S_OK) 1817 m_ListView.ModifyStyle(LVS_AUTOARRANGE, 0); 1818 else 1819 AutoArrange(); 1820 break; 1821 case FCIDM_SHVIEW_SELECTALL: 1822 m_ListView.SetItemState(-1, LVIS_SELECTED, LVIS_SELECTED); 1823 break; 1824 1825 case FCIDM_SHVIEW_INVERTSELECTION: 1826 nCount = m_ListView.GetItemCount(); 1827 for (int i=0; i < nCount; i++) 1828 m_ListView.SetItemState(i, m_ListView.GetItemState(i, LVIS_SELECTED) ? 0 : LVIS_SELECTED, LVIS_SELECTED); 1829 break; 1830 1831 case FCIDM_SHVIEW_REFRESH: 1832 Refresh(); 1833 break; 1834 1835 case FCIDM_SHVIEW_DELETE: 1836 case FCIDM_SHVIEW_CUT: 1837 case FCIDM_SHVIEW_COPY: 1838 case FCIDM_SHVIEW_RENAME: 1839 case FCIDM_SHVIEW_PROPERTIES: 1840 case FCIDM_SHVIEW_COPYTO: 1841 case FCIDM_SHVIEW_MOVETO: 1842 if (SHRestricted(REST_NOVIEWCONTEXTMENU)) 1843 return 0; 1844 1845 return OnExplorerCommand(dwCmdID, TRUE); 1846 1847 case FCIDM_SHVIEW_INSERT: 1848 case FCIDM_SHVIEW_UNDO: 1849 case FCIDM_SHVIEW_INSERTLINK: 1850 case FCIDM_SHVIEW_NEWFOLDER: 1851 return OnExplorerCommand(dwCmdID, FALSE); 1852 default: 1853 /* WM_COMMAND messages from the file menu are routed to the CDefView so as to let m_pCM handle the command */ 1854 if (m_pCM && dwCmd == 0) 1855 { 1856 InvokeContextMenuCommand(dwCmdID); 1857 } 1858 } 1859 1860 return 0; 1861 } 1862 1863 static BOOL 1864 SelectExtOnRename(void) 1865 { 1866 HKEY hKey; 1867 LONG error; 1868 DWORD dwValue = FALSE, cbValue; 1869 1870 error = RegOpenKeyExW(HKEY_CURRENT_USER, 1871 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer", 1872 0, KEY_READ, &hKey); 1873 if (error) 1874 return dwValue; 1875 1876 cbValue = sizeof(dwValue); 1877 RegQueryValueExW(hKey, L"SelectExtOnRename", NULL, NULL, (LPBYTE)&dwValue, &cbValue); 1878 1879 RegCloseKey(hKey); 1880 return !!dwValue; 1881 } 1882 1883 /********************************************************** 1884 * ShellView_OnNotify() 1885 */ 1886 1887 LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1888 { 1889 UINT CtlID; 1890 LPNMHDR lpnmh; 1891 LPNMLISTVIEW lpnmlv; 1892 NMLVDISPINFOW *lpdi; 1893 PCUITEMID_CHILD pidl; 1894 BOOL unused; 1895 1896 CtlID = wParam; 1897 lpnmh = (LPNMHDR)lParam; 1898 lpnmlv = (LPNMLISTVIEW)lpnmh; 1899 lpdi = (NMLVDISPINFOW *)lpnmh; 1900 1901 TRACE("%p CtlID=%u lpnmh->code=%x\n", this, CtlID, lpnmh->code); 1902 1903 switch (lpnmh->code) 1904 { 1905 case NM_SETFOCUS: 1906 TRACE("-- NM_SETFOCUS %p\n", this); 1907 OnSetFocus(0, 0, 0, unused); 1908 break; 1909 1910 case NM_KILLFOCUS: 1911 TRACE("-- NM_KILLFOCUS %p\n", this); 1912 OnDeactivate(); 1913 /* Notify the ICommDlgBrowser interface */ 1914 OnStateChange(CDBOSC_KILLFOCUS); 1915 break; 1916 1917 case NM_CUSTOMDRAW: 1918 TRACE("-- NM_CUSTOMDRAW %p\n", this); 1919 return CDRF_DODEFAULT; 1920 1921 case NM_RELEASEDCAPTURE: 1922 TRACE("-- NM_RELEASEDCAPTURE %p\n", this); 1923 break; 1924 1925 case NM_CLICK: 1926 TRACE("-- NM_CLICK %p\n", this); 1927 break; 1928 1929 case NM_RCLICK: 1930 TRACE("-- NM_RCLICK %p\n", this); 1931 break; 1932 1933 case NM_DBLCLK: 1934 TRACE("-- NM_DBLCLK %p\n", this); 1935 OpenSelectedItems(); 1936 break; 1937 1938 case NM_RETURN: 1939 TRACE("-- NM_RETURN %p\n", this); 1940 OpenSelectedItems(); 1941 break; 1942 1943 case HDN_ENDTRACKW: 1944 TRACE("-- HDN_ENDTRACKW %p\n", this); 1945 /*nColumn1 = m_ListView.GetColumnWidth(0); 1946 nColumn2 = m_ListView.GetColumnWidth(1);*/ 1947 break; 1948 1949 case LVN_DELETEITEM: 1950 TRACE("-- LVN_DELETEITEM %p\n", this); 1951 1952 /*delete the pidl because we made a copy of it*/ 1953 SHFree(reinterpret_cast<LPVOID>(lpnmlv->lParam)); 1954 1955 break; 1956 1957 case LVN_DELETEALLITEMS: 1958 TRACE("-- LVN_DELETEALLITEMS %p\n", this); 1959 return FALSE; 1960 1961 case LVN_INSERTITEM: 1962 TRACE("-- LVN_INSERTITEM (STUB)%p\n", this); 1963 break; 1964 1965 case LVN_ITEMACTIVATE: 1966 TRACE("-- LVN_ITEMACTIVATE %p\n", this); 1967 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */ 1968 break; 1969 1970 case LVN_COLUMNCLICK: 1971 m_sortInfo.nHeaderID = lpnmlv->iSubItem; 1972 if (m_sortInfo.nLastHeaderID == m_sortInfo.nHeaderID) 1973 m_sortInfo.bIsAscending = !m_sortInfo.bIsAscending; 1974 else 1975 m_sortInfo.bIsAscending = TRUE; 1976 _Sort(); 1977 break; 1978 1979 case LVN_GETDISPINFOA: 1980 case LVN_GETDISPINFOW: 1981 TRACE("-- LVN_GETDISPINFO %p\n", this); 1982 pidl = _PidlByItem(lpdi->item); 1983 1984 if (lpdi->item.mask & LVIF_TEXT) /* text requested */ 1985 { 1986 if (m_pSF2Parent) 1987 { 1988 SHELLDETAILS sd; 1989 if (FAILED_UNEXPECTEDLY(m_pSF2Parent->GetDetailsOf(pidl, lpdi->item.iSubItem, &sd))) 1990 break; 1991 1992 if (lpnmh->code == LVN_GETDISPINFOA) 1993 { 1994 /* shouldn't happen */ 1995 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh; 1996 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL); 1997 TRACE("-- text=%s\n", lpdiA->item.pszText); 1998 } 1999 else /* LVN_GETDISPINFOW */ 2000 { 2001 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL); 2002 TRACE("-- text=%s\n", debugstr_w(lpdi->item.pszText)); 2003 } 2004 } 2005 else 2006 { 2007 FIXME("no m_pSF2Parent\n"); 2008 } 2009 } 2010 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */ 2011 { 2012 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0); 2013 } 2014 if(lpdi->item.mask & LVIF_STATE) 2015 { 2016 ULONG attributes = SFGAO_HIDDEN; 2017 if (SUCCEEDED(m_pSFParent->GetAttributesOf(1, &pidl, &attributes))) 2018 { 2019 if (attributes & SFGAO_HIDDEN) 2020 { 2021 lpdi->item.state |= LVIS_CUT; 2022 } 2023 } 2024 } 2025 lpdi->item.mask |= LVIF_DI_SETITEM; 2026 break; 2027 2028 case LVN_ITEMCHANGED: 2029 TRACE("-- LVN_ITEMCHANGED %p\n", this); 2030 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */ 2031 UpdateStatusbar(); 2032 _DoFolderViewCB(SFVM_SELECTIONCHANGED, NULL/* FIXME */, NULL/* FIXME */); 2033 break; 2034 2035 case LVN_BEGINDRAG: 2036 case LVN_BEGINRDRAG: 2037 TRACE("-- LVN_BEGINDRAG\n"); 2038 2039 if (GetSelections()) 2040 { 2041 CComPtr<IDataObject> pda; 2042 DWORD dwAttributes = SFGAO_CANCOPY | SFGAO_CANLINK; 2043 DWORD dwEffect = DROPEFFECT_MOVE; 2044 2045 if (SUCCEEDED(m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IDataObject, &pda)))) 2046 { 2047 LPNMLISTVIEW params = (LPNMLISTVIEW)lParam; 2048 2049 if (SUCCEEDED(m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &dwAttributes))) 2050 { 2051 dwEffect |= dwAttributes & (SFGAO_CANCOPY | SFGAO_CANLINK); 2052 } 2053 2054 CComPtr<IAsyncOperation> piaso; 2055 if (SUCCEEDED(pda->QueryInterface(IID_PPV_ARG(IAsyncOperation, &piaso)))) 2056 { 2057 piaso->SetAsyncMode(TRUE); 2058 } 2059 2060 DWORD dwEffect2; 2061 2062 m_pSourceDataObject = pda; 2063 m_ptFirstMousePos = params->ptAction; 2064 ClientToScreen(&m_ptFirstMousePos); 2065 ::ClientToListView(m_ListView, &m_ptFirstMousePos); 2066 2067 HIMAGELIST big_icons, small_icons; 2068 Shell_GetImageLists(&big_icons, &small_icons); 2069 PCUITEMID_CHILD pidl = _PidlByItem(params->iItem); 2070 int iIcon = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0); 2071 POINT ptItem; 2072 m_ListView.GetItemPosition(params->iItem, &ptItem); 2073 2074 ImageList_BeginDrag(big_icons, iIcon, params->ptAction.x - ptItem.x, params->ptAction.y - ptItem.y); 2075 2076 DoDragDrop(pda, this, dwEffect, &dwEffect2); 2077 2078 m_pSourceDataObject.Release(); 2079 } 2080 } 2081 break; 2082 2083 case LVN_BEGINLABELEDITW: 2084 { 2085 DWORD dwAttr = SFGAO_CANRENAME; 2086 pidl = _PidlByItem(lpdi->item); 2087 2088 TRACE("-- LVN_BEGINLABELEDITW %p\n", this); 2089 2090 m_pSFParent->GetAttributesOf(1, &pidl, &dwAttr); 2091 if (SFGAO_CANRENAME & dwAttr) 2092 { 2093 HWND hEdit = reinterpret_cast<HWND>(m_ListView.SendMessage(LVM_GETEDITCONTROL)); 2094 SHLimitInputEdit(hEdit, m_pSFParent); 2095 2096 if (!(dwAttr & SFGAO_LINK) && (lpdi->item.mask & LVIF_TEXT) && !SelectExtOnRename()) 2097 { 2098 LPWSTR pszText = lpdi->item.pszText; 2099 LPWSTR pchDotExt = PathFindExtensionW(pszText); 2100 ::PostMessageW(hEdit, EM_SETSEL, 0, pchDotExt - pszText); 2101 ::PostMessageW(hEdit, EM_SCROLLCARET, 0, 0); 2102 } 2103 2104 m_isEditing = TRUE; 2105 return FALSE; 2106 } 2107 2108 return TRUE; 2109 } 2110 2111 case LVN_ENDLABELEDITW: 2112 { 2113 TRACE("-- LVN_ENDLABELEDITW %p\n", this); 2114 2115 m_isEditing = FALSE; 2116 2117 if (lpdi->item.pszText) 2118 { 2119 HRESULT hr; 2120 LVITEMW lvItem; 2121 2122 pidl = _PidlByItem(lpdi->item); 2123 PITEMID_CHILD pidlNew = NULL; 2124 hr = m_pSFParent->SetNameOf(0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidlNew); 2125 2126 if (SUCCEEDED(hr) && pidlNew) 2127 { 2128 lvItem.mask = LVIF_PARAM|LVIF_IMAGE; 2129 lvItem.iItem = lpdi->item.iItem; 2130 lvItem.iSubItem = 0; 2131 lvItem.lParam = reinterpret_cast<LPARAM>(pidlNew); 2132 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0); 2133 m_ListView.SetItem(&lvItem); 2134 m_ListView.Update(lpdi->item.iItem); 2135 return TRUE; 2136 } 2137 } 2138 2139 return FALSE; 2140 } 2141 2142 default: 2143 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh->code); 2144 break; 2145 } 2146 2147 return 0; 2148 } 2149 2150 /* 2151 * This is just a quick hack to make the desktop work correctly. 2152 * ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the way that 2153 * a folder should know if it should update upon a change notification. 2154 * It is exported by merged folders at a minimum. 2155 */ 2156 static BOOL ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2) 2157 { 2158 if (!pidl1 || !pidl2) 2159 return FALSE; 2160 if (ILIsParent(pidl1, pidl2, TRUE)) 2161 return TRUE; 2162 2163 if (_ILIsDesktop(pidl1)) 2164 { 2165 PIDLIST_ABSOLUTE deskpidl; 2166 SHGetFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, &deskpidl); 2167 if (ILIsParent(deskpidl, pidl2, TRUE)) 2168 { 2169 ILFree(deskpidl); 2170 return TRUE; 2171 } 2172 ILFree(deskpidl); 2173 SHGetFolderLocation(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, &deskpidl); 2174 if (ILIsParent(deskpidl, pidl2, TRUE)) 2175 { 2176 ILFree(deskpidl); 2177 return TRUE; 2178 } 2179 ILFree(deskpidl); 2180 } 2181 2182 WCHAR szPath1[MAX_PATH], szPath2[MAX_PATH]; 2183 LPITEMIDLIST pidl2Clone = ILClone(pidl2); 2184 ILRemoveLastID(pidl2Clone); 2185 if (SHGetPathFromIDListW(pidl1, szPath1) && 2186 SHGetPathFromIDListW(pidl2Clone, szPath2)) 2187 { 2188 if (lstrcmpiW(szPath1, szPath2) == 0) 2189 { 2190 ILFree(pidl2Clone); 2191 return TRUE; 2192 } 2193 } 2194 ILFree(pidl2Clone); 2195 2196 return FALSE; 2197 } 2198 2199 /********************************************************** 2200 * ShellView_OnChange() 2201 */ 2202 LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 2203 { 2204 HANDLE hChange = (HANDLE)wParam; 2205 DWORD dwProcID = (DWORD)lParam; 2206 PIDLIST_ABSOLUTE *Pidls; 2207 LONG lEvent; 2208 HANDLE hLock = SHChangeNotification_Lock(hChange, dwProcID, &Pidls, &lEvent); 2209 if (hLock == NULL) 2210 { 2211 ERR("hLock == NULL\n"); 2212 return FALSE; 2213 } 2214 2215 BOOL bParent0 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[0]); 2216 BOOL bParent1 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[1]); 2217 2218 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam); 2219 2220 lEvent &= ~SHCNE_INTERRUPT; 2221 switch (lEvent) 2222 { 2223 case SHCNE_MKDIR: 2224 case SHCNE_CREATE: 2225 if (bParent0) 2226 { 2227 if (LV_FindItemByPidl(ILFindLastID(Pidls[0])) == -1) 2228 { 2229 LV_AddItem(ILFindLastID(Pidls[0])); 2230 } 2231 else 2232 { 2233 LV_ProdItem(ILFindLastID(Pidls[0])); 2234 } 2235 } 2236 break; 2237 2238 case SHCNE_RMDIR: 2239 case SHCNE_DELETE: 2240 if (bParent0) 2241 LV_DeleteItem(ILFindLastID(Pidls[0])); 2242 break; 2243 2244 case SHCNE_RENAMEFOLDER: 2245 case SHCNE_RENAMEITEM: 2246 if (bParent0 && bParent1) 2247 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[1])); 2248 else if (bParent0) 2249 LV_DeleteItem(ILFindLastID(Pidls[0])); 2250 else if (bParent1) 2251 LV_AddItem(ILFindLastID(Pidls[1])); 2252 break; 2253 2254 case SHCNE_UPDATEITEM: 2255 if (bParent0) 2256 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0])); 2257 break; 2258 2259 case SHCNE_UPDATEDIR: 2260 Refresh(); 2261 break; 2262 } 2263 2264 SHChangeNotification_Unlock(hLock); 2265 return TRUE; 2266 } 2267 2268 HRESULT SHGetMenuIdFromMenuMsg(UINT uMsg, LPARAM lParam, UINT *CmdId); 2269 HRESULT SHSetMenuIdInMenuMsg(UINT uMsg, LPARAM lParam, UINT CmdId); 2270 2271 /********************************************************** 2272 * CDefView::OnCustomItem 2273 */ 2274 LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 2275 { 2276 if (!m_pCM.p) 2277 { 2278 /* no menu */ 2279 ERR("no menu!!!\n"); 2280 return FALSE; 2281 } 2282 2283 /* The lParam of WM_DRAWITEM WM_MEASUREITEM contain a menu id and this also needs to 2284 be changed to a menu identifier offset */ 2285 UINT CmdID; 2286 HRESULT hres = SHGetMenuIdFromMenuMsg(uMsg, lParam, &CmdID); 2287 if (SUCCEEDED(hres)) 2288 SHSetMenuIdInMenuMsg(uMsg, lParam, CmdID - CONTEXT_MENU_BASE_ID); 2289 2290 /* Forward the message to the IContextMenu2 */ 2291 LRESULT result; 2292 hres = SHForwardContextMenuMsg(m_pCM, uMsg, wParam, lParam, &result, TRUE); 2293 2294 return (SUCCEEDED(hres)); 2295 } 2296 2297 LRESULT CDefView::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 2298 { 2299 /* Wallpaper setting affects drop shadows effect */ 2300 if (wParam == SPI_SETDESKWALLPAPER || wParam == 0) 2301 UpdateListColors(); 2302 2303 return S_OK; 2304 } 2305 2306 /********************************************************** 2307 * CDefView::OnInitMenuPopup 2308 */ 2309 LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 2310 { 2311 HMENU hmenu = (HMENU) wParam; 2312 int nPos = LOWORD(lParam); 2313 UINT menuItemId; 2314 2315 OnCustomItem(uMsg, wParam, lParam, bHandled); 2316 2317 HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW); 2318 2319 if (GetSelections() == 0) 2320 { 2321 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_CUT, MF_GRAYED); 2322 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPY, MF_GRAYED); 2323 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME, MF_GRAYED); 2324 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPYTO, MF_GRAYED); 2325 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_MOVETO, MF_GRAYED); 2326 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_DELETE, MF_GRAYED); 2327 } 2328 else 2329 { 2330 // FIXME: Check copyable 2331 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_CUT, MF_ENABLED); 2332 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPY, MF_ENABLED); 2333 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME, MF_ENABLED); 2334 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPYTO, MF_ENABLED); 2335 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_MOVETO, MF_ENABLED); 2336 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_DELETE, MF_ENABLED); 2337 } 2338 2339 /* Lets try to find out what the hell wParam is */ 2340 if (hmenu == GetSubMenu(m_hMenu, nPos)) 2341 menuItemId = ReallyGetMenuItemID(m_hMenu, nPos); 2342 else if (hViewMenu && hmenu == GetSubMenu(hViewMenu, nPos)) 2343 menuItemId = ReallyGetMenuItemID(hViewMenu, nPos); 2344 else if (m_hContextMenu && hmenu == GetSubMenu(m_hContextMenu, nPos)) 2345 menuItemId = ReallyGetMenuItemID(m_hContextMenu, nPos); 2346 else 2347 return FALSE; 2348 2349 switch (menuItemId) 2350 { 2351 case FCIDM_MENU_FILE: 2352 FillFileMenu(); 2353 break; 2354 case FCIDM_MENU_VIEW: 2355 case FCIDM_SHVIEW_VIEW: 2356 CheckViewMode(hmenu); 2357 break; 2358 case FCIDM_SHVIEW_ARRANGE: 2359 FillArrangeAsMenu(hmenu); 2360 break; 2361 } 2362 2363 return FALSE; 2364 } 2365 2366 /********************************************************** 2367 * 2368 * 2369 * The INTERFACE of the IShellView object 2370 * 2371 * 2372 ********************************************************** 2373 */ 2374 2375 /********************************************************** 2376 * ShellView_GetWindow 2377 */ 2378 HRESULT WINAPI CDefView::GetWindow(HWND *phWnd) 2379 { 2380 TRACE("(%p)\n", this); 2381 2382 *phWnd = m_hWnd; 2383 2384 return S_OK; 2385 } 2386 2387 HRESULT WINAPI CDefView::ContextSensitiveHelp(BOOL fEnterMode) 2388 { 2389 FIXME("(%p) stub\n", this); 2390 2391 return E_NOTIMPL; 2392 } 2393 2394 /********************************************************** 2395 * IShellView_TranslateAccelerator 2396 * 2397 * FIXME: 2398 * use the accel functions 2399 */ 2400 HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg) 2401 { 2402 if (m_isEditing) 2403 return S_FALSE; 2404 2405 if (lpmsg->message >= WM_KEYFIRST && lpmsg->message <= WM_KEYLAST) 2406 { 2407 if (::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg) != 0) 2408 return S_OK; 2409 2410 TRACE("-- key=0x%04lx\n", lpmsg->wParam) ; 2411 } 2412 2413 return m_pShellBrowser->TranslateAcceleratorSB(lpmsg, 0); 2414 } 2415 2416 HRESULT WINAPI CDefView::EnableModeless(BOOL fEnable) 2417 { 2418 FIXME("(%p) stub\n", this); 2419 2420 return E_NOTIMPL; 2421 } 2422 2423 HRESULT WINAPI CDefView::UIActivate(UINT uState) 2424 { 2425 // CHAR szName[MAX_PATH]; 2426 LRESULT lResult; 2427 int nPartArray[1] = { -1}; 2428 2429 TRACE("(%p)->(state=%x) stub\n", this, uState); 2430 2431 /* don't do anything if the state isn't really changing */ 2432 if (m_uState == uState) 2433 { 2434 return S_OK; 2435 } 2436 2437 /* OnActivate handles the menu merging and internal state */ 2438 DoActivate(uState); 2439 2440 /* only do This if we are active */ 2441 if (uState != SVUIA_DEACTIVATE) 2442 { 2443 2444 /* 2445 GetFolderPath is not a method of IShellFolder 2446 IShellFolder_GetFolderPath( m_pSFParent, szName, sizeof(szName) ); 2447 */ 2448 /* set the number of parts */ 2449 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult); 2450 2451 /* set the text for the parts */ 2452 /* 2453 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult); 2454 */ 2455 } 2456 2457 return S_OK; 2458 } 2459 2460 HRESULT WINAPI CDefView::Refresh() 2461 { 2462 TRACE("(%p)\n", this); 2463 2464 _DoFolderViewCB(SFVM_LISTREFRESHED, TRUE, 0); 2465 2466 m_ListView.DeleteAllItems(); 2467 FillList(); 2468 2469 return S_OK; 2470 } 2471 2472 HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd) 2473 { 2474 return CreateViewWindow3(psb, lpPrevView, SV3CVW3_DEFAULT, 2475 (FOLDERFLAGS)lpfs->fFlags, (FOLDERFLAGS)lpfs->fFlags, (FOLDERVIEWMODE)lpfs->ViewMode, NULL, prcView, phWnd); 2476 } 2477 2478 HRESULT WINAPI CDefView::DestroyViewWindow() 2479 { 2480 TRACE("(%p)\n", this); 2481 2482 /* Make absolutely sure all our UI is cleaned up */ 2483 UIActivate(SVUIA_DEACTIVATE); 2484 2485 if (m_hAccel) 2486 { 2487 // "Accelerator tables loaded from resources are freed automatically when the application terminates." -- MSDN 2488 m_hAccel = NULL; 2489 } 2490 2491 if (m_hMenuArrangeModes) 2492 { 2493 DestroyMenu(m_hMenuArrangeModes); 2494 m_hMenuArrangeModes = NULL; 2495 } 2496 2497 if (m_hMenuViewModes) 2498 { 2499 DestroyMenu(m_hMenuViewModes); 2500 m_hMenuViewModes = NULL; 2501 } 2502 2503 if (m_hMenu) 2504 { 2505 DestroyMenu(m_hMenu); 2506 m_hMenu = NULL; 2507 } 2508 2509 if (m_ListView) 2510 { 2511 m_ListView.DestroyWindow(); 2512 } 2513 2514 if (m_hWnd) 2515 { 2516 _DoFolderViewCB(SFVM_WINDOWCLOSING, (WPARAM)m_hWnd, 0); 2517 DestroyWindow(); 2518 } 2519 2520 m_pShellBrowser.Release(); 2521 m_pCommDlgBrowser.Release(); 2522 2523 return S_OK; 2524 } 2525 2526 HRESULT WINAPI CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs) 2527 { 2528 TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs, 2529 m_FolderSettings.ViewMode, m_FolderSettings.fFlags); 2530 2531 if (!lpfs) 2532 return E_INVALIDARG; 2533 2534 *lpfs = m_FolderSettings; 2535 return S_OK; 2536 } 2537 2538 HRESULT WINAPI CDefView::AddPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam) 2539 { 2540 FIXME("(%p) stub\n", this); 2541 2542 return E_NOTIMPL; 2543 } 2544 2545 HRESULT WINAPI CDefView::SaveViewState() 2546 { 2547 FIXME("(%p) stub\n", this); 2548 2549 return S_OK; 2550 } 2551 2552 HRESULT WINAPI CDefView::SelectItem(PCUITEMID_CHILD pidl, UINT uFlags) 2553 { 2554 int i; 2555 2556 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl, uFlags); 2557 2558 i = LV_FindItemByPidl(pidl); 2559 if (i == -1) 2560 return S_OK; 2561 2562 LVITEMW lvItem = {0}; 2563 lvItem.mask = LVIF_STATE; 2564 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED; 2565 2566 while (m_ListView.GetItem(&lvItem)) 2567 { 2568 if (lvItem.iItem == i) 2569 { 2570 if (uFlags & SVSI_SELECT) 2571 lvItem.state |= LVIS_SELECTED; 2572 else 2573 lvItem.state &= ~LVIS_SELECTED; 2574 2575 if (uFlags & SVSI_FOCUSED) 2576 lvItem.state |= LVIS_FOCUSED; 2577 else 2578 lvItem.state &= ~LVIS_FOCUSED; 2579 } 2580 else 2581 { 2582 if (uFlags & SVSI_DESELECTOTHERS) 2583 { 2584 lvItem.state &= ~LVIS_SELECTED; 2585 } 2586 lvItem.state &= ~LVIS_FOCUSED; 2587 } 2588 2589 m_ListView.SetItem(&lvItem); 2590 lvItem.iItem++; 2591 } 2592 2593 if (uFlags & SVSI_ENSUREVISIBLE) 2594 m_ListView.EnsureVisible(i, FALSE); 2595 2596 if((uFlags & SVSI_EDIT) == SVSI_EDIT) 2597 m_ListView.EditLabel(i); 2598 2599 return S_OK; 2600 } 2601 2602 HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut) 2603 { 2604 HRESULT hr = E_NOINTERFACE; 2605 2606 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem, debugstr_guid(&riid), ppvOut); 2607 2608 if (!ppvOut) 2609 return E_INVALIDARG; 2610 2611 *ppvOut = NULL; 2612 2613 switch (uItem) 2614 { 2615 case SVGIO_BACKGROUND: 2616 if (IsEqualIID(riid, IID_IContextMenu)) 2617 { 2618 hr = CDefViewBckgrndMenu_CreateInstance(m_pSF2Parent, riid, ppvOut); 2619 if (FAILED_UNEXPECTEDLY(hr)) 2620 return hr; 2621 2622 IUnknown_SetSite(*((IUnknown**)ppvOut), (IShellView *)this); 2623 } 2624 else if (IsEqualIID(riid, IID_IDispatch)) 2625 { 2626 if (m_pShellFolderViewDual == NULL) 2627 { 2628 hr = CDefViewDual_Constructor(riid, (LPVOID*)&m_pShellFolderViewDual); 2629 if (FAILED_UNEXPECTEDLY(hr)) 2630 return hr; 2631 } 2632 hr = m_pShellFolderViewDual->QueryInterface(riid, ppvOut); 2633 } 2634 break; 2635 2636 case SVGIO_SELECTION: 2637 GetSelections(); 2638 hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, riid, 0, ppvOut); 2639 if (FAILED_UNEXPECTEDLY(hr)) 2640 return hr; 2641 2642 if (IsEqualIID(riid, IID_IContextMenu)) 2643 IUnknown_SetSite(*((IUnknown**)ppvOut), (IShellView *)this); 2644 2645 break; 2646 } 2647 2648 TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut); 2649 2650 return hr; 2651 } 2652 2653 HRESULT STDMETHODCALLTYPE CDefView::GetCurrentViewMode(UINT *pViewMode) 2654 { 2655 TRACE("(%p)->(%p), stub\n", this, pViewMode); 2656 2657 if (!pViewMode) 2658 return E_INVALIDARG; 2659 2660 *pViewMode = m_FolderSettings.ViewMode; 2661 return S_OK; 2662 } 2663 2664 HRESULT STDMETHODCALLTYPE CDefView::SetCurrentViewMode(UINT ViewMode) 2665 { 2666 DWORD dwStyle; 2667 TRACE("(%p)->(%u), stub\n", this, ViewMode); 2668 2669 /* It's not redundant to check FVM_AUTO because it's a (UINT)-1 */ 2670 if (((INT)ViewMode < FVM_FIRST || (INT)ViewMode > FVM_LAST) && ((INT)ViewMode != FVM_AUTO)) 2671 return E_INVALIDARG; 2672 2673 /* Windows before Vista uses LVM_SETVIEW and possibly 2674 LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview, 2675 while later versions seem to accomplish this through other 2676 means. */ 2677 switch (ViewMode) 2678 { 2679 case FVM_ICON: 2680 dwStyle = LVS_ICON; 2681 break; 2682 case FVM_DETAILS: 2683 dwStyle = LVS_REPORT; 2684 break; 2685 case FVM_SMALLICON: 2686 dwStyle = LVS_SMALLICON; 2687 break; 2688 case FVM_LIST: 2689 dwStyle = LVS_LIST; 2690 break; 2691 default: 2692 { 2693 FIXME("ViewMode %d not implemented\n", ViewMode); 2694 dwStyle = LVS_LIST; 2695 break; 2696 } 2697 } 2698 2699 m_ListView.ModifyStyle(LVS_TYPEMASK, dwStyle); 2700 2701 /* This will not necessarily be the actual mode set above. 2702 This mimics the behavior of Windows XP. */ 2703 m_FolderSettings.ViewMode = ViewMode; 2704 2705 return S_OK; 2706 } 2707 2708 HRESULT STDMETHODCALLTYPE CDefView::GetFolder(REFIID riid, void **ppv) 2709 { 2710 if (m_pSFParent == NULL) 2711 return E_FAIL; 2712 2713 return m_pSFParent->QueryInterface(riid, ppv); 2714 } 2715 2716 HRESULT STDMETHODCALLTYPE CDefView::Item(int iItemIndex, PITEMID_CHILD *ppidl) 2717 { 2718 PCUITEMID_CHILD pidl = _PidlByItem(iItemIndex); 2719 if (pidl) 2720 { 2721 *ppidl = ILClone(pidl); 2722 return S_OK; 2723 } 2724 2725 *ppidl = 0; 2726 return E_INVALIDARG; 2727 } 2728 2729 HRESULT STDMETHODCALLTYPE CDefView::ItemCount(UINT uFlags, int *pcItems) 2730 { 2731 TRACE("(%p)->(%u %p)\n", this, uFlags, pcItems); 2732 2733 if (uFlags != SVGIO_ALLVIEW) 2734 FIXME("some flags unsupported, %x\n", uFlags & ~SVGIO_ALLVIEW); 2735 2736 *pcItems = m_ListView.GetItemCount(); 2737 2738 return S_OK; 2739 } 2740 2741 HRESULT STDMETHODCALLTYPE CDefView::Items(UINT uFlags, REFIID riid, void **ppv) 2742 { 2743 return E_NOTIMPL; 2744 } 2745 2746 HRESULT STDMETHODCALLTYPE CDefView::GetSelectionMarkedItem(int *piItem) 2747 { 2748 TRACE("(%p)->(%p)\n", this, piItem); 2749 2750 *piItem = m_ListView.GetSelectionMark(); 2751 2752 return S_OK; 2753 } 2754 2755 HRESULT STDMETHODCALLTYPE CDefView::GetFocusedItem(int *piItem) 2756 { 2757 TRACE("(%p)->(%p)\n", this, piItem); 2758 2759 *piItem = m_ListView.GetNextItem(-1, LVNI_FOCUSED); 2760 2761 return S_OK; 2762 } 2763 2764 HRESULT STDMETHODCALLTYPE CDefView::GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt) 2765 { 2766 int lvIndex = LV_FindItemByPidl(pidl); 2767 if (lvIndex == -1 || ppt == NULL) 2768 return E_INVALIDARG; 2769 2770 m_ListView.GetItemPosition(lvIndex, ppt); 2771 return S_OK; 2772 } 2773 2774 HRESULT STDMETHODCALLTYPE CDefView::GetSpacing(POINT *ppt) 2775 { 2776 TRACE("(%p)->(%p)\n", this, ppt); 2777 2778 if (!m_ListView) 2779 return S_FALSE; 2780 2781 if (ppt) 2782 { 2783 SIZE spacing; 2784 m_ListView.GetItemSpacing(spacing); 2785 2786 ppt->x = spacing.cx; 2787 ppt->y = spacing.cy; 2788 } 2789 2790 return S_OK; 2791 } 2792 2793 HRESULT STDMETHODCALLTYPE CDefView::GetDefaultSpacing(POINT *ppt) 2794 { 2795 return E_NOTIMPL; 2796 } 2797 2798 HRESULT STDMETHODCALLTYPE CDefView::GetAutoArrange() 2799 { 2800 return ((m_ListView.GetStyle() & LVS_AUTOARRANGE) ? S_OK : S_FALSE); 2801 } 2802 2803 HRESULT CDefView::_GetSnapToGrid() 2804 { 2805 DWORD dwExStyle = (DWORD)m_ListView.SendMessage(LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); 2806 return ((dwExStyle & LVS_EX_SNAPTOGRID) ? S_OK : S_FALSE); 2807 } 2808 2809 HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags) 2810 { 2811 LVITEMW lvItem; 2812 2813 TRACE("(%p)->(%d, %x)\n", this, iItem, dwFlags); 2814 2815 lvItem.state = 0; 2816 lvItem.stateMask = LVIS_SELECTED; 2817 2818 if (dwFlags & SVSI_ENSUREVISIBLE) 2819 m_ListView.EnsureVisible(iItem, 0); 2820 2821 /* all items */ 2822 if (dwFlags & SVSI_DESELECTOTHERS) 2823 m_ListView.SetItemState(-1, 0, LVIS_SELECTED); 2824 2825 /* this item */ 2826 if (dwFlags & SVSI_SELECT) 2827 lvItem.state |= LVIS_SELECTED; 2828 2829 if (dwFlags & SVSI_FOCUSED) 2830 lvItem.stateMask |= LVIS_FOCUSED; 2831 2832 m_ListView.SetItemState(iItem, lvItem.state, lvItem.stateMask); 2833 2834 if ((dwFlags & SVSI_EDIT) == SVSI_EDIT) 2835 m_ListView.EditLabel(iItem); 2836 2837 return S_OK; 2838 } 2839 2840 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags) 2841 { 2842 /* Reset the selection */ 2843 m_ListView.SetItemState(-1, 0, LVIS_SELECTED); 2844 2845 int lvIndex; 2846 for (UINT i = 0 ; i < m_cidl; i++) 2847 { 2848 lvIndex = LV_FindItemByPidl(apidl[i]); 2849 if (lvIndex != -1) 2850 { 2851 SelectItem(lvIndex, dwFlags); 2852 m_ListView.SetItemPosition(lvIndex, &apt[i]); 2853 } 2854 } 2855 2856 return S_OK; 2857 } 2858 2859 /********************************************************** 2860 * IShellView2 implementation 2861 */ 2862 2863 HRESULT STDMETHODCALLTYPE CDefView::GetView(SHELLVIEWID *view_guid, ULONG view_type) 2864 { 2865 FIXME("(%p)->(%p, %lu) stub\n", this, view_guid, view_type); 2866 return E_NOTIMPL; 2867 } 2868 2869 HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow2(LPSV2CVW2_PARAMS view_params) 2870 { 2871 return CreateViewWindow3(view_params->psbOwner, view_params->psvPrev, 2872 SV3CVW3_DEFAULT, (FOLDERFLAGS)view_params->pfs->fFlags, (FOLDERFLAGS)view_params->pfs->fFlags, 2873 (FOLDERVIEWMODE)view_params->pfs->ViewMode, view_params->pvid, view_params->prcView, &view_params->hwndView); 2874 } 2875 2876 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) 2877 { 2878 OLEMENUGROUPWIDTHS omw = { { 0, 0, 0, 0, 0, 0 } }; 2879 2880 *hwnd = NULL; 2881 2882 TRACE("(%p)->(shlview=%p shlbrs=%p rec=%p hwnd=%p vmode=%x flags=%x)\n", this, psvPrevious, psb, prcView, hwnd, mode, flags); 2883 if (prcView != NULL) 2884 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom); 2885 2886 /* Validate the Shell Browser */ 2887 if (psb == NULL || m_hWnd) 2888 return E_UNEXPECTED; 2889 2890 if (view_flags != SV3CVW3_DEFAULT) 2891 FIXME("unsupported view flags 0x%08x\n", view_flags); 2892 2893 /* Set up the member variables */ 2894 m_pShellBrowser = psb; 2895 m_FolderSettings.ViewMode = mode; 2896 m_FolderSettings.fFlags = mask & flags; 2897 2898 if (view_id) 2899 { 2900 if (IsEqualIID(*view_id, VID_LargeIcons)) 2901 m_FolderSettings.ViewMode = FVM_ICON; 2902 else if (IsEqualIID(*view_id, VID_SmallIcons)) 2903 m_FolderSettings.ViewMode = FVM_SMALLICON; 2904 else if (IsEqualIID(*view_id, VID_List)) 2905 m_FolderSettings.ViewMode = FVM_LIST; 2906 else if (IsEqualIID(*view_id, VID_Details)) 2907 m_FolderSettings.ViewMode = FVM_DETAILS; 2908 else if (IsEqualIID(*view_id, VID_Thumbnails)) 2909 m_FolderSettings.ViewMode = FVM_THUMBNAIL; 2910 else if (IsEqualIID(*view_id, VID_Tile)) 2911 m_FolderSettings.ViewMode = FVM_TILE; 2912 else if (IsEqualIID(*view_id, VID_ThumbStrip)) 2913 m_FolderSettings.ViewMode = FVM_THUMBSTRIP; 2914 else 2915 FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_id)); 2916 } 2917 2918 /* Get our parent window */ 2919 m_pShellBrowser->GetWindow(&m_hWndParent); 2920 2921 /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */ 2922 m_pCommDlgBrowser = NULL; 2923 if (SUCCEEDED(m_pShellBrowser->QueryInterface(IID_PPV_ARG(ICommDlgBrowser, &m_pCommDlgBrowser)))) 2924 { 2925 TRACE("-- CommDlgBrowser\n"); 2926 } 2927 2928 Create(m_hWndParent, prcView, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP, 0, 0U); 2929 if (m_hWnd == NULL) 2930 return E_FAIL; 2931 2932 *hwnd = m_hWnd; 2933 2934 CheckToolbar(); 2935 2936 if (!*hwnd) 2937 return E_FAIL; 2938 2939 _DoFolderViewCB(SFVM_WINDOWCREATED, (WPARAM)m_hWnd, 0); 2940 2941 SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); 2942 UpdateWindow(); 2943 2944 if (!m_hMenu) 2945 { 2946 m_hMenu = CreateMenu(); 2947 m_pShellBrowser->InsertMenusSB(m_hMenu, &omw); 2948 TRACE("-- after fnInsertMenusSB\n"); 2949 } 2950 2951 _MergeToolbar(); 2952 2953 return S_OK; 2954 } 2955 2956 HRESULT STDMETHODCALLTYPE CDefView::HandleRename(LPCITEMIDLIST new_pidl) 2957 { 2958 FIXME("(%p)->(%p) stub\n", this, new_pidl); 2959 return E_NOTIMPL; 2960 } 2961 2962 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point) 2963 { 2964 FIXME("(%p)->(%p, %u, %p) stub\n", this, item, flags, point); 2965 return E_NOTIMPL; 2966 } 2967 2968 /********************************************************** 2969 * IShellFolderView implementation 2970 */ 2971 HRESULT STDMETHODCALLTYPE CDefView::Rearrange(LPARAM sort) 2972 { 2973 FIXME("(%p)->(%ld) stub\n", this, sort); 2974 return E_NOTIMPL; 2975 } 2976 2977 HRESULT STDMETHODCALLTYPE CDefView::GetArrangeParam(LPARAM *sort) 2978 { 2979 FIXME("(%p)->(%p) stub\n", this, sort); 2980 return E_NOTIMPL; 2981 } 2982 2983 HRESULT STDMETHODCALLTYPE CDefView::ArrangeGrid() 2984 { 2985 m_ListView.SetExtendedListViewStyle(LVS_EX_SNAPTOGRID, LVS_EX_SNAPTOGRID); 2986 return S_OK; 2987 } 2988 2989 HRESULT STDMETHODCALLTYPE CDefView::AutoArrange() 2990 { 2991 m_ListView.ModifyStyle(0, LVS_AUTOARRANGE); 2992 m_ListView.Arrange(LVA_DEFAULT); 2993 return S_OK; 2994 } 2995 2996 HRESULT STDMETHODCALLTYPE CDefView::AddObject(PITEMID_CHILD pidl, UINT *item) 2997 { 2998 TRACE("(%p)->(%p %p)\n", this, pidl, item); 2999 *item = LV_AddItem(pidl); 3000 return (int)*item >= 0 ? S_OK : E_OUTOFMEMORY; 3001 } 3002 3003 HRESULT STDMETHODCALLTYPE CDefView::GetObject(PITEMID_CHILD *pidl, UINT item) 3004 { 3005 TRACE("(%p)->(%p %d)\n", this, pidl, item); 3006 return Item(item, pidl); 3007 } 3008 3009 HRESULT STDMETHODCALLTYPE CDefView::RemoveObject(PITEMID_CHILD pidl, UINT *item) 3010 { 3011 3012 TRACE("(%p)->(%p %p)\n", this, pidl, item); 3013 3014 if (pidl) 3015 { 3016 *item = LV_FindItemByPidl(ILFindLastID(pidl)); 3017 m_ListView.DeleteItem(*item); 3018 } 3019 else 3020 { 3021 *item = 0; 3022 m_ListView.DeleteAllItems(); 3023 } 3024 3025 return S_OK; 3026 } 3027 3028 HRESULT STDMETHODCALLTYPE CDefView::GetObjectCount(UINT *count) 3029 { 3030 TRACE("(%p)->(%p)\n", this, count); 3031 *count = m_ListView.GetItemCount(); 3032 return S_OK; 3033 } 3034 3035 HRESULT STDMETHODCALLTYPE CDefView::SetObjectCount(UINT count, UINT flags) 3036 { 3037 FIXME("(%p)->(%d %x) stub\n", this, count, flags); 3038 return E_NOTIMPL; 3039 } 3040 3041 HRESULT STDMETHODCALLTYPE CDefView::UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item) 3042 { 3043 FIXME("(%p)->(%p %p %p) stub\n", this, pidl_old, pidl_new, item); 3044 return E_NOTIMPL; 3045 } 3046 3047 HRESULT STDMETHODCALLTYPE CDefView::RefreshObject(PITEMID_CHILD pidl, UINT *item) 3048 { 3049 FIXME("(%p)->(%p %p) stub\n", this, pidl, item); 3050 return E_NOTIMPL; 3051 } 3052 3053 HRESULT STDMETHODCALLTYPE CDefView::SetRedraw(BOOL redraw) 3054 { 3055 TRACE("(%p)->(%d)\n", this, redraw); 3056 m_ListView.SetRedraw(redraw); 3057 return S_OK; 3058 } 3059 3060 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedCount(UINT *count) 3061 { 3062 FIXME("(%p)->(%p) stub\n", this, count); 3063 return E_NOTIMPL; 3064 } 3065 3066 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items) 3067 { 3068 TRACE("(%p)->(%p %p)\n", this, pidl, items); 3069 3070 *items = GetSelections(); 3071 3072 if (*items) 3073 { 3074 *pidl = static_cast<PCUITEMID_CHILD *>(LocalAlloc(0, *items * sizeof(PCUITEMID_CHILD))); 3075 if (!*pidl) 3076 { 3077 return E_OUTOFMEMORY; 3078 } 3079 3080 /* it's documented that caller shouldn't PIDLs, only array itself */ 3081 memcpy(*pidl, m_apidl, *items * sizeof(PCUITEMID_CHILD)); 3082 } 3083 3084 return S_OK; 3085 } 3086 3087 HRESULT STDMETHODCALLTYPE CDefView::IsDropOnSource(IDropTarget *drop_target) 3088 { 3089 if ((m_iDragOverItem == -1 || m_pCurDropTarget == NULL) && 3090 (m_pSourceDataObject.p)) 3091 { 3092 return S_OK; 3093 } 3094 3095 return S_FALSE; 3096 } 3097 3098 HRESULT STDMETHODCALLTYPE CDefView::GetDragPoint(POINT *pt) 3099 { 3100 if (!pt) 3101 return E_INVALIDARG; 3102 3103 *pt = m_ptFirstMousePos; 3104 return S_OK; 3105 } 3106 3107 HRESULT STDMETHODCALLTYPE CDefView::GetDropPoint(POINT *pt) 3108 { 3109 FIXME("(%p)->(%p) stub\n", this, pt); 3110 return E_NOTIMPL; 3111 } 3112 3113 HRESULT STDMETHODCALLTYPE CDefView::MoveIcons(IDataObject *obj) 3114 { 3115 TRACE("(%p)->(%p)\n", this, obj); 3116 return E_NOTIMPL; 3117 } 3118 3119 HRESULT STDMETHODCALLTYPE CDefView::SetItemPos(PCUITEMID_CHILD pidl, POINT *pt) 3120 { 3121 FIXME("(%p)->(%p %p) stub\n", this, pidl, pt); 3122 return E_NOTIMPL; 3123 } 3124 3125 HRESULT STDMETHODCALLTYPE CDefView::IsBkDropTarget(IDropTarget *drop_target) 3126 { 3127 FIXME("(%p)->(%p) stub\n", this, drop_target); 3128 return E_NOTIMPL; 3129 } 3130 3131 HRESULT STDMETHODCALLTYPE CDefView::SetClipboard(BOOL move) 3132 { 3133 FIXME("(%p)->(%d) stub\n", this, move); 3134 return E_NOTIMPL; 3135 } 3136 3137 HRESULT STDMETHODCALLTYPE CDefView::SetPoints(IDataObject *obj) 3138 { 3139 FIXME("(%p)->(%p) stub\n", this, obj); 3140 return E_NOTIMPL; 3141 } 3142 3143 HRESULT STDMETHODCALLTYPE CDefView::GetItemSpacing(ITEMSPACING *spacing) 3144 { 3145 FIXME("(%p)->(%p) stub\n", this, spacing); 3146 return E_NOTIMPL; 3147 } 3148 3149 HRESULT STDMETHODCALLTYPE CDefView::SetCallback(IShellFolderViewCB *new_cb, IShellFolderViewCB **old_cb) 3150 { 3151 if (old_cb) 3152 *old_cb = m_pShellFolderViewCB.Detach(); 3153 3154 m_pShellFolderViewCB = new_cb; 3155 return S_OK; 3156 } 3157 3158 HRESULT STDMETHODCALLTYPE CDefView::Select(UINT flags) 3159 { 3160 FIXME("(%p)->(%d) stub\n", this, flags); 3161 return E_NOTIMPL; 3162 } 3163 3164 HRESULT STDMETHODCALLTYPE CDefView::QuerySupport(UINT *support) 3165 { 3166 TRACE("(%p)->(%p)\n", this, support); 3167 return S_OK; 3168 } 3169 3170 HRESULT STDMETHODCALLTYPE CDefView::SetAutomationObject(IDispatch *disp) 3171 { 3172 FIXME("(%p)->(%p) stub\n", this, disp); 3173 return E_NOTIMPL; 3174 } 3175 3176 /********************************************************** 3177 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget) 3178 */ 3179 HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText) 3180 { 3181 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n", 3182 this, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText); 3183 3184 if (!prgCmds) 3185 return E_INVALIDARG; 3186 3187 for (UINT i = 0; i < cCmds; i++) 3188 { 3189 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID); 3190 prgCmds[i].cmdf = 0; 3191 } 3192 3193 return OLECMDERR_E_UNKNOWNGROUP; 3194 } 3195 3196 /********************************************************** 3197 * ISVOleCmdTarget_Exec (IOleCommandTarget) 3198 * 3199 * nCmdID is the OLECMDID_* enumeration 3200 */ 3201 HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 3202 { 3203 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n", 3204 this, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut); 3205 3206 if (!pguidCmdGroup) 3207 return OLECMDERR_E_UNKNOWNGROUP; 3208 3209 if (IsEqualCLSID(*pguidCmdGroup, m_Category)) 3210 { 3211 if (nCmdID == FCIDM_SHVIEW_AUTOARRANGE) 3212 { 3213 if (V_VT(pvaIn) != VT_INT_PTR) 3214 return OLECMDERR_E_NOTSUPPORTED; 3215 3216 TPMPARAMS params; 3217 params.cbSize = sizeof(params); 3218 params.rcExclude = *(RECT*) V_INTREF(pvaIn); 3219 3220 if (m_hMenuViewModes) 3221 { 3222 /* Duplicate all but the last two items of the view modes menu */ 3223 HMENU hmenuViewPopup = CreatePopupMenu(); 3224 Shell_MergeMenus(hmenuViewPopup, m_hMenuViewModes, 0, 0, 0xFFFF, 0); 3225 DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION); 3226 DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION); 3227 CheckViewMode(hmenuViewPopup); 3228 TrackPopupMenuEx(hmenuViewPopup, TPM_LEFTALIGN | TPM_TOPALIGN, params.rcExclude.left, params.rcExclude.bottom, m_hWndParent, ¶ms); 3229 ::DestroyMenu(hmenuViewPopup); 3230 } 3231 3232 // pvaOut is VT_I4 with value 0x403 (cmd id of the new mode maybe?) 3233 V_VT(pvaOut) = VT_I4; 3234 V_I4(pvaOut) = 0x403; 3235 } 3236 } 3237 3238 if (IsEqualIID(*pguidCmdGroup, CGID_Explorer) && 3239 (nCmdID == 0x29) && 3240 (nCmdexecopt == 4) && pvaOut) 3241 return S_OK; 3242 3243 if (IsEqualIID(*pguidCmdGroup, CGID_ShellDocView) && 3244 (nCmdID == 9) && 3245 (nCmdexecopt == 0)) 3246 return 1; 3247 3248 return OLECMDERR_E_UNKNOWNGROUP; 3249 } 3250 3251 /********************************************************** 3252 * ISVDropTarget implementation 3253 */ 3254 3255 /****************************************************************************** 3256 * drag_notify_subitem [Internal] 3257 * 3258 * Figure out the shellfolder object, which is currently under the mouse cursor 3259 * and notify it via the IDropTarget interface. 3260 */ 3261 3262 #define SCROLLAREAWIDTH 20 3263 3264 HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 3265 { 3266 LONG lResult; 3267 HRESULT hr; 3268 RECT clientRect; 3269 3270 /* The key state on drop doesn't have MK_LBUTTON or MK_RBUTTON because it 3271 reflects the key state after the user released the button, so we need 3272 to remember the last key state when the button was pressed */ 3273 m_grfKeyState = grfKeyState; 3274 3275 /* Map from global to client coordinates and query the index of the listview-item, which is 3276 * currently under the mouse cursor. */ 3277 LVHITTESTINFO htinfo = {{pt.x, pt.y}, LVHT_ONITEM}; 3278 ScreenToClient(&htinfo.pt); 3279 lResult = m_ListView.HitTest(&htinfo); 3280 3281 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */ 3282 ::GetClientRect(m_ListView, &clientRect); 3283 if (htinfo.pt.x == m_ptLastMousePos.x && htinfo.pt.y == m_ptLastMousePos.y && 3284 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH || 3285 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH )) 3286 { 3287 m_cScrollDelay = (m_cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */ 3288 if (m_cScrollDelay == 0) 3289 { 3290 /* Mouse did hover another 250 ms over the scroll-area */ 3291 if (htinfo.pt.x < SCROLLAREAWIDTH) 3292 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEUP, 0); 3293 3294 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH) 3295 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEDOWN, 0); 3296 3297 if (htinfo.pt.y < SCROLLAREAWIDTH) 3298 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEUP, 0); 3299 3300 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH) 3301 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEDOWN, 0); 3302 } 3303 } 3304 else 3305 { 3306 m_cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */ 3307 } 3308 3309 m_ptLastMousePos = htinfo.pt; 3310 ::ClientToListView(m_ListView, &m_ptLastMousePos); 3311 3312 /* We need to check if we drag the selection over itself */ 3313 if (lResult != -1 && m_pSourceDataObject.p != NULL) 3314 { 3315 PCUITEMID_CHILD pidl = _PidlByItem(lResult); 3316 3317 for (UINT i = 0; i < m_cidl; i++) 3318 { 3319 if (pidl == m_apidl[i]) 3320 { 3321 /* The item that is being draged is hovering itself. */ 3322 lResult = -1; 3323 break; 3324 } 3325 } 3326 } 3327 3328 /* If we are still over the previous sub-item, notify it via DragOver and return. */ 3329 if (m_pCurDropTarget && lResult == m_iDragOverItem) 3330 return m_pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect); 3331 3332 /* We've left the previous sub-item, notify it via DragLeave and Release it. */ 3333 if (m_pCurDropTarget) 3334 { 3335 PCUITEMID_CHILD pidl = _PidlByItem(m_iDragOverItem); 3336 if (pidl) 3337 SelectItem(pidl, 0); 3338 3339 m_pCurDropTarget->DragLeave(); 3340 m_pCurDropTarget.Release(); 3341 } 3342 3343 m_iDragOverItem = lResult; 3344 3345 if (lResult == -1) 3346 { 3347 /* We are not above one of the listview's subitems. Bind to the parent folder's 3348 * DropTarget interface. */ 3349 hr = m_pSFParent->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget,&m_pCurDropTarget)); 3350 } 3351 else 3352 { 3353 /* Query the relative PIDL of the shellfolder object represented by the currently 3354 * dragged over listview-item ... */ 3355 PCUITEMID_CHILD pidl = _PidlByItem(lResult); 3356 3357 /* ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object */ 3358 hr = m_pSFParent->GetUIObjectOf(m_ListView, 1, &pidl, IID_NULL_PPV_ARG(IDropTarget, &m_pCurDropTarget)); 3359 } 3360 3361 IUnknown_SetSite(m_pCurDropTarget, (IShellView *)this); 3362 3363 /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */ 3364 if (FAILED(hr)) 3365 { 3366 *pdwEffect = DROPEFFECT_NONE; 3367 return hr; 3368 } 3369 3370 if (m_iDragOverItem != -1) 3371 { 3372 SelectItem(m_iDragOverItem, SVSI_SELECT); 3373 } 3374 3375 /* Notify the item just entered via DragEnter. */ 3376 return m_pCurDropTarget->DragEnter(m_pCurDataObject, grfKeyState, pt, pdwEffect); 3377 } 3378 3379 HRESULT WINAPI CDefView::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 3380 { 3381 if (*pdwEffect == DROPEFFECT_NONE) 3382 return S_OK; 3383 3384 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */ 3385 m_pCurDataObject = pDataObject; 3386 3387 HRESULT hr = drag_notify_subitem(grfKeyState, pt, pdwEffect); 3388 if (SUCCEEDED(hr)) 3389 { 3390 POINT ptClient = {pt.x, pt.y}; 3391 ScreenToClient(&ptClient); 3392 ImageList_DragEnter(m_hWnd, ptClient.x, ptClient.y); 3393 } 3394 3395 return hr; 3396 } 3397 3398 HRESULT WINAPI CDefView::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 3399 { 3400 POINT ptClient = {pt.x, pt.y}; 3401 ScreenToClient(&ptClient); 3402 ImageList_DragMove(ptClient.x, ptClient.y); 3403 return drag_notify_subitem(grfKeyState, pt, pdwEffect); 3404 } 3405 3406 HRESULT WINAPI CDefView::DragLeave() 3407 { 3408 ImageList_DragLeave(m_hWnd); 3409 3410 if (m_pCurDropTarget) 3411 { 3412 m_pCurDropTarget->DragLeave(); 3413 m_pCurDropTarget.Release(); 3414 } 3415 3416 if (m_pCurDataObject != NULL) 3417 { 3418 m_pCurDataObject.Release(); 3419 } 3420 3421 m_iDragOverItem = 0; 3422 3423 return S_OK; 3424 } 3425 3426 INT CDefView::_FindInsertableIndexFromPoint(POINT pt) 3427 { 3428 RECT rcBound; 3429 INT i, nCount = m_ListView.GetItemCount(); 3430 DWORD dwSpacing; 3431 INT dx, dy; 3432 BOOL bSmall = ((m_ListView.GetStyle() & LVS_TYPEMASK) != LVS_ICON); 3433 3434 /* FIXME: LVM_GETORIGIN is broken. See CORE-17266 */ 3435 pt.x += m_ListView.GetScrollPos(SB_HORZ); 3436 pt.y += m_ListView.GetScrollPos(SB_VERT); 3437 3438 if (m_ListView.GetStyle() & LVS_ALIGNLEFT) 3439 { 3440 // vertically 3441 for (i = 0; i < nCount; ++i) 3442 { 3443 dwSpacing = ListView_GetItemSpacing(m_ListView, bSmall); 3444 dx = LOWORD(dwSpacing); 3445 dy = HIWORD(dwSpacing); 3446 ListView_GetItemRect(m_ListView, i, &rcBound, LVIR_SELECTBOUNDS); 3447 rcBound.right = rcBound.left + dx; 3448 rcBound.bottom = rcBound.top + dy; 3449 if (pt.x < rcBound.right && pt.y < (rcBound.top + rcBound.bottom) / 2) 3450 { 3451 return i; 3452 } 3453 } 3454 for (i = nCount - 1; i >= 0; --i) 3455 { 3456 ListView_GetItemRect(m_ListView, i, &rcBound, LVIR_SELECTBOUNDS); 3457 if (rcBound.left < pt.x && rcBound.top < pt.y) 3458 { 3459 return i + 1; 3460 } 3461 } 3462 } 3463 else 3464 { 3465 // horizontally 3466 for (i = 0; i < nCount; ++i) 3467 { 3468 dwSpacing = ListView_GetItemSpacing(m_ListView, bSmall); 3469 dx = LOWORD(dwSpacing); 3470 dy = HIWORD(dwSpacing); 3471 ListView_GetItemRect(m_ListView, i, &rcBound, LVIR_SELECTBOUNDS); 3472 rcBound.right = rcBound.left + dx; 3473 rcBound.bottom = rcBound.top + dy; 3474 if (pt.y < rcBound.bottom && pt.x < rcBound.left) 3475 { 3476 return i; 3477 } 3478 if (pt.y < rcBound.bottom && pt.x < rcBound.right) 3479 { 3480 return i + 1; 3481 } 3482 } 3483 for (i = nCount - 1; i >= 0; --i) 3484 { 3485 ListView_GetItemRect(m_ListView, i, &rcBound, LVIR_SELECTBOUNDS); 3486 if (rcBound.left < pt.x && rcBound.top < pt.y) 3487 { 3488 return i + 1; 3489 } 3490 } 3491 } 3492 3493 return nCount; 3494 } 3495 3496 typedef CSimpleMap<LPARAM, INT> CLParamIndexMap; 3497 3498 static INT CALLBACK 3499 SelectionMoveCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) 3500 { 3501 CLParamIndexMap *pmap = (CLParamIndexMap *)lParamSort; 3502 INT i1 = pmap->Lookup(lParam1), i2 = pmap->Lookup(lParam2); 3503 if (i1 < i2) 3504 return -1; 3505 if (i1 > i2) 3506 return 1; 3507 return 0; 3508 } 3509 3510 void CDefView::_MoveSelectionOnAutoArrange(POINT pt) 3511 { 3512 // get insertable index from position 3513 INT iPosition = _FindInsertableIndexFromPoint(pt); 3514 3515 // create identity mapping of indexes 3516 CSimpleArray<INT> array; 3517 INT nCount = m_ListView.GetItemCount(); 3518 for (INT i = 0; i < nCount; ++i) 3519 { 3520 array.Add(i); 3521 } 3522 3523 // re-ordering mapping 3524 INT iItem = -1; 3525 while ((iItem = m_ListView.GetNextItem(iItem, LVNI_SELECTED)) >= 0) 3526 { 3527 INT iFrom = iItem, iTo = iPosition; 3528 if (iFrom < iTo) 3529 --iTo; 3530 if (iFrom >= nCount) 3531 iFrom = nCount - 1; 3532 if (iTo >= nCount) 3533 iTo = nCount - 1; 3534 3535 // shift indexes by swapping (like a bucket relay) 3536 if (iFrom < iTo) 3537 { 3538 for (INT i = iFrom; i < iTo; ++i) 3539 { 3540 // swap array[i] and array[i + 1] 3541 INT tmp = array[i]; 3542 array[i] = array[i + 1]; 3543 array[i + 1] = tmp; 3544 } 3545 } 3546 else 3547 { 3548 for (INT i = iFrom; i > iTo; --i) 3549 { 3550 // swap array[i] and array[i - 1] 3551 INT tmp = array[i]; 3552 array[i] = array[i - 1]; 3553 array[i - 1] = tmp; 3554 } 3555 } 3556 } 3557 3558 // create mapping (ListView's lParam to index) from array 3559 CLParamIndexMap map; 3560 for (INT i = 0; i < nCount; ++i) 3561 { 3562 LPARAM lParam = m_ListView.GetItemData(array[i]); 3563 map.Add(lParam, i); 3564 } 3565 3566 // finally sort 3567 m_ListView.SortItems(SelectionMoveCompareFunc, &map); 3568 } 3569 3570 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 3571 { 3572 ImageList_DragLeave(m_hWnd); 3573 ImageList_EndDrag(); 3574 3575 if ((IsDropOnSource(NULL) == S_OK) && 3576 (*pdwEffect & DROPEFFECT_MOVE) && 3577 (m_grfKeyState & MK_LBUTTON)) 3578 { 3579 if (m_pCurDropTarget) 3580 { 3581 m_pCurDropTarget->DragLeave(); 3582 m_pCurDropTarget.Release(); 3583 } 3584 3585 POINT ptDrop = { pt.x, pt.y }; 3586 ::ScreenToClient(m_ListView, &ptDrop); 3587 ::ClientToListView(m_ListView, &ptDrop); 3588 m_ptLastMousePos = ptDrop; 3589 3590 m_ListView.SetRedraw(FALSE); 3591 if (m_ListView.GetStyle() & LVS_AUTOARRANGE) 3592 { 3593 _MoveSelectionOnAutoArrange(m_ptLastMousePos); 3594 } 3595 else 3596 { 3597 POINT ptItem; 3598 INT iItem = -1; 3599 while ((iItem = m_ListView.GetNextItem(iItem, LVNI_SELECTED)) >= 0) 3600 { 3601 if (m_ListView.GetItemPosition(iItem, &ptItem)) 3602 { 3603 ptItem.x += m_ptLastMousePos.x - m_ptFirstMousePos.x; 3604 ptItem.y += m_ptLastMousePos.y - m_ptFirstMousePos.y; 3605 m_ListView.SetItemPosition(iItem, &ptItem); 3606 } 3607 } 3608 } 3609 m_ListView.SetRedraw(TRUE); 3610 } 3611 else if (m_pCurDropTarget) 3612 { 3613 m_pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect); 3614 m_pCurDropTarget.Release(); 3615 } 3616 3617 m_pCurDataObject.Release(); 3618 m_iDragOverItem = 0; 3619 return S_OK; 3620 } 3621 3622 /********************************************************** 3623 * ISVDropSource implementation 3624 */ 3625 3626 HRESULT WINAPI CDefView::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) 3627 { 3628 TRACE("(%p)\n", this); 3629 3630 if (fEscapePressed) 3631 return DRAGDROP_S_CANCEL; 3632 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON)) 3633 return DRAGDROP_S_DROP; 3634 else 3635 return S_OK; 3636 } 3637 3638 HRESULT WINAPI CDefView::GiveFeedback(DWORD dwEffect) 3639 { 3640 TRACE("(%p)\n", this); 3641 3642 return DRAGDROP_S_USEDEFAULTCURSORS; 3643 } 3644 3645 /********************************************************** 3646 * ISVViewObject implementation 3647 */ 3648 3649 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) 3650 { 3651 FIXME("Stub: this=%p\n", this); 3652 3653 return E_NOTIMPL; 3654 } 3655 3656 HRESULT WINAPI CDefView::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet) 3657 { 3658 FIXME("Stub: this=%p\n", this); 3659 3660 return E_NOTIMPL; 3661 } 3662 3663 HRESULT WINAPI CDefView::Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze) 3664 { 3665 FIXME("Stub: this=%p\n", this); 3666 3667 return E_NOTIMPL; 3668 } 3669 3670 HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze) 3671 { 3672 FIXME("Stub: this=%p\n", this); 3673 3674 return E_NOTIMPL; 3675 } 3676 3677 HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink) 3678 { 3679 FIXME("partial stub: %p 0x%08x 0x%08x %p\n", this, aspects, advf, pAdvSink); 3680 3681 /* FIXME: we set the AdviseSink, but never use it to send any advice */ 3682 m_pAdvSink = pAdvSink; 3683 m_dwAspects = aspects; 3684 m_dwAdvf = advf; 3685 3686 return S_OK; 3687 } 3688 3689 HRESULT WINAPI CDefView::GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink) 3690 { 3691 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects, pAdvf, ppAdvSink); 3692 3693 if (ppAdvSink) 3694 { 3695 *ppAdvSink = m_pAdvSink; 3696 m_pAdvSink.p->AddRef(); 3697 } 3698 3699 if (pAspects) 3700 *pAspects = m_dwAspects; 3701 3702 if (pAdvf) 3703 *pAdvf = m_dwAdvf; 3704 3705 return S_OK; 3706 } 3707 3708 HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) 3709 { 3710 if (IsEqualIID(guidService, SID_IShellBrowser)) 3711 return m_pShellBrowser->QueryInterface(riid, ppvObject); 3712 else if(IsEqualIID(guidService, SID_IFolderView)) 3713 return QueryInterface(riid, ppvObject); 3714 3715 return E_NOINTERFACE; 3716 } 3717 3718 HRESULT CDefView::_MergeToolbar() 3719 { 3720 CComPtr<IExplorerToolbar> ptb; 3721 HRESULT hr = S_OK; 3722 3723 hr = IUnknown_QueryService(m_pShellBrowser, IID_IExplorerToolbar, IID_PPV_ARG(IExplorerToolbar, &ptb)); 3724 if (FAILED(hr)) 3725 return hr; 3726 3727 m_Category = CGID_DefViewFrame; 3728 3729 hr = ptb->SetCommandTarget(static_cast<IOleCommandTarget*>(this), &m_Category, 0); 3730 if (FAILED(hr)) 3731 return hr; 3732 3733 if (hr == S_FALSE) 3734 return S_OK; 3735 3736 #if 0 3737 hr = ptb->AddButtons(&m_Category, buttonsCount, buttons); 3738 if (FAILED(hr)) 3739 return hr; 3740 #endif 3741 3742 return S_OK; 3743 } 3744 3745 HRESULT CDefView::_DoFolderViewCB(UINT uMsg, WPARAM wParam, LPARAM lParam) 3746 { 3747 HRESULT hr = E_NOTIMPL; 3748 3749 if (m_pShellFolderViewCB) 3750 { 3751 hr = m_pShellFolderViewCB->MessageSFVCB(uMsg, wParam, lParam); 3752 } 3753 3754 return hr; 3755 } 3756 3757 HRESULT CDefView_CreateInstance(IShellFolder *pFolder, REFIID riid, LPVOID * ppvOut) 3758 { 3759 return ShellObjectCreatorInit<CDefView>(pFolder, riid, ppvOut); 3760 } 3761 3762 HRESULT WINAPI SHCreateShellFolderViewEx( 3763 LPCSFV psvcbi, /* [in] shelltemplate struct */ 3764 IShellView **ppsv) /* [out] IShellView pointer */ 3765 { 3766 CComPtr<IShellView> psv; 3767 HRESULT hRes; 3768 3769 TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n", 3770 psvcbi->pshf, psvcbi->pidl, psvcbi->pfnCallback, 3771 psvcbi->fvm, psvcbi->psvOuter); 3772 3773 *ppsv = NULL; 3774 hRes = CDefView_CreateInstance(psvcbi->pshf, IID_PPV_ARG(IShellView, &psv)); 3775 if (FAILED_UNEXPECTEDLY(hRes)) 3776 return hRes; 3777 3778 *ppsv = psv.Detach(); 3779 return hRes; 3780 } 3781 3782 HRESULT WINAPI SHCreateShellFolderView(const SFV_CREATE *pcsfv, 3783 IShellView **ppsv) 3784 { 3785 CComPtr<IShellView> psv; 3786 HRESULT hRes; 3787 3788 if (!ppsv) 3789 return E_INVALIDARG; 3790 3791 *ppsv = NULL; 3792 3793 if (!pcsfv || pcsfv->cbSize != sizeof(*pcsfv)) 3794 return E_INVALIDARG; 3795 3796 TRACE("sf=%p outer=%p callback=%p\n", 3797 pcsfv->pshf, pcsfv->psvOuter, pcsfv->psfvcb); 3798 3799 hRes = CDefView_CreateInstance(pcsfv->pshf, IID_PPV_ARG(IShellView, &psv)); 3800 if (FAILED(hRes)) 3801 return hRes; 3802 3803 if (pcsfv->psfvcb) 3804 { 3805 CComPtr<IShellFolderView> sfv; 3806 if (SUCCEEDED(psv->QueryInterface(IID_PPV_ARG(IShellFolderView, &sfv)))) 3807 { 3808 sfv->SetCallback(pcsfv->psfvcb, NULL); 3809 } 3810 } 3811 3812 *ppsv = psv.Detach(); 3813 return hRes; 3814 } 3815