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 SHFree(reinterpret_cast<LPVOID>(lvItem.lParam)); 865 lvItem.mask = LVIF_PARAM | LVIF_IMAGE | LVIF_TEXT; 866 lvItem.iItem = nItem; 867 lvItem.iSubItem = 0; 868 lvItem.lParam = reinterpret_cast<LPARAM>(ILClone(pidlNew)); /* set the item's data */ 869 lvItem.pszText = LPSTR_TEXTCALLBACKW; 870 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0); 871 m_ListView.SetItem(&lvItem); 872 m_ListView.Update(nItem); 873 return TRUE; /* FIXME: better handling */ 874 } 875 876 return FALSE; 877 } 878 879 /********************************************************** 880 * LV_ProdItem() 881 */ 882 BOOLEAN CDefView::LV_ProdItem(PCUITEMID_CHILD pidl) 883 { 884 int nItem; 885 LVITEMW lvItem; 886 887 TRACE("(%p)(pidl=%p)\n", this, pidl); 888 889 nItem = LV_FindItemByPidl(pidl); 890 891 if (-1 != nItem) 892 { 893 lvItem.mask = LVIF_IMAGE; 894 lvItem.iItem = nItem; 895 lvItem.iSubItem = 0; 896 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0); 897 m_ListView.SetItem(&lvItem); 898 m_ListView.Update(nItem); 899 return TRUE; 900 } 901 902 return FALSE; 903 } 904 905 /********************************************************** 906 * ShellView_FillList() 907 * 908 * - gets the objectlist from the shellfolder 909 * - sorts the list 910 * - fills the list into the view 911 */ 912 INT CALLBACK CDefView::fill_list(LPVOID ptr, LPVOID arg) 913 { 914 PITEMID_CHILD pidl = static_cast<PITEMID_CHILD>(ptr); 915 CDefView *pThis = static_cast<CDefView *>(arg); 916 917 /* in a commdlg This works as a filemask*/ 918 if (pThis->IncludeObject(pidl) == S_OK) 919 pThis->LV_AddItem(pidl); 920 921 SHFree(pidl); 922 return TRUE; 923 } 924 925 HRESULT CDefView::FillList() 926 { 927 CComPtr<IEnumIDList> pEnumIDList; 928 PITEMID_CHILD pidl; 929 DWORD dwFetched; 930 HRESULT hRes; 931 HDPA hdpa; 932 DWORD dFlags = SHCONTF_NONFOLDERS | SHCONTF_FOLDERS; 933 DWORD dwValue, cbValue; 934 935 TRACE("%p\n", this); 936 937 /* determine if there is a setting to show all the hidden files/folders */ 938 dwValue = 1; 939 cbValue = sizeof(dwValue); 940 SHGetValueW(HKEY_CURRENT_USER, 941 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", 942 L"Hidden", NULL, &dwValue, &cbValue); 943 if (dwValue == 1) 944 { 945 dFlags |= SHCONTF_INCLUDEHIDDEN; 946 m_ListView.SendMessageW(LVM_SETCALLBACKMASK, LVIS_CUT, 0); 947 } 948 949 dwValue = 0; 950 cbValue = sizeof(dwValue); 951 SHGetValueW(HKEY_CURRENT_USER, 952 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", 953 L"ShowSuperHidden", NULL, &dwValue, &cbValue); 954 if (dwValue) 955 { 956 dFlags |= SHCONTF_INCLUDESUPERHIDDEN; 957 m_ListView.SendMessageW(LVM_SETCALLBACKMASK, LVIS_CUT, 0); 958 } 959 960 /* get the itemlist from the shfolder */ 961 hRes = m_pSFParent->EnumObjects(m_hWnd, dFlags, &pEnumIDList); 962 if (hRes != S_OK) 963 { 964 if (hRes == S_FALSE) 965 return(NOERROR); 966 return(hRes); 967 } 968 969 /* create a pointer array */ 970 hdpa = DPA_Create(16); 971 if (!hdpa) 972 { 973 return(E_OUTOFMEMORY); 974 } 975 976 /* copy the items into the array*/ 977 while((S_OK == pEnumIDList->Next(1, &pidl, &dwFetched)) && dwFetched) 978 { 979 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1) 980 { 981 SHFree(pidl); 982 } 983 } 984 985 /*turn the listview's redrawing off*/ 986 m_ListView.SetRedraw(FALSE); 987 988 DPA_DestroyCallback( hdpa, fill_list, this); 989 990 /* sort the array */ 991 if (m_pSF2Parent) 992 { 993 m_pSF2Parent->GetDefaultColumn(NULL, (ULONG*)&m_sortInfo.nHeaderID, NULL); 994 } 995 else 996 { 997 FIXME("no m_pSF2Parent\n"); 998 } 999 m_sortInfo.bIsAscending = TRUE; 1000 _Sort(); 1001 1002 if (m_viewinfo_data.hbmBack) 1003 { 1004 ::DeleteObject(m_viewinfo_data.hbmBack); 1005 m_viewinfo_data.hbmBack = NULL; 1006 } 1007 1008 // load custom background image and custom text color 1009 m_viewinfo_data.cbSize = sizeof(m_viewinfo_data); 1010 _DoFolderViewCB(SFVM_GET_CUSTOMVIEWINFO, 0, (LPARAM)&m_viewinfo_data); 1011 1012 /*turn the listview's redrawing back on and force it to draw*/ 1013 m_ListView.SetRedraw(TRUE); 1014 1015 UpdateListColors(); 1016 1017 if (!(m_FolderSettings.fFlags & FWF_DESKTOP)) 1018 { 1019 // redraw now 1020 m_ListView.InvalidateRect(NULL, TRUE); 1021 } 1022 1023 _DoFolderViewCB(SFVM_LISTREFRESHED, 0, 0); 1024 1025 return S_OK; 1026 } 1027 1028 LRESULT CDefView::OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1029 { 1030 m_ListView.UpdateWindow(); 1031 bHandled = FALSE; 1032 return 0; 1033 } 1034 1035 LRESULT CDefView::OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1036 { 1037 return m_ListView.SendMessageW(uMsg, 0, 0); 1038 } 1039 1040 LRESULT CDefView::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1041 { 1042 if (!m_Destroyed) 1043 { 1044 m_Destroyed = TRUE; 1045 if (m_hMenu) 1046 { 1047 DestroyMenu(m_hMenu); 1048 m_hMenu = NULL; 1049 } 1050 RevokeDragDrop(m_hWnd); 1051 SHChangeNotifyDeregister(m_hNotify); 1052 m_hNotify = NULL; 1053 SHFree(m_pidlParent); 1054 m_pidlParent = NULL; 1055 } 1056 bHandled = FALSE; 1057 return 0; 1058 } 1059 1060 LRESULT CDefView::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1061 { 1062 /* redirect to parent */ 1063 if (m_FolderSettings.fFlags & (FWF_DESKTOP | FWF_TRANSPARENT)) 1064 return SendMessageW(GetParent(), WM_ERASEBKGND, wParam, lParam); 1065 1066 bHandled = FALSE; 1067 return 0; 1068 } 1069 1070 static VOID 1071 DrawTileBitmap(HDC hDC, LPCRECT prc, HBITMAP hbm, INT nWidth, INT nHeight, INT dx, INT dy) 1072 { 1073 INT x0 = prc->left, y0 = prc->top, x1 = prc->right, y1 = prc->bottom; 1074 x0 += dx; 1075 y0 += dy; 1076 1077 HDC hMemDC = CreateCompatibleDC(hDC); 1078 HGDIOBJ hbmOld = SelectObject(hMemDC, hbm); 1079 1080 for (INT y = y0; y < y1; y += nHeight) 1081 { 1082 for (INT x = x0; x < x1; x += nWidth) 1083 { 1084 BitBlt(hDC, x, y, nWidth, nHeight, hMemDC, 0, 0, SRCCOPY); 1085 } 1086 } 1087 1088 SelectObject(hMemDC, hbmOld); 1089 DeleteDC(hMemDC); 1090 } 1091 1092 LRESULT CDefView::OnPrintClient(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1093 { 1094 HDC hDC = (HDC)wParam; 1095 1096 RECT rc; 1097 ::GetClientRect(m_ListView, &rc); 1098 1099 if (m_viewinfo_data.hbmBack) 1100 { 1101 BITMAP bm; 1102 if (::GetObject(m_viewinfo_data.hbmBack, sizeof(BITMAP), &bm)) 1103 { 1104 INT dx = -(::GetScrollPos(m_ListView, SB_HORZ) % bm.bmWidth); 1105 INT dy = -(::GetScrollPos(m_ListView, SB_VERT) % bm.bmHeight); 1106 DrawTileBitmap(hDC, &rc, m_viewinfo_data.hbmBack, bm.bmWidth, bm.bmHeight, dx, dy); 1107 } 1108 } 1109 else 1110 { 1111 FillRect(hDC, &rc, GetSysColorBrush(COLOR_WINDOW)); 1112 } 1113 1114 bHandled = TRUE; 1115 1116 return TRUE; 1117 } 1118 1119 LRESULT CDefView::OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1120 { 1121 /* Update desktop labels color */ 1122 UpdateListColors(); 1123 1124 /* Forward WM_SYSCOLORCHANGE to common controls */ 1125 return m_ListView.SendMessageW(uMsg, 0, 0); 1126 } 1127 1128 LRESULT CDefView::OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1129 { 1130 return reinterpret_cast<LRESULT>(m_pShellBrowser.p); 1131 } 1132 1133 LRESULT CDefView::OnNCCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1134 { 1135 this->AddRef(); 1136 bHandled = FALSE; 1137 return 0; 1138 } 1139 1140 LRESULT CDefView::OnNCDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1141 { 1142 this->Release(); 1143 bHandled = FALSE; 1144 return 0; 1145 } 1146 1147 /********************************************************** 1148 * ShellView_OnCreate() 1149 */ 1150 LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1151 { 1152 CComPtr<IDropTarget> pdt; 1153 CComPtr<IPersistFolder2> ppf2; 1154 1155 TRACE("%p\n", this); 1156 1157 if (SUCCEEDED(QueryInterface(IID_PPV_ARG(IDropTarget, &pdt)))) 1158 { 1159 if (FAILED(RegisterDragDrop(m_hWnd, pdt))) 1160 ERR("Registering Drag Drop Failed"); 1161 } 1162 1163 /* register for receiving notifications */ 1164 m_pSFParent->QueryInterface(IID_PPV_ARG(IPersistFolder2, &ppf2)); 1165 if (ppf2) 1166 { 1167 ppf2->GetCurFolder(&m_pidlParent); 1168 } 1169 1170 if (CreateList()) 1171 { 1172 if (InitList()) 1173 { 1174 FillList(); 1175 } 1176 } 1177 1178 if (m_FolderSettings.fFlags & FWF_DESKTOP) 1179 { 1180 HWND hwndSB; 1181 m_pShellBrowser->GetWindow(&hwndSB); 1182 SetShellWindowEx(hwndSB, m_ListView); 1183 } 1184 1185 SHChangeNotifyEntry ntreg[1]; 1186 ntreg[0].fRecursive = FALSE; 1187 ntreg[0].pidl = m_pidlParent; 1188 m_hNotify = SHChangeNotifyRegister(m_hWnd, 1189 SHCNRF_InterruptLevel | SHCNRF_ShellLevel | 1190 SHCNRF_NewDelivery, 1191 SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1192 1, ntreg); 1193 1194 /* _DoFolderViewCB(SFVM_GETNOTIFY, ?? ??) */ 1195 1196 m_hAccel = LoadAcceleratorsW(shell32_hInstance, MAKEINTRESOURCEW(IDA_SHELLVIEW)); 1197 1198 UpdateStatusbar(); 1199 1200 return S_OK; 1201 } 1202 1203 /********************************************************** 1204 * #### Handling of the menus #### 1205 */ 1206 1207 extern "C" DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID); 1208 1209 HMENU GetSubmenuByID(HMENU hmenu, UINT id) 1210 { 1211 MENUITEMINFOW mii = {sizeof(mii), MIIM_SUBMENU}; 1212 if (::GetMenuItemInfoW(hmenu, id, FALSE, &mii)) 1213 return mii.hSubMenu; 1214 1215 return NULL; 1216 } 1217 1218 /* ReallyGetMenuItemID returns the id of an item even if it opens a submenu, 1219 GetMenuItemID returns -1 if the specified item opens a submenu */ 1220 UINT ReallyGetMenuItemID(HMENU hmenu, int i) 1221 { 1222 MENUITEMINFOW mii = {sizeof(mii), MIIM_ID}; 1223 if (::GetMenuItemInfoW(hmenu, i, TRUE, &mii)) 1224 return mii.wID; 1225 1226 return UINT_MAX; 1227 } 1228 1229 HRESULT CDefView::FillFileMenu() 1230 { 1231 HMENU hFileMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_FILE); 1232 if (!hFileMenu) 1233 return E_FAIL; 1234 1235 /* Cleanup the items added previously */ 1236 for (int i = GetMenuItemCount(hFileMenu) - 1; i >= 0; i--) 1237 { 1238 UINT id = GetMenuItemID(hFileMenu, i); 1239 if (id < FCIDM_BROWSERFIRST || id > FCIDM_BROWSERLAST) 1240 DeleteMenu(hFileMenu, i, MF_BYPOSITION); 1241 } 1242 1243 m_cidl = m_ListView.GetSelectedCount(); 1244 1245 /* Store the context menu in m_pCM and keep it in order to invoke the selected command later on */ 1246 HRESULT hr = GetItemObject((m_cidl ? SVGIO_SELECTION : SVGIO_BACKGROUND), 1247 IID_PPV_ARG(IContextMenu, &m_pCM)); 1248 if (FAILED_UNEXPECTEDLY(hr)) 1249 return hr; 1250 1251 HMENU hmenu = CreatePopupMenu(); 1252 1253 hr = m_pCM->QueryContextMenu(hmenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0); 1254 if (FAILED_UNEXPECTEDLY(hr)) 1255 return hr; 1256 1257 // TODO: filter or something 1258 1259 Shell_MergeMenus(hFileMenu, hmenu, 0, 0, 0xFFFF, MM_ADDSEPARATOR | MM_SUBMENUSHAVEIDS); 1260 1261 ::DestroyMenu(hmenu); 1262 1263 return S_OK; 1264 } 1265 1266 HRESULT CDefView::FillEditMenu() 1267 { 1268 HMENU hEditMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_EDIT); 1269 if (!hEditMenu) 1270 return E_FAIL; 1271 1272 HMENU hmenuContents = ::LoadMenuW(shell32_hInstance, L"MENU_003"); 1273 if (!hmenuContents) 1274 return E_FAIL; 1275 1276 Shell_MergeMenus(hEditMenu, hmenuContents, 0, 0, 0xFFFF, 0); 1277 1278 ::DestroyMenu(hmenuContents); 1279 1280 return S_OK; 1281 } 1282 1283 HRESULT CDefView::FillViewMenu() 1284 { 1285 HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW); 1286 if (!hViewMenu) 1287 return E_FAIL; 1288 1289 m_hMenuViewModes = ::LoadMenuW(shell32_hInstance, L"MENU_001"); 1290 if (!m_hMenuViewModes) 1291 return E_FAIL; 1292 1293 UINT i = SHMenuIndexFromID(hViewMenu, FCIDM_MENU_VIEW_SEP_OPTIONS); 1294 Shell_MergeMenus(hViewMenu, m_hMenuViewModes, i, 0, 0xFFFF, MM_ADDSEPARATOR | MM_DONTREMOVESEPS | MM_SUBMENUSHAVEIDS); 1295 1296 return S_OK; 1297 } 1298 1299 HRESULT CDefView::FillArrangeAsMenu(HMENU hmenuArrange) 1300 { 1301 /* We only need to fill this once */ 1302 if (GetMenuItemID(hmenuArrange, 0) == FCIDM_SHVIEW_AUTOARRANGE) 1303 { 1304 Shell_MergeMenus(hmenuArrange, m_hMenuArrangeModes, 0, 0, 0xFFFF,0); 1305 } 1306 1307 /* Also check the menu item according to which we sort */ 1308 CheckMenuRadioItem(hmenuArrange, 1309 0x30, 1310 0x100, 1311 m_sortInfo.nHeaderID + 0x30, 1312 MF_BYCOMMAND); 1313 1314 if (m_FolderSettings.ViewMode == FVM_DETAILS || m_FolderSettings.ViewMode == FVM_LIST) 1315 { 1316 EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_BYCOMMAND | MF_GRAYED); 1317 EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_ALIGNTOGRID, MF_BYCOMMAND | MF_GRAYED); 1318 } 1319 else 1320 { 1321 EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_BYCOMMAND); 1322 EnableMenuItem(hmenuArrange, FCIDM_SHVIEW_ALIGNTOGRID, MF_BYCOMMAND); 1323 1324 if (GetAutoArrange() == S_OK) 1325 CheckMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_CHECKED); 1326 else 1327 CheckMenuItem(hmenuArrange, FCIDM_SHVIEW_AUTOARRANGE, MF_UNCHECKED); 1328 1329 if (_GetSnapToGrid() == S_OK) 1330 CheckMenuItem(hmenuArrange, FCIDM_SHVIEW_ALIGNTOGRID, MF_CHECKED); 1331 else 1332 CheckMenuItem(hmenuArrange, FCIDM_SHVIEW_ALIGNTOGRID, MF_UNCHECKED); 1333 } 1334 1335 1336 return S_OK; 1337 } 1338 1339 HRESULT CDefView::CheckViewMode(HMENU hmenuView) 1340 { 1341 if (m_FolderSettings.ViewMode >= FVM_FIRST && m_FolderSettings.ViewMode <= FVM_LAST) 1342 { 1343 UINT iItemFirst = FCIDM_SHVIEW_BIGICON; 1344 UINT iItemLast = iItemFirst + FVM_LAST - FVM_FIRST; 1345 UINT iItem = iItemFirst + m_FolderSettings.ViewMode - FVM_FIRST; 1346 CheckMenuRadioItem(hmenuView, iItemFirst, iItemLast, iItem, MF_BYCOMMAND); 1347 } 1348 1349 return S_OK; 1350 } 1351 1352 /********************************************************** 1353 * ShellView_GetSelections() 1354 * 1355 * - fills the m_apidl list with the selected objects 1356 * 1357 * RETURNS 1358 * number of selected items 1359 */ 1360 UINT CDefView::GetSelections() 1361 { 1362 SHFree(m_apidl); 1363 1364 m_cidl = m_ListView.GetSelectedCount(); 1365 m_apidl = static_cast<PCUITEMID_CHILD*>(SHAlloc(m_cidl * sizeof(PCUITEMID_CHILD))); 1366 if (!m_apidl) 1367 { 1368 m_cidl = 0; 1369 return 0; 1370 } 1371 1372 TRACE("-- Items selected =%u\n", m_cidl); 1373 1374 UINT i = 0; 1375 int lvIndex = -1; 1376 while ((lvIndex = m_ListView.GetNextItem(lvIndex, LVNI_SELECTED)) > -1) 1377 { 1378 m_apidl[i] = _PidlByItem(lvIndex); 1379 i++; 1380 if (i == m_cidl) 1381 break; 1382 TRACE("-- selected Item found\n"); 1383 } 1384 1385 return m_cidl; 1386 } 1387 1388 HRESULT CDefView::InvokeContextMenuCommand(UINT uCommand) 1389 { 1390 CMINVOKECOMMANDINFO cmi; 1391 1392 ZeroMemory(&cmi, sizeof(cmi)); 1393 cmi.cbSize = sizeof(cmi); 1394 cmi.lpVerb = MAKEINTRESOURCEA(uCommand); 1395 cmi.hwnd = m_hWnd; 1396 1397 if (GetKeyState(VK_SHIFT) & 0x8000) 1398 cmi.fMask |= CMIC_MASK_SHIFT_DOWN; 1399 1400 if (GetKeyState(VK_CONTROL) & 0x8000) 1401 cmi.fMask |= CMIC_MASK_CONTROL_DOWN; 1402 1403 HRESULT hr = m_pCM->InvokeCommand(&cmi); 1404 if (FAILED_UNEXPECTEDLY(hr)) 1405 return hr; 1406 1407 return S_OK; 1408 } 1409 1410 /********************************************************** 1411 * ShellView_OpenSelectedItems() 1412 */ 1413 HRESULT CDefView::OpenSelectedItems() 1414 { 1415 HMENU hMenu; 1416 UINT uCommand; 1417 HRESULT hResult; 1418 1419 m_cidl = m_ListView.GetSelectedCount(); 1420 if (m_cidl == 0) 1421 return S_OK; 1422 1423 hResult = OnDefaultCommand(); 1424 if (hResult == S_OK) 1425 return hResult; 1426 1427 hMenu = CreatePopupMenu(); 1428 if (!hMenu) 1429 return E_FAIL; 1430 1431 hResult = GetItemObject(SVGIO_SELECTION, IID_PPV_ARG(IContextMenu, &m_pCM)); 1432 if (FAILED_UNEXPECTEDLY(hResult)) 1433 goto cleanup; 1434 1435 hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_DEFAULTONLY); 1436 if (FAILED_UNEXPECTEDLY(hResult)) 1437 goto cleanup; 1438 1439 uCommand = GetMenuDefaultItem(hMenu, FALSE, 0); 1440 if (uCommand == (UINT)-1) 1441 { 1442 hResult = E_FAIL; 1443 goto cleanup; 1444 } 1445 1446 InvokeContextMenuCommand(uCommand); 1447 1448 cleanup: 1449 1450 if (hMenu) 1451 DestroyMenu(hMenu); 1452 1453 if (m_pCM) 1454 { 1455 IUnknown_SetSite(m_pCM, NULL); 1456 m_pCM.Release(); 1457 } 1458 1459 return hResult; 1460 } 1461 1462 /********************************************************** 1463 * ShellView_DoContextMenu() 1464 */ 1465 LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1466 { 1467 int x, y; 1468 UINT uCommand; 1469 HRESULT hResult; 1470 1471 TRACE("(%p)\n", this); 1472 1473 m_hContextMenu = CreatePopupMenu(); 1474 if (!m_hContextMenu) 1475 return E_FAIL; 1476 1477 if (lParam != ~0) // unless app key (menu key) was pressed 1478 { 1479 x = GET_X_LPARAM(lParam); 1480 y = GET_Y_LPARAM(lParam); 1481 1482 LV_HITTESTINFO hittest = { { x, y } }; 1483 ScreenToClient(&hittest.pt); 1484 m_ListView.HitTest(&hittest); 1485 1486 // Right-Clicked item is selected? If selected, no selection change. 1487 // If not selected, then reset the selection and select the item. 1488 if ((hittest.flags & LVHT_ONITEM) && 1489 m_ListView.GetItemState(hittest.iItem, LVIS_SELECTED) != LVIS_SELECTED) 1490 { 1491 SelectItem(hittest.iItem, SVSI_SELECT | SVSI_DESELECTOTHERS | SVSI_ENSUREVISIBLE); 1492 } 1493 } 1494 1495 m_cidl = m_ListView.GetSelectedCount(); 1496 1497 hResult = GetItemObject( m_cidl ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM)); 1498 if (FAILED_UNEXPECTEDLY(hResult)) 1499 goto cleanup; 1500 1501 /* Use 1 as the first id as we want 0 the mean that the user canceled the menu */ 1502 hResult = m_pCM->QueryContextMenu(m_hContextMenu, 0, CONTEXT_MENU_BASE_ID, FCIDM_SHVIEWLAST, CMF_NORMAL); 1503 if (FAILED_UNEXPECTEDLY(hResult)) 1504 goto cleanup; 1505 1506 /* There is no position requested, so try to find one */ 1507 if (lParam == ~0) 1508 { 1509 HWND hFocus = ::GetFocus(); 1510 int lvIndex = -1; 1511 POINT pt; 1512 1513 if (hFocus == m_ListView.m_hWnd || m_ListView.IsChild(hFocus)) 1514 { 1515 /* Is there an item focused and selected? */ 1516 lvIndex = m_ListView.GetNextItem(-1, LVIS_SELECTED|LVIS_FOCUSED); 1517 /* If not, find the first selected item */ 1518 if (lvIndex < 0) 1519 lvIndex = m_ListView.GetNextItem(-1, LVIS_SELECTED); 1520 } 1521 1522 /* We got something */ 1523 if (lvIndex > -1) 1524 { 1525 /* Let's find the center of the icon */ 1526 RECT rc = { LVIR_ICON }; 1527 m_ListView.SendMessage(LVM_GETITEMRECT, lvIndex, (LPARAM)&rc); 1528 pt.x = (rc.right + rc.left) / 2; 1529 pt.y = (rc.bottom + rc.top) / 2; 1530 } 1531 else 1532 { 1533 /* We have to drop it somewhere.. */ 1534 pt.x = pt.y = 0; 1535 } 1536 1537 m_ListView.ClientToScreen(&pt); 1538 x = pt.x; 1539 y = pt.y; 1540 } 1541 1542 uCommand = TrackPopupMenu(m_hContextMenu, 1543 TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, 1544 x, y, 0, m_hWnd, NULL); 1545 if (uCommand == 0) 1546 goto cleanup; 1547 1548 if (uCommand == FCIDM_SHVIEW_OPEN && OnDefaultCommand() == S_OK) 1549 goto cleanup; 1550 1551 InvokeContextMenuCommand(uCommand - CONTEXT_MENU_BASE_ID); 1552 1553 cleanup: 1554 if (m_pCM) 1555 { 1556 IUnknown_SetSite(m_pCM, NULL); 1557 m_pCM.Release(); 1558 } 1559 1560 if (m_hContextMenu) 1561 { 1562 DestroyMenu(m_hContextMenu); 1563 m_hContextMenu = NULL; 1564 } 1565 1566 return 0; 1567 } 1568 1569 LRESULT CDefView::OnExplorerCommand(UINT uCommand, BOOL bUseSelection) 1570 { 1571 HRESULT hResult; 1572 HMENU hMenu; 1573 1574 hMenu = CreatePopupMenu(); 1575 if (!hMenu) 1576 return 0; 1577 1578 hResult = GetItemObject( bUseSelection ? SVGIO_SELECTION : SVGIO_BACKGROUND, IID_PPV_ARG(IContextMenu, &m_pCM)); 1579 if (FAILED_UNEXPECTEDLY( hResult)) 1580 goto cleanup; 1581 1582 hResult = m_pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, CMF_NORMAL); 1583 if (FAILED_UNEXPECTEDLY( hResult)) 1584 goto cleanup; 1585 1586 InvokeContextMenuCommand(uCommand); 1587 1588 cleanup: 1589 if (m_pCM) 1590 { 1591 IUnknown_SetSite(m_pCM, NULL); 1592 m_pCM.Release(); 1593 } 1594 1595 if (hMenu) 1596 DestroyMenu(hMenu); 1597 1598 return 0; 1599 } 1600 1601 /********************************************************** 1602 * ##### message handling ##### 1603 */ 1604 1605 /********************************************************** 1606 * ShellView_OnSize() 1607 */ 1608 LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1609 { 1610 WORD wWidth, wHeight; 1611 1612 wWidth = LOWORD(lParam); 1613 wHeight = HIWORD(lParam); 1614 1615 TRACE("%p width=%u height=%u\n", this, wWidth, wHeight); 1616 1617 /* Resize the ListView to fit our window */ 1618 if (m_ListView) 1619 { 1620 ::MoveWindow(m_ListView, 0, 0, wWidth, wHeight, TRUE); 1621 } 1622 1623 _DoFolderViewCB(SFVM_SIZE, 0, 0); 1624 1625 return 0; 1626 } 1627 1628 /********************************************************** 1629 * ShellView_OnDeactivate() 1630 * 1631 * NOTES 1632 * internal 1633 */ 1634 void CDefView::OnDeactivate() 1635 { 1636 TRACE("%p\n", this); 1637 1638 if (m_uState != SVUIA_DEACTIVATE) 1639 { 1640 // TODO: cleanup menu after deactivation 1641 1642 m_uState = SVUIA_DEACTIVATE; 1643 } 1644 } 1645 1646 void CDefView::DoActivate(UINT uState) 1647 { 1648 TRACE("%p uState=%x\n", this, uState); 1649 1650 /*don't do anything if the state isn't really changing */ 1651 if (m_uState == uState) 1652 { 1653 return; 1654 } 1655 1656 if (uState == SVUIA_DEACTIVATE) 1657 { 1658 OnDeactivate(); 1659 } 1660 else 1661 { 1662 if(m_hMenu && !m_bmenuBarInitialized) 1663 { 1664 FillEditMenu(); 1665 FillViewMenu(); 1666 m_pShellBrowser->SetMenuSB(m_hMenu, 0, m_hWnd); 1667 m_bmenuBarInitialized = TRUE; 1668 } 1669 1670 if (SVUIA_ACTIVATE_FOCUS == uState) 1671 { 1672 m_ListView.SetFocus(); 1673 } 1674 } 1675 1676 m_uState = uState; 1677 TRACE("--\n"); 1678 } 1679 1680 /********************************************************** 1681 * ShellView_OnActivate() 1682 */ 1683 LRESULT CDefView::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1684 { 1685 DoActivate(SVUIA_ACTIVATE_FOCUS); 1686 return 0; 1687 } 1688 1689 /********************************************************** 1690 * ShellView_OnSetFocus() 1691 * 1692 */ 1693 LRESULT CDefView::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1694 { 1695 TRACE("%p\n", this); 1696 1697 /* Tell the browser one of our windows has received the focus. This 1698 should always be done before merging menus (OnActivate merges the 1699 menus) if one of our windows has the focus.*/ 1700 1701 m_pShellBrowser->OnViewWindowActive(this); 1702 DoActivate(SVUIA_ACTIVATE_FOCUS); 1703 1704 /* Set the focus to the listview */ 1705 m_ListView.SetFocus(); 1706 1707 /* Notify the ICommDlgBrowser interface */ 1708 OnStateChange(CDBOSC_SETFOCUS); 1709 1710 return 0; 1711 } 1712 1713 /********************************************************** 1714 * ShellView_OnKillFocus() 1715 */ 1716 LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1717 { 1718 TRACE("(%p) stub\n", this); 1719 1720 DoActivate(SVUIA_ACTIVATE_NOFOCUS); 1721 /* Notify the ICommDlgBrowser */ 1722 OnStateChange(CDBOSC_KILLFOCUS); 1723 1724 return 0; 1725 } 1726 1727 /********************************************************** 1728 * ShellView_OnCommand() 1729 * 1730 * NOTES 1731 * the CmdID's are the ones from the context menu 1732 */ 1733 LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1734 { 1735 DWORD dwCmdID; 1736 DWORD dwCmd; 1737 HWND hwndCmd; 1738 int nCount; 1739 1740 dwCmdID = GET_WM_COMMAND_ID(wParam, lParam); 1741 dwCmd = GET_WM_COMMAND_CMD(wParam, lParam); 1742 hwndCmd = GET_WM_COMMAND_HWND(wParam, lParam); 1743 1744 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n", this, dwCmdID, dwCmd, hwndCmd); 1745 1746 switch (dwCmdID) 1747 { 1748 case FCIDM_SHVIEW_SMALLICON: 1749 m_FolderSettings.ViewMode = FVM_SMALLICON; 1750 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_SMALLICON); 1751 CheckToolbar(); 1752 break; 1753 1754 case FCIDM_SHVIEW_BIGICON: 1755 m_FolderSettings.ViewMode = FVM_ICON; 1756 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_ICON); 1757 CheckToolbar(); 1758 break; 1759 1760 case FCIDM_SHVIEW_LISTVIEW: 1761 m_FolderSettings.ViewMode = FVM_LIST; 1762 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_LIST); 1763 CheckToolbar(); 1764 break; 1765 1766 case FCIDM_SHVIEW_REPORTVIEW: 1767 m_FolderSettings.ViewMode = FVM_DETAILS; 1768 m_ListView.ModifyStyle(LVS_TYPEMASK, LVS_REPORT); 1769 CheckToolbar(); 1770 break; 1771 1772 /* the menu-ID's for sorting are 0x30... see shrec.rc */ 1773 case 0x30: 1774 case 0x31: 1775 case 0x32: 1776 case 0x33: 1777 m_sortInfo.nHeaderID = dwCmdID - 0x30; 1778 m_sortInfo.bIsAscending = TRUE; 1779 _Sort(); 1780 break; 1781 1782 case FCIDM_SHVIEW_SNAPTOGRID: 1783 m_ListView.Arrange(LVA_SNAPTOGRID); 1784 break; 1785 case FCIDM_SHVIEW_ALIGNTOGRID: 1786 if (_GetSnapToGrid() == S_OK) 1787 m_ListView.SetExtendedListViewStyle(0, LVS_EX_SNAPTOGRID); 1788 else 1789 ArrangeGrid(); 1790 break; 1791 case FCIDM_SHVIEW_AUTOARRANGE: 1792 if (GetAutoArrange() == S_OK) 1793 m_ListView.ModifyStyle(LVS_AUTOARRANGE, 0); 1794 else 1795 AutoArrange(); 1796 break; 1797 case FCIDM_SHVIEW_SELECTALL: 1798 m_ListView.SetItemState(-1, LVIS_SELECTED, LVIS_SELECTED); 1799 break; 1800 1801 case FCIDM_SHVIEW_INVERTSELECTION: 1802 nCount = m_ListView.GetItemCount(); 1803 for (int i=0; i < nCount; i++) 1804 m_ListView.SetItemState(i, m_ListView.GetItemState(i, LVIS_SELECTED) ? 0 : LVIS_SELECTED, LVIS_SELECTED); 1805 break; 1806 1807 case FCIDM_SHVIEW_REFRESH: 1808 Refresh(); 1809 break; 1810 1811 case FCIDM_SHVIEW_DELETE: 1812 case FCIDM_SHVIEW_CUT: 1813 case FCIDM_SHVIEW_COPY: 1814 case FCIDM_SHVIEW_RENAME: 1815 case FCIDM_SHVIEW_PROPERTIES: 1816 case FCIDM_SHVIEW_COPYTO: 1817 case FCIDM_SHVIEW_MOVETO: 1818 return OnExplorerCommand(dwCmdID, TRUE); 1819 1820 case FCIDM_SHVIEW_INSERT: 1821 case FCIDM_SHVIEW_UNDO: 1822 case FCIDM_SHVIEW_INSERTLINK: 1823 case FCIDM_SHVIEW_NEWFOLDER: 1824 return OnExplorerCommand(dwCmdID, FALSE); 1825 default: 1826 /* WM_COMMAND messages from the file menu are routed to the CDefView so as to let m_pCM handle the command */ 1827 if (m_pCM && dwCmd == 0) 1828 { 1829 InvokeContextMenuCommand(dwCmdID); 1830 } 1831 } 1832 1833 return 0; 1834 } 1835 1836 static BOOL 1837 SelectExtOnRename(void) 1838 { 1839 HKEY hKey; 1840 LONG error; 1841 DWORD dwValue = FALSE, cbValue; 1842 1843 error = RegOpenKeyExW(HKEY_CURRENT_USER, 1844 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer", 1845 0, KEY_READ, &hKey); 1846 if (error) 1847 return dwValue; 1848 1849 cbValue = sizeof(dwValue); 1850 RegQueryValueExW(hKey, L"SelectExtOnRename", NULL, NULL, (LPBYTE)&dwValue, &cbValue); 1851 1852 RegCloseKey(hKey); 1853 return !!dwValue; 1854 } 1855 1856 /********************************************************** 1857 * ShellView_OnNotify() 1858 */ 1859 1860 LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 1861 { 1862 UINT CtlID; 1863 LPNMHDR lpnmh; 1864 LPNMLISTVIEW lpnmlv; 1865 NMLVDISPINFOW *lpdi; 1866 PCUITEMID_CHILD pidl; 1867 BOOL unused; 1868 1869 CtlID = wParam; 1870 lpnmh = (LPNMHDR)lParam; 1871 lpnmlv = (LPNMLISTVIEW)lpnmh; 1872 lpdi = (NMLVDISPINFOW *)lpnmh; 1873 1874 TRACE("%p CtlID=%u lpnmh->code=%x\n", this, CtlID, lpnmh->code); 1875 1876 switch (lpnmh->code) 1877 { 1878 case NM_SETFOCUS: 1879 TRACE("-- NM_SETFOCUS %p\n", this); 1880 OnSetFocus(0, 0, 0, unused); 1881 break; 1882 1883 case NM_KILLFOCUS: 1884 TRACE("-- NM_KILLFOCUS %p\n", this); 1885 OnDeactivate(); 1886 /* Notify the ICommDlgBrowser interface */ 1887 OnStateChange(CDBOSC_KILLFOCUS); 1888 break; 1889 1890 case NM_CUSTOMDRAW: 1891 TRACE("-- NM_CUSTOMDRAW %p\n", this); 1892 return CDRF_DODEFAULT; 1893 1894 case NM_RELEASEDCAPTURE: 1895 TRACE("-- NM_RELEASEDCAPTURE %p\n", this); 1896 break; 1897 1898 case NM_CLICK: 1899 TRACE("-- NM_CLICK %p\n", this); 1900 break; 1901 1902 case NM_RCLICK: 1903 TRACE("-- NM_RCLICK %p\n", this); 1904 break; 1905 1906 case NM_DBLCLK: 1907 TRACE("-- NM_DBLCLK %p\n", this); 1908 OpenSelectedItems(); 1909 break; 1910 1911 case NM_RETURN: 1912 TRACE("-- NM_RETURN %p\n", this); 1913 OpenSelectedItems(); 1914 break; 1915 1916 case HDN_ENDTRACKW: 1917 TRACE("-- HDN_ENDTRACKW %p\n", this); 1918 /*nColumn1 = m_ListView.GetColumnWidth(0); 1919 nColumn2 = m_ListView.GetColumnWidth(1);*/ 1920 break; 1921 1922 case LVN_DELETEITEM: 1923 TRACE("-- LVN_DELETEITEM %p\n", this); 1924 1925 /*delete the pidl because we made a copy of it*/ 1926 SHFree(reinterpret_cast<LPVOID>(lpnmlv->lParam)); 1927 1928 break; 1929 1930 case LVN_DELETEALLITEMS: 1931 TRACE("-- LVN_DELETEALLITEMS %p\n", this); 1932 return FALSE; 1933 1934 case LVN_INSERTITEM: 1935 TRACE("-- LVN_INSERTITEM (STUB)%p\n", this); 1936 break; 1937 1938 case LVN_ITEMACTIVATE: 1939 TRACE("-- LVN_ITEMACTIVATE %p\n", this); 1940 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */ 1941 break; 1942 1943 case LVN_COLUMNCLICK: 1944 m_sortInfo.nHeaderID = lpnmlv->iSubItem; 1945 if (m_sortInfo.nLastHeaderID == m_sortInfo.nHeaderID) 1946 m_sortInfo.bIsAscending = !m_sortInfo.bIsAscending; 1947 else 1948 m_sortInfo.bIsAscending = TRUE; 1949 _Sort(); 1950 break; 1951 1952 case LVN_GETDISPINFOA: 1953 case LVN_GETDISPINFOW: 1954 TRACE("-- LVN_GETDISPINFO %p\n", this); 1955 pidl = _PidlByItem(lpdi->item); 1956 1957 if (lpdi->item.mask & LVIF_TEXT) /* text requested */ 1958 { 1959 if (m_pSF2Parent) 1960 { 1961 SHELLDETAILS sd; 1962 if (FAILED_UNEXPECTEDLY(m_pSF2Parent->GetDetailsOf(pidl, lpdi->item.iSubItem, &sd))) 1963 break; 1964 1965 if (lpnmh->code == LVN_GETDISPINFOA) 1966 { 1967 /* shouldn't happen */ 1968 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh; 1969 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL); 1970 TRACE("-- text=%s\n", lpdiA->item.pszText); 1971 } 1972 else /* LVN_GETDISPINFOW */ 1973 { 1974 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL); 1975 TRACE("-- text=%s\n", debugstr_w(lpdi->item.pszText)); 1976 } 1977 } 1978 else 1979 { 1980 FIXME("no m_pSF2Parent\n"); 1981 } 1982 } 1983 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */ 1984 { 1985 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0); 1986 } 1987 if(lpdi->item.mask & LVIF_STATE) 1988 { 1989 ULONG attributes = SFGAO_HIDDEN; 1990 if (SUCCEEDED(m_pSFParent->GetAttributesOf(1, &pidl, &attributes))) 1991 { 1992 if (attributes & SFGAO_HIDDEN) 1993 { 1994 lpdi->item.state |= LVIS_CUT; 1995 } 1996 } 1997 } 1998 lpdi->item.mask |= LVIF_DI_SETITEM; 1999 break; 2000 2001 case LVN_ITEMCHANGED: 2002 TRACE("-- LVN_ITEMCHANGED %p\n", this); 2003 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */ 2004 UpdateStatusbar(); 2005 _DoFolderViewCB(SFVM_SELECTIONCHANGED, NULL/* FIXME */, NULL/* FIXME */); 2006 break; 2007 2008 case LVN_BEGINDRAG: 2009 case LVN_BEGINRDRAG: 2010 TRACE("-- LVN_BEGINDRAG\n"); 2011 2012 if (GetSelections()) 2013 { 2014 CComPtr<IDataObject> pda; 2015 DWORD dwAttributes = SFGAO_CANCOPY | SFGAO_CANLINK; 2016 DWORD dwEffect = DROPEFFECT_MOVE; 2017 2018 if (SUCCEEDED(m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, IID_NULL_PPV_ARG(IDataObject, &pda)))) 2019 { 2020 LPNMLISTVIEW params = (LPNMLISTVIEW)lParam; 2021 2022 if (SUCCEEDED(m_pSFParent->GetAttributesOf(m_cidl, m_apidl, &dwAttributes))) 2023 { 2024 dwEffect |= dwAttributes & (SFGAO_CANCOPY | SFGAO_CANLINK); 2025 } 2026 2027 CComPtr<IAsyncOperation> piaso; 2028 if (SUCCEEDED(pda->QueryInterface(IID_PPV_ARG(IAsyncOperation, &piaso)))) 2029 { 2030 piaso->SetAsyncMode(TRUE); 2031 } 2032 2033 DWORD dwEffect2; 2034 2035 m_pSourceDataObject = pda; 2036 m_ptFirstMousePos = params->ptAction; 2037 ClientToScreen(&m_ptFirstMousePos); 2038 ::ClientToListView(m_ListView, &m_ptFirstMousePos); 2039 2040 HIMAGELIST big_icons, small_icons; 2041 Shell_GetImageLists(&big_icons, &small_icons); 2042 PCUITEMID_CHILD pidl = _PidlByItem(params->iItem); 2043 int iIcon = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidl, 0); 2044 POINT ptItem; 2045 m_ListView.GetItemPosition(params->iItem, &ptItem); 2046 2047 ImageList_BeginDrag(big_icons, iIcon, params->ptAction.x - ptItem.x, params->ptAction.y - ptItem.y); 2048 2049 DoDragDrop(pda, this, dwEffect, &dwEffect2); 2050 2051 m_pSourceDataObject.Release(); 2052 } 2053 } 2054 break; 2055 2056 case LVN_BEGINLABELEDITW: 2057 { 2058 DWORD dwAttr = SFGAO_CANRENAME; 2059 pidl = _PidlByItem(lpdi->item); 2060 2061 TRACE("-- LVN_BEGINLABELEDITW %p\n", this); 2062 2063 m_pSFParent->GetAttributesOf(1, &pidl, &dwAttr); 2064 if (SFGAO_CANRENAME & dwAttr) 2065 { 2066 HWND hEdit = reinterpret_cast<HWND>(m_ListView.SendMessage(LVM_GETEDITCONTROL)); 2067 SHLimitInputEdit(hEdit, m_pSFParent); 2068 2069 if (!(dwAttr & SFGAO_LINK) && (lpdi->item.mask & LVIF_TEXT) && !SelectExtOnRename()) 2070 { 2071 LPWSTR pszText = lpdi->item.pszText; 2072 LPWSTR pchDotExt = PathFindExtensionW(pszText); 2073 ::PostMessageW(hEdit, EM_SETSEL, 0, pchDotExt - pszText); 2074 ::PostMessageW(hEdit, EM_SCROLLCARET, 0, 0); 2075 } 2076 2077 m_isEditing = TRUE; 2078 return FALSE; 2079 } 2080 2081 return TRUE; 2082 } 2083 2084 case LVN_ENDLABELEDITW: 2085 { 2086 TRACE("-- LVN_ENDLABELEDITW %p\n", this); 2087 2088 m_isEditing = FALSE; 2089 2090 if (lpdi->item.pszText) 2091 { 2092 HRESULT hr; 2093 LVITEMW lvItem; 2094 2095 pidl = _PidlByItem(lpdi->item); 2096 PITEMID_CHILD pidlNew = NULL; 2097 hr = m_pSFParent->SetNameOf(0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidlNew); 2098 2099 if (SUCCEEDED(hr) && pidlNew) 2100 { 2101 lvItem.mask = LVIF_PARAM|LVIF_IMAGE; 2102 lvItem.iItem = lpdi->item.iItem; 2103 lvItem.iSubItem = 0; 2104 lvItem.lParam = reinterpret_cast<LPARAM>(pidlNew); 2105 lvItem.iImage = SHMapPIDLToSystemImageListIndex(m_pSFParent, pidlNew, 0); 2106 m_ListView.SetItem(&lvItem); 2107 m_ListView.Update(lpdi->item.iItem); 2108 return TRUE; 2109 } 2110 } 2111 2112 return FALSE; 2113 } 2114 2115 default: 2116 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh->code); 2117 break; 2118 } 2119 2120 return 0; 2121 } 2122 2123 /* 2124 * This is just a quick hack to make the desktop work correctly. 2125 * ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the way that 2126 * a folder should know if it should update upon a change notification. 2127 * It is exported by merged folders at a minimum. 2128 */ 2129 static BOOL ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1, PCIDLIST_ABSOLUTE pidl2) 2130 { 2131 if (!pidl1 || !pidl2) 2132 return FALSE; 2133 if (ILIsParent(pidl1, pidl2, TRUE)) 2134 return TRUE; 2135 2136 if (_ILIsDesktop(pidl1)) 2137 { 2138 PIDLIST_ABSOLUTE deskpidl; 2139 SHGetFolderLocation(NULL, CSIDL_DESKTOPDIRECTORY, NULL, 0, &deskpidl); 2140 if (ILIsParent(deskpidl, pidl2, TRUE)) 2141 { 2142 ILFree(deskpidl); 2143 return TRUE; 2144 } 2145 ILFree(deskpidl); 2146 SHGetFolderLocation(NULL, CSIDL_COMMON_DESKTOPDIRECTORY, NULL, 0, &deskpidl); 2147 if (ILIsParent(deskpidl, pidl2, TRUE)) 2148 { 2149 ILFree(deskpidl); 2150 return TRUE; 2151 } 2152 ILFree(deskpidl); 2153 } 2154 2155 WCHAR szPath1[MAX_PATH], szPath2[MAX_PATH]; 2156 LPITEMIDLIST pidl2Clone = ILClone(pidl2); 2157 ILRemoveLastID(pidl2Clone); 2158 if (SHGetPathFromIDListW(pidl1, szPath1) && 2159 SHGetPathFromIDListW(pidl2Clone, szPath2)) 2160 { 2161 if (lstrcmpiW(szPath1, szPath2) == 0) 2162 { 2163 ILFree(pidl2Clone); 2164 return TRUE; 2165 } 2166 } 2167 ILFree(pidl2Clone); 2168 2169 return FALSE; 2170 } 2171 2172 /********************************************************** 2173 * ShellView_OnChange() 2174 */ 2175 LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 2176 { 2177 HANDLE hChange = (HANDLE)wParam; 2178 DWORD dwProcID = (DWORD)lParam; 2179 PIDLIST_ABSOLUTE *Pidls; 2180 LONG lEvent; 2181 HANDLE hLock = SHChangeNotification_Lock(hChange, dwProcID, &Pidls, &lEvent); 2182 if (hLock == NULL) 2183 { 2184 ERR("hLock == NULL\n"); 2185 return FALSE; 2186 } 2187 2188 BOOL bParent0 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[0]); 2189 BOOL bParent1 = ILIsParentOrSpecialParent(m_pidlParent, Pidls[1]); 2190 2191 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam); 2192 2193 lEvent &= ~SHCNE_INTERRUPT; 2194 switch (lEvent) 2195 { 2196 case SHCNE_MKDIR: 2197 case SHCNE_CREATE: 2198 if (bParent0) 2199 { 2200 if (LV_FindItemByPidl(ILFindLastID(Pidls[0])) == -1) 2201 { 2202 LV_AddItem(ILFindLastID(Pidls[0])); 2203 } 2204 else 2205 { 2206 LV_ProdItem(ILFindLastID(Pidls[0])); 2207 } 2208 } 2209 break; 2210 2211 case SHCNE_RMDIR: 2212 case SHCNE_DELETE: 2213 if (bParent0) 2214 LV_DeleteItem(ILFindLastID(Pidls[0])); 2215 break; 2216 2217 case SHCNE_RENAMEFOLDER: 2218 case SHCNE_RENAMEITEM: 2219 if (bParent0 && bParent1) 2220 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[1])); 2221 else if (bParent0) 2222 LV_DeleteItem(ILFindLastID(Pidls[0])); 2223 else if (bParent1) 2224 LV_AddItem(ILFindLastID(Pidls[1])); 2225 break; 2226 2227 case SHCNE_UPDATEITEM: 2228 if (bParent0) 2229 LV_RenameItem(ILFindLastID(Pidls[0]), ILFindLastID(Pidls[0])); 2230 break; 2231 2232 case SHCNE_UPDATEDIR: 2233 Refresh(); 2234 break; 2235 } 2236 2237 SHChangeNotification_Unlock(hLock); 2238 return TRUE; 2239 } 2240 2241 HRESULT SHGetMenuIdFromMenuMsg(UINT uMsg, LPARAM lParam, UINT *CmdId); 2242 HRESULT SHSetMenuIdInMenuMsg(UINT uMsg, LPARAM lParam, UINT CmdId); 2243 2244 /********************************************************** 2245 * CDefView::OnCustomItem 2246 */ 2247 LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 2248 { 2249 if (!m_pCM.p) 2250 { 2251 /* no menu */ 2252 ERR("no menu!!!\n"); 2253 return FALSE; 2254 } 2255 2256 /* The lParam of WM_DRAWITEM WM_MEASUREITEM contain a menu id and this also needs to 2257 be changed to a menu identifier offset */ 2258 UINT CmdID; 2259 HRESULT hres = SHGetMenuIdFromMenuMsg(uMsg, lParam, &CmdID); 2260 if (SUCCEEDED(hres)) 2261 SHSetMenuIdInMenuMsg(uMsg, lParam, CmdID - CONTEXT_MENU_BASE_ID); 2262 2263 /* Forward the message to the IContextMenu2 */ 2264 LRESULT result; 2265 hres = SHForwardContextMenuMsg(m_pCM, uMsg, wParam, lParam, &result, TRUE); 2266 2267 return (SUCCEEDED(hres)); 2268 } 2269 2270 LRESULT CDefView::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 2271 { 2272 /* Wallpaper setting affects drop shadows effect */ 2273 if (wParam == SPI_SETDESKWALLPAPER || wParam == 0) 2274 UpdateListColors(); 2275 2276 return S_OK; 2277 } 2278 2279 /********************************************************** 2280 * CDefView::OnInitMenuPopup 2281 */ 2282 LRESULT CDefView::OnInitMenuPopup(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 2283 { 2284 HMENU hmenu = (HMENU) wParam; 2285 int nPos = LOWORD(lParam); 2286 UINT menuItemId; 2287 2288 OnCustomItem(uMsg, wParam, lParam, bHandled); 2289 2290 HMENU hViewMenu = GetSubmenuByID(m_hMenu, FCIDM_MENU_VIEW); 2291 2292 if (GetSelections() == 0) 2293 { 2294 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_CUT, MF_GRAYED); 2295 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPY, MF_GRAYED); 2296 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME, MF_GRAYED); 2297 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPYTO, MF_GRAYED); 2298 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_MOVETO, MF_GRAYED); 2299 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_DELETE, MF_GRAYED); 2300 } 2301 else 2302 { 2303 // FIXME: Check copyable 2304 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_CUT, MF_ENABLED); 2305 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPY, MF_ENABLED); 2306 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_RENAME, MF_ENABLED); 2307 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_COPYTO, MF_ENABLED); 2308 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_MOVETO, MF_ENABLED); 2309 ::EnableMenuItem(hmenu, FCIDM_SHVIEW_DELETE, MF_ENABLED); 2310 } 2311 2312 /* Lets try to find out what the hell wParam is */ 2313 if (hmenu == GetSubMenu(m_hMenu, nPos)) 2314 menuItemId = ReallyGetMenuItemID(m_hMenu, nPos); 2315 else if (hViewMenu && hmenu == GetSubMenu(hViewMenu, nPos)) 2316 menuItemId = ReallyGetMenuItemID(hViewMenu, nPos); 2317 else if (m_hContextMenu && hmenu == GetSubMenu(m_hContextMenu, nPos)) 2318 menuItemId = ReallyGetMenuItemID(m_hContextMenu, nPos); 2319 else 2320 return FALSE; 2321 2322 switch (menuItemId) 2323 { 2324 case FCIDM_MENU_FILE: 2325 FillFileMenu(); 2326 break; 2327 case FCIDM_MENU_VIEW: 2328 case FCIDM_SHVIEW_VIEW: 2329 CheckViewMode(hmenu); 2330 break; 2331 case FCIDM_SHVIEW_ARRANGE: 2332 FillArrangeAsMenu(hmenu); 2333 break; 2334 } 2335 2336 return FALSE; 2337 } 2338 2339 /********************************************************** 2340 * 2341 * 2342 * The INTERFACE of the IShellView object 2343 * 2344 * 2345 ********************************************************** 2346 */ 2347 2348 /********************************************************** 2349 * ShellView_GetWindow 2350 */ 2351 HRESULT WINAPI CDefView::GetWindow(HWND *phWnd) 2352 { 2353 TRACE("(%p)\n", this); 2354 2355 *phWnd = m_hWnd; 2356 2357 return S_OK; 2358 } 2359 2360 HRESULT WINAPI CDefView::ContextSensitiveHelp(BOOL fEnterMode) 2361 { 2362 FIXME("(%p) stub\n", this); 2363 2364 return E_NOTIMPL; 2365 } 2366 2367 /********************************************************** 2368 * IShellView_TranslateAccelerator 2369 * 2370 * FIXME: 2371 * use the accel functions 2372 */ 2373 HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg) 2374 { 2375 if (m_isEditing) 2376 return S_FALSE; 2377 2378 if (lpmsg->message >= WM_KEYFIRST && lpmsg->message <= WM_KEYLAST) 2379 { 2380 if (::TranslateAcceleratorW(m_hWnd, m_hAccel, lpmsg) != 0) 2381 return S_OK; 2382 2383 TRACE("-- key=0x%04lx\n", lpmsg->wParam) ; 2384 } 2385 2386 return m_pShellBrowser->TranslateAcceleratorSB(lpmsg, 0); 2387 } 2388 2389 HRESULT WINAPI CDefView::EnableModeless(BOOL fEnable) 2390 { 2391 FIXME("(%p) stub\n", this); 2392 2393 return E_NOTIMPL; 2394 } 2395 2396 HRESULT WINAPI CDefView::UIActivate(UINT uState) 2397 { 2398 // CHAR szName[MAX_PATH]; 2399 LRESULT lResult; 2400 int nPartArray[1] = { -1}; 2401 2402 TRACE("(%p)->(state=%x) stub\n", this, uState); 2403 2404 /* don't do anything if the state isn't really changing */ 2405 if (m_uState == uState) 2406 { 2407 return S_OK; 2408 } 2409 2410 /* OnActivate handles the menu merging and internal state */ 2411 DoActivate(uState); 2412 2413 /* only do This if we are active */ 2414 if (uState != SVUIA_DEACTIVATE) 2415 { 2416 2417 /* 2418 GetFolderPath is not a method of IShellFolder 2419 IShellFolder_GetFolderPath( m_pSFParent, szName, sizeof(szName) ); 2420 */ 2421 /* set the number of parts */ 2422 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult); 2423 2424 /* set the text for the parts */ 2425 /* 2426 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult); 2427 */ 2428 } 2429 2430 return S_OK; 2431 } 2432 2433 HRESULT WINAPI CDefView::Refresh() 2434 { 2435 TRACE("(%p)\n", this); 2436 2437 _DoFolderViewCB(SFVM_LISTREFRESHED, TRUE, 0); 2438 2439 m_ListView.DeleteAllItems(); 2440 FillList(); 2441 2442 return S_OK; 2443 } 2444 2445 HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd) 2446 { 2447 return CreateViewWindow3(psb, lpPrevView, SV3CVW3_DEFAULT, 2448 (FOLDERFLAGS)lpfs->fFlags, (FOLDERFLAGS)lpfs->fFlags, (FOLDERVIEWMODE)lpfs->ViewMode, NULL, prcView, phWnd); 2449 } 2450 2451 HRESULT WINAPI CDefView::DestroyViewWindow() 2452 { 2453 TRACE("(%p)\n", this); 2454 2455 /* Make absolutely sure all our UI is cleaned up */ 2456 UIActivate(SVUIA_DEACTIVATE); 2457 2458 if (m_hAccel) 2459 { 2460 // "Accelerator tables loaded from resources are freed automatically when the application terminates." -- MSDN 2461 m_hAccel = NULL; 2462 } 2463 2464 if (m_hMenuArrangeModes) 2465 { 2466 DestroyMenu(m_hMenuArrangeModes); 2467 m_hMenuArrangeModes = NULL; 2468 } 2469 2470 if (m_hMenuViewModes) 2471 { 2472 DestroyMenu(m_hMenuViewModes); 2473 m_hMenuViewModes = NULL; 2474 } 2475 2476 if (m_hMenu) 2477 { 2478 DestroyMenu(m_hMenu); 2479 m_hMenu = NULL; 2480 } 2481 2482 if (m_ListView) 2483 { 2484 m_ListView.DestroyWindow(); 2485 } 2486 2487 if (m_hWnd) 2488 { 2489 _DoFolderViewCB(SFVM_WINDOWCLOSING, (WPARAM)m_hWnd, 0); 2490 DestroyWindow(); 2491 } 2492 2493 m_pShellBrowser.Release(); 2494 m_pCommDlgBrowser.Release(); 2495 2496 return S_OK; 2497 } 2498 2499 HRESULT WINAPI CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs) 2500 { 2501 TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs, 2502 m_FolderSettings.ViewMode, m_FolderSettings.fFlags); 2503 2504 if (!lpfs) 2505 return E_INVALIDARG; 2506 2507 *lpfs = m_FolderSettings; 2508 return S_OK; 2509 } 2510 2511 HRESULT WINAPI CDefView::AddPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam) 2512 { 2513 FIXME("(%p) stub\n", this); 2514 2515 return E_NOTIMPL; 2516 } 2517 2518 HRESULT WINAPI CDefView::SaveViewState() 2519 { 2520 FIXME("(%p) stub\n", this); 2521 2522 return S_OK; 2523 } 2524 2525 HRESULT WINAPI CDefView::SelectItem(PCUITEMID_CHILD pidl, UINT uFlags) 2526 { 2527 int i; 2528 2529 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl, uFlags); 2530 2531 i = LV_FindItemByPidl(pidl); 2532 if (i == -1) 2533 return S_OK; 2534 2535 LVITEMW lvItem = {0}; 2536 lvItem.mask = LVIF_STATE; 2537 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED; 2538 2539 while (m_ListView.GetItem(&lvItem)) 2540 { 2541 if (lvItem.iItem == i) 2542 { 2543 if (uFlags & SVSI_SELECT) 2544 lvItem.state |= LVIS_SELECTED; 2545 else 2546 lvItem.state &= ~LVIS_SELECTED; 2547 2548 if (uFlags & SVSI_FOCUSED) 2549 lvItem.state |= LVIS_FOCUSED; 2550 else 2551 lvItem.state &= ~LVIS_FOCUSED; 2552 } 2553 else 2554 { 2555 if (uFlags & SVSI_DESELECTOTHERS) 2556 { 2557 lvItem.state &= ~LVIS_SELECTED; 2558 } 2559 lvItem.state &= ~LVIS_FOCUSED; 2560 } 2561 2562 m_ListView.SetItem(&lvItem); 2563 lvItem.iItem++; 2564 } 2565 2566 if (uFlags & SVSI_ENSUREVISIBLE) 2567 m_ListView.EnsureVisible(i, FALSE); 2568 2569 if((uFlags & SVSI_EDIT) == SVSI_EDIT) 2570 m_ListView.EditLabel(i); 2571 2572 return S_OK; 2573 } 2574 2575 HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut) 2576 { 2577 HRESULT hr = E_NOINTERFACE; 2578 2579 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem, debugstr_guid(&riid), ppvOut); 2580 2581 if (!ppvOut) 2582 return E_INVALIDARG; 2583 2584 *ppvOut = NULL; 2585 2586 switch (uItem) 2587 { 2588 case SVGIO_BACKGROUND: 2589 if (IsEqualIID(riid, IID_IContextMenu)) 2590 { 2591 hr = CDefViewBckgrndMenu_CreateInstance(m_pSF2Parent, riid, ppvOut); 2592 if (FAILED_UNEXPECTEDLY(hr)) 2593 return hr; 2594 2595 IUnknown_SetSite(*((IUnknown**)ppvOut), (IShellView *)this); 2596 } 2597 else if (IsEqualIID(riid, IID_IDispatch)) 2598 { 2599 if (m_pShellFolderViewDual == NULL) 2600 { 2601 hr = CDefViewDual_Constructor(riid, (LPVOID*)&m_pShellFolderViewDual); 2602 if (FAILED_UNEXPECTEDLY(hr)) 2603 return hr; 2604 } 2605 hr = m_pShellFolderViewDual->QueryInterface(riid, ppvOut); 2606 } 2607 break; 2608 2609 case SVGIO_SELECTION: 2610 GetSelections(); 2611 hr = m_pSFParent->GetUIObjectOf(m_hWnd, m_cidl, m_apidl, riid, 0, ppvOut); 2612 if (FAILED_UNEXPECTEDLY(hr)) 2613 return hr; 2614 2615 if (IsEqualIID(riid, IID_IContextMenu)) 2616 IUnknown_SetSite(*((IUnknown**)ppvOut), (IShellView *)this); 2617 2618 break; 2619 } 2620 2621 TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut); 2622 2623 return hr; 2624 } 2625 2626 HRESULT STDMETHODCALLTYPE CDefView::GetCurrentViewMode(UINT *pViewMode) 2627 { 2628 TRACE("(%p)->(%p), stub\n", this, pViewMode); 2629 2630 if (!pViewMode) 2631 return E_INVALIDARG; 2632 2633 *pViewMode = m_FolderSettings.ViewMode; 2634 return S_OK; 2635 } 2636 2637 HRESULT STDMETHODCALLTYPE CDefView::SetCurrentViewMode(UINT ViewMode) 2638 { 2639 DWORD dwStyle; 2640 TRACE("(%p)->(%u), stub\n", this, ViewMode); 2641 2642 /* It's not redundant to check FVM_AUTO because it's a (UINT)-1 */ 2643 if (((INT)ViewMode < FVM_FIRST || (INT)ViewMode > FVM_LAST) && ((INT)ViewMode != FVM_AUTO)) 2644 return E_INVALIDARG; 2645 2646 /* Windows before Vista uses LVM_SETVIEW and possibly 2647 LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview, 2648 while later versions seem to accomplish this through other 2649 means. */ 2650 switch (ViewMode) 2651 { 2652 case FVM_ICON: 2653 dwStyle = LVS_ICON; 2654 break; 2655 case FVM_DETAILS: 2656 dwStyle = LVS_REPORT; 2657 break; 2658 case FVM_SMALLICON: 2659 dwStyle = LVS_SMALLICON; 2660 break; 2661 case FVM_LIST: 2662 dwStyle = LVS_LIST; 2663 break; 2664 default: 2665 { 2666 FIXME("ViewMode %d not implemented\n", ViewMode); 2667 dwStyle = LVS_LIST; 2668 break; 2669 } 2670 } 2671 2672 m_ListView.ModifyStyle(LVS_TYPEMASK, dwStyle); 2673 2674 /* This will not necessarily be the actual mode set above. 2675 This mimics the behavior of Windows XP. */ 2676 m_FolderSettings.ViewMode = ViewMode; 2677 2678 return S_OK; 2679 } 2680 2681 HRESULT STDMETHODCALLTYPE CDefView::GetFolder(REFIID riid, void **ppv) 2682 { 2683 if (m_pSFParent == NULL) 2684 return E_FAIL; 2685 2686 return m_pSFParent->QueryInterface(riid, ppv); 2687 } 2688 2689 HRESULT STDMETHODCALLTYPE CDefView::Item(int iItemIndex, PITEMID_CHILD *ppidl) 2690 { 2691 PCUITEMID_CHILD pidl = _PidlByItem(iItemIndex); 2692 if (pidl) 2693 { 2694 *ppidl = ILClone(pidl); 2695 return S_OK; 2696 } 2697 2698 *ppidl = 0; 2699 return E_INVALIDARG; 2700 } 2701 2702 HRESULT STDMETHODCALLTYPE CDefView::ItemCount(UINT uFlags, int *pcItems) 2703 { 2704 TRACE("(%p)->(%u %p)\n", this, uFlags, pcItems); 2705 2706 if (uFlags != SVGIO_ALLVIEW) 2707 FIXME("some flags unsupported, %x\n", uFlags & ~SVGIO_ALLVIEW); 2708 2709 *pcItems = m_ListView.GetItemCount(); 2710 2711 return S_OK; 2712 } 2713 2714 HRESULT STDMETHODCALLTYPE CDefView::Items(UINT uFlags, REFIID riid, void **ppv) 2715 { 2716 return E_NOTIMPL; 2717 } 2718 2719 HRESULT STDMETHODCALLTYPE CDefView::GetSelectionMarkedItem(int *piItem) 2720 { 2721 TRACE("(%p)->(%p)\n", this, piItem); 2722 2723 *piItem = m_ListView.GetSelectionMark(); 2724 2725 return S_OK; 2726 } 2727 2728 HRESULT STDMETHODCALLTYPE CDefView::GetFocusedItem(int *piItem) 2729 { 2730 TRACE("(%p)->(%p)\n", this, piItem); 2731 2732 *piItem = m_ListView.GetNextItem(-1, LVNI_FOCUSED); 2733 2734 return S_OK; 2735 } 2736 2737 HRESULT STDMETHODCALLTYPE CDefView::GetItemPosition(PCUITEMID_CHILD pidl, POINT *ppt) 2738 { 2739 int lvIndex = LV_FindItemByPidl(pidl); 2740 if (lvIndex == -1 || ppt == NULL) 2741 return E_INVALIDARG; 2742 2743 m_ListView.GetItemPosition(lvIndex, ppt); 2744 return S_OK; 2745 } 2746 2747 HRESULT STDMETHODCALLTYPE CDefView::GetSpacing(POINT *ppt) 2748 { 2749 TRACE("(%p)->(%p)\n", this, ppt); 2750 2751 if (!m_ListView) 2752 return S_FALSE; 2753 2754 if (ppt) 2755 { 2756 SIZE spacing; 2757 m_ListView.GetItemSpacing(spacing); 2758 2759 ppt->x = spacing.cx; 2760 ppt->y = spacing.cy; 2761 } 2762 2763 return S_OK; 2764 } 2765 2766 HRESULT STDMETHODCALLTYPE CDefView::GetDefaultSpacing(POINT *ppt) 2767 { 2768 return E_NOTIMPL; 2769 } 2770 2771 HRESULT STDMETHODCALLTYPE CDefView::GetAutoArrange() 2772 { 2773 return ((m_ListView.GetStyle() & LVS_AUTOARRANGE) ? S_OK : S_FALSE); 2774 } 2775 2776 HRESULT CDefView::_GetSnapToGrid() 2777 { 2778 DWORD dwExStyle = (DWORD)m_ListView.SendMessage(LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0); 2779 return ((dwExStyle & LVS_EX_SNAPTOGRID) ? S_OK : S_FALSE); 2780 } 2781 2782 HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags) 2783 { 2784 LVITEMW lvItem; 2785 2786 TRACE("(%p)->(%d, %x)\n", this, iItem, dwFlags); 2787 2788 lvItem.state = 0; 2789 lvItem.stateMask = LVIS_SELECTED; 2790 2791 if (dwFlags & SVSI_ENSUREVISIBLE) 2792 m_ListView.EnsureVisible(iItem, 0); 2793 2794 /* all items */ 2795 if (dwFlags & SVSI_DESELECTOTHERS) 2796 m_ListView.SetItemState(-1, 0, LVIS_SELECTED); 2797 2798 /* this item */ 2799 if (dwFlags & SVSI_SELECT) 2800 lvItem.state |= LVIS_SELECTED; 2801 2802 if (dwFlags & SVSI_FOCUSED) 2803 lvItem.stateMask |= LVIS_FOCUSED; 2804 2805 m_ListView.SetItemState(iItem, lvItem.state, lvItem.stateMask); 2806 2807 if ((dwFlags & SVSI_EDIT) == SVSI_EDIT) 2808 m_ListView.EditLabel(iItem); 2809 2810 return S_OK; 2811 } 2812 2813 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD dwFlags) 2814 { 2815 /* Reset the selection */ 2816 m_ListView.SetItemState(-1, 0, LVIS_SELECTED); 2817 2818 int lvIndex; 2819 for (UINT i = 0 ; i < m_cidl; i++) 2820 { 2821 lvIndex = LV_FindItemByPidl(apidl[i]); 2822 if (lvIndex != -1) 2823 { 2824 SelectItem(lvIndex, dwFlags); 2825 m_ListView.SetItemPosition(lvIndex, &apt[i]); 2826 } 2827 } 2828 2829 return S_OK; 2830 } 2831 2832 /********************************************************** 2833 * IShellView2 implementation 2834 */ 2835 2836 HRESULT STDMETHODCALLTYPE CDefView::GetView(SHELLVIEWID *view_guid, ULONG view_type) 2837 { 2838 FIXME("(%p)->(%p, %lu) stub\n", this, view_guid, view_type); 2839 return E_NOTIMPL; 2840 } 2841 2842 HRESULT STDMETHODCALLTYPE CDefView::CreateViewWindow2(LPSV2CVW2_PARAMS view_params) 2843 { 2844 return CreateViewWindow3(view_params->psbOwner, view_params->psvPrev, 2845 SV3CVW3_DEFAULT, (FOLDERFLAGS)view_params->pfs->fFlags, (FOLDERFLAGS)view_params->pfs->fFlags, 2846 (FOLDERVIEWMODE)view_params->pfs->ViewMode, view_params->pvid, view_params->prcView, &view_params->hwndView); 2847 } 2848 2849 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) 2850 { 2851 OLEMENUGROUPWIDTHS omw = { { 0, 0, 0, 0, 0, 0 } }; 2852 2853 *hwnd = NULL; 2854 2855 TRACE("(%p)->(shlview=%p shlbrs=%p rec=%p hwnd=%p vmode=%x flags=%x)\n", this, psvPrevious, psb, prcView, hwnd, mode, flags); 2856 if (prcView != NULL) 2857 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom); 2858 2859 /* Validate the Shell Browser */ 2860 if (psb == NULL || m_hWnd) 2861 return E_UNEXPECTED; 2862 2863 if (view_flags != SV3CVW3_DEFAULT) 2864 FIXME("unsupported view flags 0x%08x\n", view_flags); 2865 2866 /* Set up the member variables */ 2867 m_pShellBrowser = psb; 2868 m_FolderSettings.ViewMode = mode; 2869 m_FolderSettings.fFlags = mask & flags; 2870 2871 if (view_id) 2872 { 2873 if (IsEqualIID(*view_id, VID_LargeIcons)) 2874 m_FolderSettings.ViewMode = FVM_ICON; 2875 else if (IsEqualIID(*view_id, VID_SmallIcons)) 2876 m_FolderSettings.ViewMode = FVM_SMALLICON; 2877 else if (IsEqualIID(*view_id, VID_List)) 2878 m_FolderSettings.ViewMode = FVM_LIST; 2879 else if (IsEqualIID(*view_id, VID_Details)) 2880 m_FolderSettings.ViewMode = FVM_DETAILS; 2881 else if (IsEqualIID(*view_id, VID_Thumbnails)) 2882 m_FolderSettings.ViewMode = FVM_THUMBNAIL; 2883 else if (IsEqualIID(*view_id, VID_Tile)) 2884 m_FolderSettings.ViewMode = FVM_TILE; 2885 else if (IsEqualIID(*view_id, VID_ThumbStrip)) 2886 m_FolderSettings.ViewMode = FVM_THUMBSTRIP; 2887 else 2888 FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_id)); 2889 } 2890 2891 /* Get our parent window */ 2892 m_pShellBrowser->GetWindow(&m_hWndParent); 2893 2894 /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */ 2895 m_pCommDlgBrowser = NULL; 2896 if (SUCCEEDED(m_pShellBrowser->QueryInterface(IID_PPV_ARG(ICommDlgBrowser, &m_pCommDlgBrowser)))) 2897 { 2898 TRACE("-- CommDlgBrowser\n"); 2899 } 2900 2901 Create(m_hWndParent, prcView, NULL, WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP, 0, 0U); 2902 if (m_hWnd == NULL) 2903 return E_FAIL; 2904 2905 *hwnd = m_hWnd; 2906 2907 CheckToolbar(); 2908 2909 if (!*hwnd) 2910 return E_FAIL; 2911 2912 _DoFolderViewCB(SFVM_WINDOWCREATED, (WPARAM)m_hWnd, 0); 2913 2914 SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); 2915 UpdateWindow(); 2916 2917 if (!m_hMenu) 2918 { 2919 m_hMenu = CreateMenu(); 2920 m_pShellBrowser->InsertMenusSB(m_hMenu, &omw); 2921 TRACE("-- after fnInsertMenusSB\n"); 2922 } 2923 2924 _MergeToolbar(); 2925 2926 return S_OK; 2927 } 2928 2929 HRESULT STDMETHODCALLTYPE CDefView::HandleRename(LPCITEMIDLIST new_pidl) 2930 { 2931 FIXME("(%p)->(%p) stub\n", this, new_pidl); 2932 return E_NOTIMPL; 2933 } 2934 2935 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItem(LPCITEMIDLIST item, UINT flags, POINT *point) 2936 { 2937 FIXME("(%p)->(%p, %u, %p) stub\n", this, item, flags, point); 2938 return E_NOTIMPL; 2939 } 2940 2941 /********************************************************** 2942 * IShellFolderView implementation 2943 */ 2944 HRESULT STDMETHODCALLTYPE CDefView::Rearrange(LPARAM sort) 2945 { 2946 FIXME("(%p)->(%ld) stub\n", this, sort); 2947 return E_NOTIMPL; 2948 } 2949 2950 HRESULT STDMETHODCALLTYPE CDefView::GetArrangeParam(LPARAM *sort) 2951 { 2952 FIXME("(%p)->(%p) stub\n", this, sort); 2953 return E_NOTIMPL; 2954 } 2955 2956 HRESULT STDMETHODCALLTYPE CDefView::ArrangeGrid() 2957 { 2958 m_ListView.SetExtendedListViewStyle(LVS_EX_SNAPTOGRID, LVS_EX_SNAPTOGRID); 2959 return S_OK; 2960 } 2961 2962 HRESULT STDMETHODCALLTYPE CDefView::AutoArrange() 2963 { 2964 m_ListView.ModifyStyle(0, LVS_AUTOARRANGE); 2965 m_ListView.Arrange(LVA_DEFAULT); 2966 return S_OK; 2967 } 2968 2969 HRESULT STDMETHODCALLTYPE CDefView::AddObject(PITEMID_CHILD pidl, UINT *item) 2970 { 2971 TRACE("(%p)->(%p %p)\n", this, pidl, item); 2972 *item = LV_AddItem(pidl); 2973 return (int)*item >= 0 ? S_OK : E_OUTOFMEMORY; 2974 } 2975 2976 HRESULT STDMETHODCALLTYPE CDefView::GetObject(PITEMID_CHILD *pidl, UINT item) 2977 { 2978 TRACE("(%p)->(%p %d)\n", this, pidl, item); 2979 return Item(item, pidl); 2980 } 2981 2982 HRESULT STDMETHODCALLTYPE CDefView::RemoveObject(PITEMID_CHILD pidl, UINT *item) 2983 { 2984 2985 TRACE("(%p)->(%p %p)\n", this, pidl, item); 2986 2987 if (pidl) 2988 { 2989 *item = LV_FindItemByPidl(ILFindLastID(pidl)); 2990 m_ListView.DeleteItem(*item); 2991 } 2992 else 2993 { 2994 *item = 0; 2995 m_ListView.DeleteAllItems(); 2996 } 2997 2998 return S_OK; 2999 } 3000 3001 HRESULT STDMETHODCALLTYPE CDefView::GetObjectCount(UINT *count) 3002 { 3003 TRACE("(%p)->(%p)\n", this, count); 3004 *count = m_ListView.GetItemCount(); 3005 return S_OK; 3006 } 3007 3008 HRESULT STDMETHODCALLTYPE CDefView::SetObjectCount(UINT count, UINT flags) 3009 { 3010 FIXME("(%p)->(%d %x) stub\n", this, count, flags); 3011 return E_NOTIMPL; 3012 } 3013 3014 HRESULT STDMETHODCALLTYPE CDefView::UpdateObject(PITEMID_CHILD pidl_old, PITEMID_CHILD pidl_new, UINT *item) 3015 { 3016 FIXME("(%p)->(%p %p %p) stub\n", this, pidl_old, pidl_new, item); 3017 return E_NOTIMPL; 3018 } 3019 3020 HRESULT STDMETHODCALLTYPE CDefView::RefreshObject(PITEMID_CHILD pidl, UINT *item) 3021 { 3022 FIXME("(%p)->(%p %p) stub\n", this, pidl, item); 3023 return E_NOTIMPL; 3024 } 3025 3026 HRESULT STDMETHODCALLTYPE CDefView::SetRedraw(BOOL redraw) 3027 { 3028 TRACE("(%p)->(%d)\n", this, redraw); 3029 m_ListView.SetRedraw(redraw); 3030 return S_OK; 3031 } 3032 3033 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedCount(UINT *count) 3034 { 3035 FIXME("(%p)->(%p) stub\n", this, count); 3036 return E_NOTIMPL; 3037 } 3038 3039 HRESULT STDMETHODCALLTYPE CDefView::GetSelectedObjects(PCUITEMID_CHILD **pidl, UINT *items) 3040 { 3041 TRACE("(%p)->(%p %p)\n", this, pidl, items); 3042 3043 *items = GetSelections(); 3044 3045 if (*items) 3046 { 3047 *pidl = static_cast<PCUITEMID_CHILD *>(LocalAlloc(0, *items * sizeof(PCUITEMID_CHILD))); 3048 if (!*pidl) 3049 { 3050 return E_OUTOFMEMORY; 3051 } 3052 3053 /* it's documented that caller shouldn't PIDLs, only array itself */ 3054 memcpy(*pidl, m_apidl, *items * sizeof(PCUITEMID_CHILD)); 3055 } 3056 3057 return S_OK; 3058 } 3059 3060 HRESULT STDMETHODCALLTYPE CDefView::IsDropOnSource(IDropTarget *drop_target) 3061 { 3062 if ((m_iDragOverItem == -1 || m_pCurDropTarget == NULL) && 3063 (m_pSourceDataObject.p)) 3064 { 3065 return S_OK; 3066 } 3067 3068 return S_FALSE; 3069 } 3070 3071 HRESULT STDMETHODCALLTYPE CDefView::GetDragPoint(POINT *pt) 3072 { 3073 if (!pt) 3074 return E_INVALIDARG; 3075 3076 *pt = m_ptFirstMousePos; 3077 return S_OK; 3078 } 3079 3080 HRESULT STDMETHODCALLTYPE CDefView::GetDropPoint(POINT *pt) 3081 { 3082 FIXME("(%p)->(%p) stub\n", this, pt); 3083 return E_NOTIMPL; 3084 } 3085 3086 HRESULT STDMETHODCALLTYPE CDefView::MoveIcons(IDataObject *obj) 3087 { 3088 TRACE("(%p)->(%p)\n", this, obj); 3089 return E_NOTIMPL; 3090 } 3091 3092 HRESULT STDMETHODCALLTYPE CDefView::SetItemPos(PCUITEMID_CHILD pidl, POINT *pt) 3093 { 3094 FIXME("(%p)->(%p %p) stub\n", this, pidl, pt); 3095 return E_NOTIMPL; 3096 } 3097 3098 HRESULT STDMETHODCALLTYPE CDefView::IsBkDropTarget(IDropTarget *drop_target) 3099 { 3100 FIXME("(%p)->(%p) stub\n", this, drop_target); 3101 return E_NOTIMPL; 3102 } 3103 3104 HRESULT STDMETHODCALLTYPE CDefView::SetClipboard(BOOL move) 3105 { 3106 FIXME("(%p)->(%d) stub\n", this, move); 3107 return E_NOTIMPL; 3108 } 3109 3110 HRESULT STDMETHODCALLTYPE CDefView::SetPoints(IDataObject *obj) 3111 { 3112 FIXME("(%p)->(%p) stub\n", this, obj); 3113 return E_NOTIMPL; 3114 } 3115 3116 HRESULT STDMETHODCALLTYPE CDefView::GetItemSpacing(ITEMSPACING *spacing) 3117 { 3118 FIXME("(%p)->(%p) stub\n", this, spacing); 3119 return E_NOTIMPL; 3120 } 3121 3122 HRESULT STDMETHODCALLTYPE CDefView::SetCallback(IShellFolderViewCB *new_cb, IShellFolderViewCB **old_cb) 3123 { 3124 if (old_cb) 3125 *old_cb = m_pShellFolderViewCB.Detach(); 3126 3127 m_pShellFolderViewCB = new_cb; 3128 return S_OK; 3129 } 3130 3131 HRESULT STDMETHODCALLTYPE CDefView::Select(UINT flags) 3132 { 3133 FIXME("(%p)->(%d) stub\n", this, flags); 3134 return E_NOTIMPL; 3135 } 3136 3137 HRESULT STDMETHODCALLTYPE CDefView::QuerySupport(UINT *support) 3138 { 3139 TRACE("(%p)->(%p)\n", this, support); 3140 return S_OK; 3141 } 3142 3143 HRESULT STDMETHODCALLTYPE CDefView::SetAutomationObject(IDispatch *disp) 3144 { 3145 FIXME("(%p)->(%p) stub\n", this, disp); 3146 return E_NOTIMPL; 3147 } 3148 3149 /********************************************************** 3150 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget) 3151 */ 3152 HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText) 3153 { 3154 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n", 3155 this, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText); 3156 3157 if (!prgCmds) 3158 return E_INVALIDARG; 3159 3160 for (UINT i = 0; i < cCmds; i++) 3161 { 3162 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID); 3163 prgCmds[i].cmdf = 0; 3164 } 3165 3166 return OLECMDERR_E_UNKNOWNGROUP; 3167 } 3168 3169 /********************************************************** 3170 * ISVOleCmdTarget_Exec (IOleCommandTarget) 3171 * 3172 * nCmdID is the OLECMDID_* enumeration 3173 */ 3174 HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 3175 { 3176 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n", 3177 this, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut); 3178 3179 if (!pguidCmdGroup) 3180 return OLECMDERR_E_UNKNOWNGROUP; 3181 3182 if (IsEqualCLSID(*pguidCmdGroup, m_Category)) 3183 { 3184 if (nCmdID == FCIDM_SHVIEW_AUTOARRANGE) 3185 { 3186 if (V_VT(pvaIn) != VT_INT_PTR) 3187 return OLECMDERR_E_NOTSUPPORTED; 3188 3189 TPMPARAMS params; 3190 params.cbSize = sizeof(params); 3191 params.rcExclude = *(RECT*) V_INTREF(pvaIn); 3192 3193 if (m_hMenuViewModes) 3194 { 3195 /* Duplicate all but the last two items of the view modes menu */ 3196 HMENU hmenuViewPopup = CreatePopupMenu(); 3197 Shell_MergeMenus(hmenuViewPopup, m_hMenuViewModes, 0, 0, 0xFFFF, 0); 3198 DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION); 3199 DeleteMenu(hmenuViewPopup, GetMenuItemCount(hmenuViewPopup) - 1, MF_BYPOSITION); 3200 CheckViewMode(hmenuViewPopup); 3201 TrackPopupMenuEx(hmenuViewPopup, TPM_LEFTALIGN | TPM_TOPALIGN, params.rcExclude.left, params.rcExclude.bottom, m_hWndParent, ¶ms); 3202 ::DestroyMenu(hmenuViewPopup); 3203 } 3204 3205 // pvaOut is VT_I4 with value 0x403 (cmd id of the new mode maybe?) 3206 V_VT(pvaOut) = VT_I4; 3207 V_I4(pvaOut) = 0x403; 3208 } 3209 } 3210 3211 if (IsEqualIID(*pguidCmdGroup, CGID_Explorer) && 3212 (nCmdID == 0x29) && 3213 (nCmdexecopt == 4) && pvaOut) 3214 return S_OK; 3215 3216 if (IsEqualIID(*pguidCmdGroup, CGID_ShellDocView) && 3217 (nCmdID == 9) && 3218 (nCmdexecopt == 0)) 3219 return 1; 3220 3221 return OLECMDERR_E_UNKNOWNGROUP; 3222 } 3223 3224 /********************************************************** 3225 * ISVDropTarget implementation 3226 */ 3227 3228 /****************************************************************************** 3229 * drag_notify_subitem [Internal] 3230 * 3231 * Figure out the shellfolder object, which is currently under the mouse cursor 3232 * and notify it via the IDropTarget interface. 3233 */ 3234 3235 #define SCROLLAREAWIDTH 20 3236 3237 HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 3238 { 3239 LONG lResult; 3240 HRESULT hr; 3241 RECT clientRect; 3242 3243 /* The key state on drop doesn't have MK_LBUTTON or MK_RBUTTON because it 3244 reflects the key state after the user released the button, so we need 3245 to remember the last key state when the button was pressed */ 3246 m_grfKeyState = grfKeyState; 3247 3248 /* Map from global to client coordinates and query the index of the listview-item, which is 3249 * currently under the mouse cursor. */ 3250 LVHITTESTINFO htinfo = {{pt.x, pt.y}, LVHT_ONITEM}; 3251 ScreenToClient(&htinfo.pt); 3252 lResult = m_ListView.HitTest(&htinfo); 3253 3254 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */ 3255 ::GetClientRect(m_ListView, &clientRect); 3256 if (htinfo.pt.x == m_ptLastMousePos.x && htinfo.pt.y == m_ptLastMousePos.y && 3257 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH || 3258 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH )) 3259 { 3260 m_cScrollDelay = (m_cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */ 3261 if (m_cScrollDelay == 0) 3262 { 3263 /* Mouse did hover another 250 ms over the scroll-area */ 3264 if (htinfo.pt.x < SCROLLAREAWIDTH) 3265 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEUP, 0); 3266 3267 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH) 3268 m_ListView.SendMessageW(WM_HSCROLL, SB_LINEDOWN, 0); 3269 3270 if (htinfo.pt.y < SCROLLAREAWIDTH) 3271 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEUP, 0); 3272 3273 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH) 3274 m_ListView.SendMessageW(WM_VSCROLL, SB_LINEDOWN, 0); 3275 } 3276 } 3277 else 3278 { 3279 m_cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */ 3280 } 3281 3282 m_ptLastMousePos = htinfo.pt; 3283 ::ClientToListView(m_ListView, &m_ptLastMousePos); 3284 3285 /* We need to check if we drag the selection over itself */ 3286 if (lResult != -1 && m_pSourceDataObject.p != NULL) 3287 { 3288 PCUITEMID_CHILD pidl = _PidlByItem(lResult); 3289 3290 for (UINT i = 0; i < m_cidl; i++) 3291 { 3292 if (pidl == m_apidl[i]) 3293 { 3294 /* The item that is being draged is hovering itself. */ 3295 lResult = -1; 3296 break; 3297 } 3298 } 3299 } 3300 3301 /* If we are still over the previous sub-item, notify it via DragOver and return. */ 3302 if (m_pCurDropTarget && lResult == m_iDragOverItem) 3303 return m_pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect); 3304 3305 /* We've left the previous sub-item, notify it via DragLeave and Release it. */ 3306 if (m_pCurDropTarget) 3307 { 3308 PCUITEMID_CHILD pidl = _PidlByItem(m_iDragOverItem); 3309 if (pidl) 3310 SelectItem(pidl, 0); 3311 3312 m_pCurDropTarget->DragLeave(); 3313 m_pCurDropTarget.Release(); 3314 } 3315 3316 m_iDragOverItem = lResult; 3317 3318 if (lResult == -1) 3319 { 3320 /* We are not above one of the listview's subitems. Bind to the parent folder's 3321 * DropTarget interface. */ 3322 hr = m_pSFParent->CreateViewObject(NULL, IID_PPV_ARG(IDropTarget,&m_pCurDropTarget)); 3323 } 3324 else 3325 { 3326 /* Query the relative PIDL of the shellfolder object represented by the currently 3327 * dragged over listview-item ... */ 3328 PCUITEMID_CHILD pidl = _PidlByItem(lResult); 3329 3330 /* ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object */ 3331 hr = m_pSFParent->GetUIObjectOf(m_ListView, 1, &pidl, IID_NULL_PPV_ARG(IDropTarget, &m_pCurDropTarget)); 3332 } 3333 3334 IUnknown_SetSite(m_pCurDropTarget, (IShellView *)this); 3335 3336 /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */ 3337 if (FAILED(hr)) 3338 { 3339 *pdwEffect = DROPEFFECT_NONE; 3340 return hr; 3341 } 3342 3343 if (m_iDragOverItem != -1) 3344 { 3345 SelectItem(m_iDragOverItem, SVSI_SELECT); 3346 } 3347 3348 /* Notify the item just entered via DragEnter. */ 3349 return m_pCurDropTarget->DragEnter(m_pCurDataObject, grfKeyState, pt, pdwEffect); 3350 } 3351 3352 HRESULT WINAPI CDefView::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 3353 { 3354 if (*pdwEffect == DROPEFFECT_NONE) 3355 return S_OK; 3356 3357 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */ 3358 m_pCurDataObject = pDataObject; 3359 3360 HRESULT hr = drag_notify_subitem(grfKeyState, pt, pdwEffect); 3361 if (SUCCEEDED(hr)) 3362 { 3363 POINT ptClient = {pt.x, pt.y}; 3364 ScreenToClient(&ptClient); 3365 ImageList_DragEnter(m_hWnd, ptClient.x, ptClient.y); 3366 } 3367 3368 return hr; 3369 } 3370 3371 HRESULT WINAPI CDefView::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 3372 { 3373 POINT ptClient = {pt.x, pt.y}; 3374 ScreenToClient(&ptClient); 3375 ImageList_DragMove(ptClient.x, ptClient.y); 3376 return drag_notify_subitem(grfKeyState, pt, pdwEffect); 3377 } 3378 3379 HRESULT WINAPI CDefView::DragLeave() 3380 { 3381 ImageList_DragLeave(m_hWnd); 3382 3383 if (m_pCurDropTarget) 3384 { 3385 m_pCurDropTarget->DragLeave(); 3386 m_pCurDropTarget.Release(); 3387 } 3388 3389 if (m_pCurDataObject != NULL) 3390 { 3391 m_pCurDataObject.Release(); 3392 } 3393 3394 m_iDragOverItem = 0; 3395 3396 return S_OK; 3397 } 3398 3399 INT CDefView::_FindInsertableIndexFromPoint(POINT pt) 3400 { 3401 RECT rcBound; 3402 INT i, nCount = m_ListView.GetItemCount(); 3403 DWORD dwSpacing; 3404 INT dx, dy; 3405 BOOL bSmall = ((m_ListView.GetStyle() & LVS_TYPEMASK) != LVS_ICON); 3406 3407 /* FIXME: LVM_GETORIGIN is broken. See CORE-17266 */ 3408 pt.x += m_ListView.GetScrollPos(SB_HORZ); 3409 pt.y += m_ListView.GetScrollPos(SB_VERT); 3410 3411 if (m_ListView.GetStyle() & LVS_ALIGNLEFT) 3412 { 3413 // vertically 3414 for (i = 0; i < nCount; ++i) 3415 { 3416 dwSpacing = ListView_GetItemSpacing(m_ListView, bSmall); 3417 dx = LOWORD(dwSpacing); 3418 dy = HIWORD(dwSpacing); 3419 ListView_GetItemRect(m_ListView, i, &rcBound, LVIR_SELECTBOUNDS); 3420 rcBound.right = rcBound.left + dx; 3421 rcBound.bottom = rcBound.top + dy; 3422 if (pt.x < rcBound.right && pt.y < (rcBound.top + rcBound.bottom) / 2) 3423 { 3424 return i; 3425 } 3426 } 3427 for (i = nCount - 1; i >= 0; --i) 3428 { 3429 ListView_GetItemRect(m_ListView, i, &rcBound, LVIR_SELECTBOUNDS); 3430 if (rcBound.left < pt.x && rcBound.top < pt.y) 3431 { 3432 return i + 1; 3433 } 3434 } 3435 } 3436 else 3437 { 3438 // horizontally 3439 for (i = 0; i < nCount; ++i) 3440 { 3441 dwSpacing = ListView_GetItemSpacing(m_ListView, bSmall); 3442 dx = LOWORD(dwSpacing); 3443 dy = HIWORD(dwSpacing); 3444 ListView_GetItemRect(m_ListView, i, &rcBound, LVIR_SELECTBOUNDS); 3445 rcBound.right = rcBound.left + dx; 3446 rcBound.bottom = rcBound.top + dy; 3447 if (pt.y < rcBound.bottom && pt.x < rcBound.left) 3448 { 3449 return i; 3450 } 3451 if (pt.y < rcBound.bottom && pt.x < rcBound.right) 3452 { 3453 return i + 1; 3454 } 3455 } 3456 for (i = nCount - 1; i >= 0; --i) 3457 { 3458 ListView_GetItemRect(m_ListView, i, &rcBound, LVIR_SELECTBOUNDS); 3459 if (rcBound.left < pt.x && rcBound.top < pt.y) 3460 { 3461 return i + 1; 3462 } 3463 } 3464 } 3465 3466 return nCount; 3467 } 3468 3469 typedef CSimpleMap<LPARAM, INT> CLParamIndexMap; 3470 3471 static INT CALLBACK 3472 SelectionMoveCompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) 3473 { 3474 CLParamIndexMap *pmap = (CLParamIndexMap *)lParamSort; 3475 INT i1 = pmap->Lookup(lParam1), i2 = pmap->Lookup(lParam2); 3476 if (i1 < i2) 3477 return -1; 3478 if (i1 > i2) 3479 return 1; 3480 return 0; 3481 } 3482 3483 void CDefView::_MoveSelectionOnAutoArrange(POINT pt) 3484 { 3485 // get insertable index from position 3486 INT iPosition = _FindInsertableIndexFromPoint(pt); 3487 3488 // create identity mapping of indexes 3489 CSimpleArray<INT> array; 3490 INT nCount = m_ListView.GetItemCount(); 3491 for (INT i = 0; i < nCount; ++i) 3492 { 3493 array.Add(i); 3494 } 3495 3496 // re-ordering mapping 3497 INT iItem = -1; 3498 while ((iItem = m_ListView.GetNextItem(iItem, LVNI_SELECTED)) >= 0) 3499 { 3500 INT iFrom = iItem, iTo = iPosition; 3501 if (iFrom < iTo) 3502 --iTo; 3503 if (iFrom >= nCount) 3504 iFrom = nCount - 1; 3505 if (iTo >= nCount) 3506 iTo = nCount - 1; 3507 3508 // shift indexes by swapping (like a bucket relay) 3509 if (iFrom < iTo) 3510 { 3511 for (INT i = iFrom; i < iTo; ++i) 3512 { 3513 // swap array[i] and array[i + 1] 3514 INT tmp = array[i]; 3515 array[i] = array[i + 1]; 3516 array[i + 1] = tmp; 3517 } 3518 } 3519 else 3520 { 3521 for (INT i = iFrom; i > iTo; --i) 3522 { 3523 // swap array[i] and array[i - 1] 3524 INT tmp = array[i]; 3525 array[i] = array[i - 1]; 3526 array[i - 1] = tmp; 3527 } 3528 } 3529 } 3530 3531 // create mapping (ListView's lParam to index) from array 3532 CLParamIndexMap map; 3533 for (INT i = 0; i < nCount; ++i) 3534 { 3535 LPARAM lParam = m_ListView.GetItemData(array[i]); 3536 map.Add(lParam, i); 3537 } 3538 3539 // finally sort 3540 m_ListView.SortItems(SelectionMoveCompareFunc, &map); 3541 } 3542 3543 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 3544 { 3545 ImageList_DragLeave(m_hWnd); 3546 ImageList_EndDrag(); 3547 3548 if ((IsDropOnSource(NULL) == S_OK) && 3549 (*pdwEffect & DROPEFFECT_MOVE) && 3550 (m_grfKeyState & MK_LBUTTON)) 3551 { 3552 if (m_pCurDropTarget) 3553 { 3554 m_pCurDropTarget->DragLeave(); 3555 m_pCurDropTarget.Release(); 3556 } 3557 3558 POINT ptDrop = { pt.x, pt.y }; 3559 ::ScreenToClient(m_ListView, &ptDrop); 3560 ::ClientToListView(m_ListView, &ptDrop); 3561 m_ptLastMousePos = ptDrop; 3562 3563 m_ListView.SetRedraw(FALSE); 3564 if (m_ListView.GetStyle() & LVS_AUTOARRANGE) 3565 { 3566 _MoveSelectionOnAutoArrange(m_ptLastMousePos); 3567 } 3568 else 3569 { 3570 POINT ptItem; 3571 INT iItem = -1; 3572 while ((iItem = m_ListView.GetNextItem(iItem, LVNI_SELECTED)) >= 0) 3573 { 3574 if (m_ListView.GetItemPosition(iItem, &ptItem)) 3575 { 3576 ptItem.x += m_ptLastMousePos.x - m_ptFirstMousePos.x; 3577 ptItem.y += m_ptLastMousePos.y - m_ptFirstMousePos.y; 3578 m_ListView.SetItemPosition(iItem, &ptItem); 3579 } 3580 } 3581 } 3582 m_ListView.SetRedraw(TRUE); 3583 } 3584 else if (m_pCurDropTarget) 3585 { 3586 m_pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect); 3587 m_pCurDropTarget.Release(); 3588 } 3589 3590 m_pCurDataObject.Release(); 3591 m_iDragOverItem = 0; 3592 return S_OK; 3593 } 3594 3595 /********************************************************** 3596 * ISVDropSource implementation 3597 */ 3598 3599 HRESULT WINAPI CDefView::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) 3600 { 3601 TRACE("(%p)\n", this); 3602 3603 if (fEscapePressed) 3604 return DRAGDROP_S_CANCEL; 3605 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON)) 3606 return DRAGDROP_S_DROP; 3607 else 3608 return S_OK; 3609 } 3610 3611 HRESULT WINAPI CDefView::GiveFeedback(DWORD dwEffect) 3612 { 3613 TRACE("(%p)\n", this); 3614 3615 return DRAGDROP_S_USEDEFAULTCURSORS; 3616 } 3617 3618 /********************************************************** 3619 * ISVViewObject implementation 3620 */ 3621 3622 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) 3623 { 3624 FIXME("Stub: this=%p\n", this); 3625 3626 return E_NOTIMPL; 3627 } 3628 3629 HRESULT WINAPI CDefView::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet) 3630 { 3631 FIXME("Stub: this=%p\n", this); 3632 3633 return E_NOTIMPL; 3634 } 3635 3636 HRESULT WINAPI CDefView::Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze) 3637 { 3638 FIXME("Stub: this=%p\n", this); 3639 3640 return E_NOTIMPL; 3641 } 3642 3643 HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze) 3644 { 3645 FIXME("Stub: this=%p\n", this); 3646 3647 return E_NOTIMPL; 3648 } 3649 3650 HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink) 3651 { 3652 FIXME("partial stub: %p 0x%08x 0x%08x %p\n", this, aspects, advf, pAdvSink); 3653 3654 /* FIXME: we set the AdviseSink, but never use it to send any advice */ 3655 m_pAdvSink = pAdvSink; 3656 m_dwAspects = aspects; 3657 m_dwAdvf = advf; 3658 3659 return S_OK; 3660 } 3661 3662 HRESULT WINAPI CDefView::GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink) 3663 { 3664 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects, pAdvf, ppAdvSink); 3665 3666 if (ppAdvSink) 3667 { 3668 *ppAdvSink = m_pAdvSink; 3669 m_pAdvSink.p->AddRef(); 3670 } 3671 3672 if (pAspects) 3673 *pAspects = m_dwAspects; 3674 3675 if (pAdvf) 3676 *pAdvf = m_dwAdvf; 3677 3678 return S_OK; 3679 } 3680 3681 HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) 3682 { 3683 if (IsEqualIID(guidService, SID_IShellBrowser)) 3684 return m_pShellBrowser->QueryInterface(riid, ppvObject); 3685 else if(IsEqualIID(guidService, SID_IFolderView)) 3686 return QueryInterface(riid, ppvObject); 3687 3688 return E_NOINTERFACE; 3689 } 3690 3691 HRESULT CDefView::_MergeToolbar() 3692 { 3693 CComPtr<IExplorerToolbar> ptb; 3694 HRESULT hr = S_OK; 3695 3696 hr = IUnknown_QueryService(m_pShellBrowser, IID_IExplorerToolbar, IID_PPV_ARG(IExplorerToolbar, &ptb)); 3697 if (FAILED(hr)) 3698 return hr; 3699 3700 m_Category = CGID_DefViewFrame; 3701 3702 hr = ptb->SetCommandTarget(static_cast<IOleCommandTarget*>(this), &m_Category, 0); 3703 if (FAILED(hr)) 3704 return hr; 3705 3706 if (hr == S_FALSE) 3707 return S_OK; 3708 3709 #if 0 3710 hr = ptb->AddButtons(&m_Category, buttonsCount, buttons); 3711 if (FAILED(hr)) 3712 return hr; 3713 #endif 3714 3715 return S_OK; 3716 } 3717 3718 HRESULT CDefView::_DoFolderViewCB(UINT uMsg, WPARAM wParam, LPARAM lParam) 3719 { 3720 HRESULT hr = E_NOTIMPL; 3721 3722 if (m_pShellFolderViewCB) 3723 { 3724 hr = m_pShellFolderViewCB->MessageSFVCB(uMsg, wParam, lParam); 3725 } 3726 3727 return hr; 3728 } 3729 3730 HRESULT CDefView_CreateInstance(IShellFolder *pFolder, REFIID riid, LPVOID * ppvOut) 3731 { 3732 return ShellObjectCreatorInit<CDefView>(pFolder, riid, ppvOut); 3733 } 3734 3735 HRESULT WINAPI SHCreateShellFolderViewEx( 3736 LPCSFV psvcbi, /* [in] shelltemplate struct */ 3737 IShellView **ppsv) /* [out] IShellView pointer */ 3738 { 3739 CComPtr<IShellView> psv; 3740 HRESULT hRes; 3741 3742 TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n", 3743 psvcbi->pshf, psvcbi->pidl, psvcbi->pfnCallback, 3744 psvcbi->fvm, psvcbi->psvOuter); 3745 3746 *ppsv = NULL; 3747 hRes = CDefView_CreateInstance(psvcbi->pshf, IID_PPV_ARG(IShellView, &psv)); 3748 if (FAILED_UNEXPECTEDLY(hRes)) 3749 return hRes; 3750 3751 *ppsv = psv.Detach(); 3752 return hRes; 3753 } 3754 3755 HRESULT WINAPI SHCreateShellFolderView(const SFV_CREATE *pcsfv, 3756 IShellView **ppsv) 3757 { 3758 CComPtr<IShellView> psv; 3759 HRESULT hRes; 3760 3761 if (!ppsv) 3762 return E_INVALIDARG; 3763 3764 *ppsv = NULL; 3765 3766 if (!pcsfv || pcsfv->cbSize != sizeof(*pcsfv)) 3767 return E_INVALIDARG; 3768 3769 TRACE("sf=%p outer=%p callback=%p\n", 3770 pcsfv->pshf, pcsfv->psvOuter, pcsfv->psfvcb); 3771 3772 hRes = CDefView_CreateInstance(pcsfv->pshf, IID_PPV_ARG(IShellView, &psv)); 3773 if (FAILED(hRes)) 3774 return hRes; 3775 3776 if (pcsfv->psfvcb) 3777 { 3778 CComPtr<IShellFolderView> sfv; 3779 if (SUCCEEDED(psv->QueryInterface(IID_PPV_ARG(IShellFolderView, &sfv)))) 3780 { 3781 sfv->SetCallback(pcsfv->psfvcb, NULL); 3782 } 3783 } 3784 3785 *ppsv = psv.Detach(); 3786 return hRes; 3787 } 3788