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