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