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