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