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