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