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