Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenshlview.cpp
Go to the documentation of this file.
00001 /* 00002 * ShellView 00003 * 00004 * Copyright 1998,1999 <juergen.schmied@debitel.net> 00005 * 00006 * This is the view visualizing the data provided by the shellfolder. 00007 * No direct access to data from pidls should be done from here. 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 * This library is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00022 * 00023 * FIXME: The order by part of the background context menu should be 00024 * built according to the columns shown. 00025 * 00026 * FIXME: CheckToolbar: handle the "new folder" and "folder up" button 00027 * 00028 * FIXME: ShellView_FillList: consider sort orders 00029 */ 00030 00031 /* 00032 TODO: 00033 1. Load/Save the view state from/into the stream provided by the ShellBrowser. 00034 2. Let the shell folder sort items. 00035 3. Code to merge menus in the shellbrowser is incorrect. 00036 4. Move the background context menu creation into shell view. It should store the 00037 shell view HWND to send commands. 00038 5. Send init, measure, and draw messages to context menu during tracking. 00039 6. Shell view should do SetCommandTarget on internet toolbar. 00040 7. When editing starts on item, set edit text to for editing value. 00041 8. When shell view is called back for item info, let listview save the value. 00042 9. Shell view should update status bar. 00043 10. Fix shell view to handle view mode popup exec. 00044 11. The background context menu should have a pidl just like foreground menus. This 00045 causes crashes when dynamic handlers try to use the NULL pidl. 00046 12. The SHELLDLL_DefView should not be filled with blue unconditionally. This causes 00047 annoying flashing of blue even on XP, and is not correct. 00048 13. Reorder of columns doesn't work - might be bug in comctl32 00049 */ 00050 00051 #include <precomp.h> 00052 00053 WINE_DEFAULT_DEBUG_CHANNEL(shell); 00054 00055 #undef SV_CLASS_NAME 00056 00057 static const WCHAR SV_CLASS_NAME[] = {'S', 'H', 'E', 'L', 'L', 'D', 'L', 'L', '_', 'D', 'e', 'f', 'V', 'i', 'e', 'w', 0}; 00058 00059 typedef struct 00060 { BOOL bIsAscending; 00061 INT nHeaderID; 00062 INT nLastHeaderID; 00063 } LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO; 00064 00065 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111 00066 00067 class CDefView : 00068 public CWindowImpl<CDefView, CWindow, CControlWinTraits>, 00069 public CComObjectRootEx<CComMultiThreadModelNoCS>, 00070 public IShellView, 00071 public IFolderView, 00072 public IOleCommandTarget, 00073 public IDropTarget, 00074 public IDropSource, 00075 public IViewObject, 00076 public IServiceProvider 00077 { 00078 private: 00079 CComPtr<IShellFolder> pSFParent; 00080 CComPtr<IShellFolder2> pSF2Parent; 00081 CComPtr<IShellBrowser> pShellBrowser; 00082 CComPtr<ICommDlgBrowser> pCommDlgBrowser; 00083 HWND hWndList; /* ListView control */ 00084 HWND hWndParent; 00085 FOLDERSETTINGS FolderSettings; 00086 HMENU hMenu; 00087 UINT uState; 00088 UINT cidl; 00089 LPITEMIDLIST *apidl; 00090 LISTVIEW_SORT_INFO ListViewSortInfo; 00091 ULONG hNotify; /* change notification handle */ 00092 HANDLE hAccel; 00093 DWORD dwAspects; 00094 DWORD dwAdvf; 00095 CComPtr<IAdviseSink> pAdvSink; 00096 // for drag and drop 00097 CComPtr<IDropTarget> pCurDropTarget; /* The sub-item, which is currently dragged over */ 00098 CComPtr<IDataObject> pCurDataObject; /* The dragged data-object */ 00099 LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */ 00100 UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */ 00101 POINT ptLastMousePos; /* Mouse position at last DragOver call */ 00102 // 00103 CComPtr<IContextMenu2> pCM; 00104 public: 00105 CDefView(); 00106 ~CDefView(); 00107 HRESULT WINAPI Initialize(IShellFolder *shellFolder); 00108 HRESULT IncludeObject(LPCITEMIDLIST pidl); 00109 HRESULT OnDefaultCommand(); 00110 HRESULT OnStateChange(UINT uFlags); 00111 void CheckToolbar(); 00112 void SetStyle(DWORD dwAdd, DWORD dwRemove); 00113 BOOL CreateList(); 00114 void UpdateListColors(); 00115 BOOL InitList(); 00116 static INT CALLBACK CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData); 00117 static INT CALLBACK ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData); 00118 int LV_FindItemByPidl(LPCITEMIDLIST pidl); 00119 BOOLEAN LV_AddItem(LPCITEMIDLIST pidl); 00120 BOOLEAN LV_DeleteItem(LPCITEMIDLIST pidl); 00121 BOOLEAN LV_RenameItem(LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew); 00122 static INT CALLBACK fill_list(LPVOID ptr, LPVOID arg); 00123 HRESULT FillList(); 00124 HMENU BuildFileMenu(); 00125 void MergeFileMenu(HMENU hSubMenu); 00126 void MergeViewMenu(HMENU hSubMenu); 00127 UINT GetSelections(); 00128 HRESULT OpenSelectedItems(); 00129 void OnDeactivate(); 00130 void DoActivate(UINT uState); 00131 HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); 00132 00133 // *** IOleWindow methods *** 00134 virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd); 00135 virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode); 00136 00137 // *** IShellView methods *** 00138 virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(MSG *pmsg); 00139 virtual HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable); 00140 virtual HRESULT STDMETHODCALLTYPE UIActivate(UINT uState); 00141 virtual HRESULT STDMETHODCALLTYPE Refresh(); 00142 virtual HRESULT STDMETHODCALLTYPE CreateViewWindow(IShellView *psvPrevious, LPCFOLDERSETTINGS pfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd); 00143 virtual HRESULT STDMETHODCALLTYPE DestroyViewWindow(); 00144 virtual HRESULT STDMETHODCALLTYPE GetCurrentInfo(LPFOLDERSETTINGS pfs); 00145 virtual HRESULT STDMETHODCALLTYPE AddPropertySheetPages(DWORD dwReserved, LPFNSVADDPROPSHEETPAGE pfn, LPARAM lparam); 00146 virtual HRESULT STDMETHODCALLTYPE SaveViewState(); 00147 virtual HRESULT STDMETHODCALLTYPE SelectItem(LPCITEMIDLIST pidlItem, SVSIF uFlags); 00148 virtual HRESULT STDMETHODCALLTYPE GetItemObject(UINT uItem, REFIID riid, void **ppv); 00149 00150 // *** IFolderView methods *** 00151 virtual HRESULT STDMETHODCALLTYPE GetCurrentViewMode(UINT *pViewMode); 00152 virtual HRESULT STDMETHODCALLTYPE SetCurrentViewMode(UINT ViewMode); 00153 virtual HRESULT STDMETHODCALLTYPE GetFolder(REFIID riid, void **ppv); 00154 virtual HRESULT STDMETHODCALLTYPE Item(int iItemIndex, LPITEMIDLIST *ppidl); 00155 virtual HRESULT STDMETHODCALLTYPE ItemCount(UINT uFlags, int *pcItems); 00156 virtual HRESULT STDMETHODCALLTYPE Items(UINT uFlags, REFIID riid, void **ppv); 00157 virtual HRESULT STDMETHODCALLTYPE GetSelectionMarkedItem(int *piItem); 00158 virtual HRESULT STDMETHODCALLTYPE GetFocusedItem(int *piItem); 00159 virtual HRESULT STDMETHODCALLTYPE GetItemPosition(LPCITEMIDLIST pidl, POINT *ppt); 00160 virtual HRESULT STDMETHODCALLTYPE GetSpacing(POINT *ppt); 00161 virtual HRESULT STDMETHODCALLTYPE GetDefaultSpacing(POINT *ppt); 00162 virtual HRESULT STDMETHODCALLTYPE GetAutoArrange(); 00163 virtual HRESULT STDMETHODCALLTYPE SelectItem(int iItem, DWORD dwFlags); 00164 virtual HRESULT STDMETHODCALLTYPE SelectAndPositionItems(UINT cidl, LPCITEMIDLIST *apidl, POINT *apt, DWORD dwFlags); 00165 00166 // *** IOleCommandTarget methods *** 00167 virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText); 00168 virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut); 00169 00170 // *** IDropTarget methods *** 00171 virtual HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); 00172 virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); 00173 virtual HRESULT STDMETHODCALLTYPE DragLeave(); 00174 virtual HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect); 00175 00176 // *** IDropSource methods *** 00177 virtual HRESULT STDMETHODCALLTYPE QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState); 00178 virtual HRESULT STDMETHODCALLTYPE GiveFeedback(DWORD dwEffect); 00179 00180 // *** IViewObject methods *** 00181 virtual HRESULT STDMETHODCALLTYPE Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, 00182 HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds, 00183 BOOL ( STDMETHODCALLTYPE *pfnContinue )(ULONG_PTR dwContinue), ULONG_PTR dwContinue); 00184 virtual HRESULT STDMETHODCALLTYPE GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, 00185 DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE **ppColorSet); 00186 virtual HRESULT STDMETHODCALLTYPE Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze); 00187 virtual HRESULT STDMETHODCALLTYPE Unfreeze(DWORD dwFreeze); 00188 virtual HRESULT STDMETHODCALLTYPE SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink); 00189 virtual HRESULT STDMETHODCALLTYPE GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink); 00190 00191 // *** IServiceProvider methods *** 00192 virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject); 00193 00194 // message handlers 00195 LRESULT OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00196 LRESULT OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00197 LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00198 LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00199 LRESULT OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00200 LRESULT OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00201 LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00202 LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00203 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00204 LRESULT OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00205 LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00206 LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00207 LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00208 LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00209 LRESULT OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00210 LRESULT OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00211 LRESULT OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); 00212 00213 static ATL::CWndClassInfo& GetWndClassInfo() 00214 { 00215 static ATL::CWndClassInfo wc = 00216 { 00217 { sizeof(WNDCLASSEX), 0, StartWindowProc, 00218 0, 0, NULL, NULL, 00219 LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_BACKGROUND + 1), NULL, SV_CLASS_NAME, NULL 00220 }, 00221 NULL, NULL, IDC_ARROW, TRUE, 0, _T("") 00222 }; 00223 return wc; 00224 } 00225 00226 virtual WNDPROC GetWindowProc() 00227 { 00228 return WindowProc; 00229 } 00230 00231 static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) 00232 { 00233 CDefView *pThis; 00234 LRESULT result; 00235 00236 // must hold a reference during message handling 00237 pThis = reinterpret_cast<CDefView *>(hWnd); 00238 pThis->AddRef(); 00239 result = CWindowImpl<CDefView, CWindow, CControlWinTraits>::WindowProc(hWnd, uMsg, wParam, lParam); 00240 pThis->Release(); 00241 return result; 00242 } 00243 00244 BEGIN_MSG_MAP(CDefView) 00245 MESSAGE_HANDLER(WM_SIZE, OnSize) 00246 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) 00247 MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus) 00248 MESSAGE_HANDLER(WM_CREATE, OnCreate) 00249 MESSAGE_HANDLER(WM_ACTIVATE, OnActivate) 00250 MESSAGE_HANDLER(WM_NOTIFY, OnNotify) 00251 MESSAGE_HANDLER(WM_COMMAND, OnCommand) 00252 MESSAGE_HANDLER(SHV_CHANGE_NOTIFY, OnChangeNotify) 00253 MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu) 00254 MESSAGE_HANDLER(WM_DRAWITEM, OnCustomItem) 00255 MESSAGE_HANDLER(WM_MEASUREITEM, OnCustomItem) 00256 MESSAGE_HANDLER(WM_SHOWWINDOW, OnShowWindow) 00257 MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode) 00258 MESSAGE_HANDLER(WM_DESTROY, OnDestroy) 00259 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) 00260 MESSAGE_HANDLER(WM_SYSCOLORCHANGE, OnSysColorChange) 00261 MESSAGE_HANDLER(CWM_GETISHELLBROWSER, OnGetShellBrowser) 00262 MESSAGE_HANDLER(WM_SETTINGCHANGE, OnSettingChange) 00263 END_MSG_MAP() 00264 00265 BEGIN_COM_MAP(CDefView) 00266 COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow) 00267 COM_INTERFACE_ENTRY_IID(IID_IShellView, IShellView) 00268 COM_INTERFACE_ENTRY_IID(IID_IFolderView, IFolderView) 00269 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) 00270 COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget) 00271 COM_INTERFACE_ENTRY_IID(IID_IDropSource, IDropSource) 00272 COM_INTERFACE_ENTRY_IID(IID_IViewObject, IViewObject) 00273 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider) 00274 END_COM_MAP() 00275 }; 00276 00277 /* ListView Header ID's */ 00278 #define LISTVIEW_COLUMN_NAME 0 00279 #define LISTVIEW_COLUMN_SIZE 1 00280 #define LISTVIEW_COLUMN_TYPE 2 00281 #define LISTVIEW_COLUMN_TIME 3 00282 #define LISTVIEW_COLUMN_ATTRIB 4 00283 00284 /*menu items */ 00285 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500) 00286 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501) 00287 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502) 00288 00289 #define ID_LISTVIEW 1 00290 00291 /*windowsx.h */ 00292 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp) 00293 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp) 00294 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp) 00295 00296 /* 00297 Items merged into the toolbar and the filemenu 00298 */ 00299 typedef struct 00300 { int idCommand; 00301 int iImage; 00302 int idButtonString; 00303 int idMenuString; 00304 BYTE bState; 00305 BYTE bStyle; 00306 } MYTOOLINFO, *LPMYTOOLINFO; 00307 00308 static const MYTOOLINFO Tools[] = 00309 { 00310 { FCIDM_SHVIEW_BIGICON, 0, 0, IDS_VIEW_LARGE, TBSTATE_ENABLED, BTNS_BUTTON }, 00311 { FCIDM_SHVIEW_SMALLICON, 0, 0, IDS_VIEW_SMALL, TBSTATE_ENABLED, BTNS_BUTTON }, 00312 { FCIDM_SHVIEW_LISTVIEW, 0, 0, IDS_VIEW_LIST, TBSTATE_ENABLED, BTNS_BUTTON }, 00313 { FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON }, 00314 { -1, 0, 0, 0, 0, 0} 00315 }; 00316 00317 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask); 00318 00319 CDefView::CDefView() 00320 { 00321 hWndList = NULL; 00322 hWndParent = NULL; 00323 FolderSettings.fFlags = 0; 00324 FolderSettings.ViewMode = 0; 00325 hMenu = NULL; 00326 uState = 0; 00327 cidl = 0; 00328 apidl = NULL; 00329 ListViewSortInfo.bIsAscending = FALSE; 00330 ListViewSortInfo.nHeaderID = 0; 00331 ListViewSortInfo.nLastHeaderID = 0; 00332 hNotify = 0; 00333 hAccel = NULL; 00334 dwAspects = 0; 00335 dwAdvf = 0; 00336 iDragOverItem = 0; 00337 cScrollDelay = 0; 00338 ptLastMousePos.x = 0; 00339 ptLastMousePos.y = 0; 00340 } 00341 00342 CDefView::~CDefView() 00343 { 00344 TRACE(" destroying IShellView(%p)\n", this); 00345 00346 SHFree(apidl); 00347 } 00348 00349 HRESULT WINAPI CDefView::Initialize(IShellFolder *shellFolder) 00350 { 00351 pSFParent = shellFolder; 00352 shellFolder->QueryInterface(IID_IShellFolder2, (LPVOID *)&pSF2Parent); 00353 00354 return S_OK; 00355 } 00356 00357 /********************************************************** 00358 * 00359 * ##### helperfunctions for communication with ICommDlgBrowser ##### 00360 */ 00361 HRESULT CDefView::IncludeObject(LPCITEMIDLIST pidl) 00362 { 00363 HRESULT ret = S_OK; 00364 00365 if (pCommDlgBrowser.p != NULL) 00366 { 00367 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl); 00368 ret = pCommDlgBrowser->IncludeObject((IShellView *)this, pidl); 00369 TRACE("--0x%08x\n", ret); 00370 } 00371 00372 return ret; 00373 } 00374 00375 HRESULT CDefView::OnDefaultCommand() 00376 { 00377 HRESULT ret = S_FALSE; 00378 00379 if (pCommDlgBrowser.p != NULL) 00380 { 00381 TRACE("ICommDlgBrowser::OnDefaultCommand\n"); 00382 ret = pCommDlgBrowser->OnDefaultCommand((IShellView *)this); 00383 TRACE("-- returns %08x\n", ret); 00384 } 00385 00386 return ret; 00387 } 00388 00389 HRESULT CDefView::OnStateChange(UINT uFlags) 00390 { 00391 HRESULT ret = S_FALSE; 00392 00393 if (pCommDlgBrowser.p != NULL) 00394 { 00395 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags); 00396 ret = pCommDlgBrowser->OnStateChange((IShellView *)this, uFlags); 00397 TRACE("--\n"); 00398 } 00399 00400 return ret; 00401 } 00402 /********************************************************** 00403 * set the toolbar of the filedialog buttons 00404 * 00405 * - activates the buttons from the shellbrowser according to 00406 * the view state 00407 */ 00408 void CDefView::CheckToolbar() 00409 { 00410 LRESULT result; 00411 00412 TRACE("\n"); 00413 00414 if (pCommDlgBrowser != NULL) 00415 { 00416 pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_CHECKBUTTON, 00417 FCIDM_TB_SMALLICON, (FolderSettings.ViewMode == FVM_LIST) ? TRUE : FALSE, &result); 00418 pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_CHECKBUTTON, 00419 FCIDM_TB_REPORTVIEW, (FolderSettings.ViewMode == FVM_DETAILS) ? TRUE : FALSE, &result); 00420 pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON, 00421 FCIDM_TB_SMALLICON, TRUE, &result); 00422 pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON, 00423 FCIDM_TB_REPORTVIEW, TRUE, &result); 00424 } 00425 } 00426 00427 /********************************************************** 00428 * 00429 * ##### helperfunctions for initializing the view ##### 00430 */ 00431 /********************************************************** 00432 * change the style of the listview control 00433 */ 00434 void CDefView::SetStyle(DWORD dwAdd, DWORD dwRemove) 00435 { 00436 DWORD tmpstyle; 00437 00438 TRACE("(%p)\n", this); 00439 00440 tmpstyle = ::GetWindowLongPtrW(hWndList, GWL_STYLE); 00441 ::SetWindowLongPtrW(hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove)); 00442 } 00443 00444 /********************************************************** 00445 * ShellView_CreateList() 00446 * 00447 * - creates the list view window 00448 */ 00449 BOOL CDefView::CreateList() 00450 { DWORD dwStyle, dwExStyle; 00451 00452 TRACE("%p\n", this); 00453 00454 dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | 00455 LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_AUTOARRANGE; 00456 dwExStyle = WS_EX_CLIENTEDGE; 00457 00458 if (FolderSettings.fFlags & FWF_DESKTOP) 00459 dwStyle |= LVS_ALIGNLEFT; 00460 else 00461 dwStyle |= LVS_ALIGNTOP; 00462 00463 switch (FolderSettings.ViewMode) 00464 { 00465 case FVM_ICON: 00466 dwStyle |= LVS_ICON; 00467 break; 00468 00469 case FVM_DETAILS: 00470 dwStyle |= LVS_REPORT; 00471 break; 00472 00473 case FVM_SMALLICON: 00474 dwStyle |= LVS_SMALLICON; 00475 break; 00476 00477 case FVM_LIST: 00478 dwStyle |= LVS_LIST; 00479 break; 00480 00481 default: 00482 dwStyle |= LVS_LIST; 00483 break; 00484 } 00485 00486 if (FolderSettings.fFlags & FWF_AUTOARRANGE) 00487 dwStyle |= LVS_AUTOARRANGE; 00488 00489 if (FolderSettings.fFlags & FWF_DESKTOP) 00490 FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL; 00491 00492 if (FolderSettings.fFlags & FWF_SINGLESEL) 00493 dwStyle |= LVS_SINGLESEL; 00494 00495 if (FolderSettings.fFlags & FWF_NOCLIENTEDGE) 00496 dwExStyle &= ~WS_EX_CLIENTEDGE; 00497 00498 hWndList = CreateWindowExW( dwExStyle, 00499 WC_LISTVIEWW, 00500 NULL, 00501 dwStyle, 00502 0, 0, 0, 0, 00503 m_hWnd, 00504 (HMENU)ID_LISTVIEW, 00505 shell32_hInstance, 00506 NULL); 00507 00508 if (!hWndList) 00509 return FALSE; 00510 00511 ListViewSortInfo.bIsAscending = TRUE; 00512 ListViewSortInfo.nHeaderID = -1; 00513 ListViewSortInfo.nLastHeaderID = -1; 00514 00515 UpdateListColors(); 00516 00517 /* UpdateShellSettings(); */ 00518 return TRUE; 00519 } 00520 00521 void CDefView::UpdateListColors() 00522 { 00523 if (FolderSettings.fFlags & FWF_DESKTOP) 00524 { 00525 /* Check if drop shadows option is enabled */ 00526 BOOL bDropShadow = FALSE; 00527 DWORD cbDropShadow = sizeof(bDropShadow); 00528 WCHAR wszBuf[16] = L""; 00529 00530 RegGetValueW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", 00531 L"ListviewShadow", RRF_RT_DWORD, NULL, &bDropShadow, &cbDropShadow); 00532 if (bDropShadow && SystemParametersInfoW(SPI_GETDESKWALLPAPER, _countof(wszBuf), wszBuf, 0) && wszBuf[0]) 00533 { 00534 SendMessageW(hWndList, LVM_SETTEXTBKCOLOR, 0, CLR_NONE); 00535 SendMessageW(hWndList, LVM_SETBKCOLOR, 0, CLR_NONE); 00536 SendMessageW(hWndList, LVM_SETTEXTCOLOR, 0, RGB(255, 255, 255)); 00537 SendMessageW(hWndList, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTSHADOWTEXT, LVS_EX_TRANSPARENTSHADOWTEXT); 00538 } 00539 else 00540 { 00541 COLORREF crDesktop = GetSysColor(COLOR_DESKTOP); 00542 SendMessageW(hWndList, LVM_SETTEXTBKCOLOR, 0, crDesktop); 00543 SendMessageW(hWndList, LVM_SETBKCOLOR, 0, crDesktop); 00544 if (GetRValue(crDesktop) + GetGValue(crDesktop) + GetBValue(crDesktop) > 128 * 3) 00545 SendMessageW(hWndList, LVM_SETTEXTCOLOR, 0, RGB(0, 0, 0)); 00546 else 00547 SendMessageW(hWndList, LVM_SETTEXTCOLOR, 0, RGB(255, 255, 255)); 00548 SendMessageW(hWndList, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_TRANSPARENTSHADOWTEXT, 0); 00549 } 00550 } 00551 } 00552 00553 /********************************************************** 00554 * ShellView_InitList() 00555 * 00556 * - adds all needed columns to the shellview 00557 */ 00558 BOOL CDefView::InitList() 00559 { 00560 LVCOLUMNW lvColumn; 00561 SHELLDETAILS sd; 00562 WCHAR szTemp[50]; 00563 00564 TRACE("%p\n", this); 00565 00566 SendMessageW(hWndList, LVM_DELETEALLITEMS, 0, 0); 00567 00568 lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; 00569 lvColumn.pszText = szTemp; 00570 00571 if (pSF2Parent) 00572 { 00573 for (int i = 0; 1; i++) 00574 { 00575 if (FAILED(pSF2Parent->GetDetailsOf(NULL, i, &sd))) 00576 break; 00577 00578 lvColumn.fmt = sd.fmt; 00579 lvColumn.cx = sd.cxChar * 8; /* chars->pixel */ 00580 StrRetToStrNW( szTemp, 50, &sd.str, NULL); 00581 SendMessageW(hWndList, LVM_INSERTCOLUMNW, i, (LPARAM) &lvColumn); 00582 } 00583 } 00584 else 00585 { 00586 FIXME("no SF2\n"); 00587 } 00588 00589 SendMessageW(hWndList, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ShellSmallIconList); 00590 SendMessageW(hWndList, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)ShellBigIconList); 00591 00592 return TRUE; 00593 } 00594 00595 /********************************************************** 00596 * ShellView_CompareItems() 00597 * 00598 * NOTES 00599 * internal, CALLBACK for DSA_Sort 00600 */ 00601 INT CALLBACK CDefView::CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData) 00602 { 00603 int ret; 00604 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData); 00605 00606 if (!lpData) 00607 return 0; 00608 00609 ret = (SHORT)SCODE_CODE(((IShellFolder *)lpData)->CompareIDs(0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2)); 00610 TRACE("ret=%i\n", ret); 00611 00612 return ret; 00613 } 00614 00615 /************************************************************************* 00616 * ShellView_ListViewCompareItems 00617 * 00618 * Compare Function for the Listview (FileOpen Dialog) 00619 * 00620 * PARAMS 00621 * lParam1 [I] the first ItemIdList to compare with 00622 * lParam2 [I] the second ItemIdList to compare with 00623 * lpData [I] The column ID for the header Ctrl to process 00624 * 00625 * RETURNS 00626 * A negative value if the first item should precede the second, 00627 * a positive value if the first item should follow the second, 00628 * or zero if the two items are equivalent 00629 * 00630 * NOTES 00631 * FIXME: function does what ShellView_CompareItems is supposed to do. 00632 * unify it and figure out how to use the undocumented first parameter 00633 * of IShellFolder_CompareIDs to do the job this function does and 00634 * move this code to IShellFolder. 00635 * make LISTVIEW_SORT_INFO obsolete 00636 * the way this function works is only usable if we had only 00637 * filesystemfolders (25/10/99 jsch) 00638 */ 00639 INT CALLBACK CDefView::ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData) 00640 { 00641 INT nDiff = 0; 00642 FILETIME fd1, fd2; 00643 char strName1[MAX_PATH], strName2[MAX_PATH]; 00644 BOOL bIsFolder1, bIsFolder2, bIsBothFolder; 00645 LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1; 00646 LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2; 00647 LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData; 00648 00649 00650 bIsFolder1 = _ILIsFolder(pItemIdList1); 00651 bIsFolder2 = _ILIsFolder(pItemIdList2); 00652 bIsBothFolder = bIsFolder1 && bIsFolder2; 00653 00654 /* When sorting between a File and a Folder, the Folder gets sorted first */ 00655 if ( (bIsFolder1 || bIsFolder2) && !bIsBothFolder) 00656 { 00657 nDiff = bIsFolder1 ? -1 : 1; 00658 } 00659 else 00660 { 00661 /* Sort by Time: Folders or Files can be sorted */ 00662 00663 if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME) 00664 { 00665 _ILGetFileDateTime(pItemIdList1, &fd1); 00666 _ILGetFileDateTime(pItemIdList2, &fd2); 00667 nDiff = CompareFileTime(&fd2, &fd1); 00668 } 00669 /* Sort by Attribute: Folder or Files can be sorted */ 00670 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB) 00671 { 00672 _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH); 00673 _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH); 00674 nDiff = lstrcmpiA(strName1, strName2); 00675 } 00676 /* Sort by FileName: Folder or Files can be sorted */ 00677 else if (pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder) 00678 { 00679 /* Sort by Text */ 00680 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH); 00681 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH); 00682 nDiff = lstrcmpiA(strName1, strName2); 00683 } 00684 /* Sort by File Size, Only valid for Files */ 00685 else if (pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE) 00686 { 00687 nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0)); 00688 } 00689 /* Sort by File Type, Only valid for Files */ 00690 else if (pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE) 00691 { 00692 /* Sort by Type */ 00693 _ILGetFileType(pItemIdList1, strName1, MAX_PATH); 00694 _ILGetFileType(pItemIdList2, strName2, MAX_PATH); 00695 nDiff = lstrcmpiA(strName1, strName2); 00696 } 00697 } 00698 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */ 00699 00700 if (nDiff == 0) 00701 { 00702 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH); 00703 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH); 00704 nDiff = lstrcmpiA(strName1, strName2); 00705 } 00706 00707 if (!pSortInfo->bIsAscending) 00708 { 00709 nDiff = -nDiff; 00710 } 00711 00712 return nDiff; 00713 } 00714 00715 /********************************************************** 00716 * LV_FindItemByPidl() 00717 */ 00718 int CDefView::LV_FindItemByPidl(LPCITEMIDLIST pidl) 00719 { 00720 LVITEMW lvItem; 00721 lvItem.iSubItem = 0; 00722 lvItem.mask = LVIF_PARAM; 00723 00724 for (lvItem.iItem = 0; 00725 SendMessageW(hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem); 00726 lvItem.iItem++) 00727 { 00728 LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam; 00729 HRESULT hr = pSFParent->CompareIDs(0, pidl, currentpidl); 00730 00731 if (SUCCEEDED(hr) && !HRESULT_CODE(hr)) 00732 { 00733 return lvItem.iItem; 00734 } 00735 } 00736 return -1; 00737 } 00738 00739 /********************************************************** 00740 * LV_AddItem() 00741 */ 00742 BOOLEAN CDefView::LV_AddItem(LPCITEMIDLIST pidl) 00743 { 00744 LVITEMW lvItem; 00745 00746 TRACE("(%p)(pidl=%p)\n", this, pidl); 00747 00748 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/ 00749 lvItem.iItem = ListView_GetItemCount(hWndList); /*add the item to the end of the list*/ 00750 lvItem.iSubItem = 0; 00751 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/ 00752 lvItem.pszText = LPSTR_TEXTCALLBACKW; /*get text on a callback basis*/ 00753 lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/ 00754 00755 if (SendMessageW(hWndList, LVM_INSERTITEMW, 0, (LPARAM)&lvItem) == -1) 00756 return FALSE; 00757 else 00758 return TRUE; 00759 } 00760 00761 /********************************************************** 00762 * LV_DeleteItem() 00763 */ 00764 BOOLEAN CDefView::LV_DeleteItem(LPCITEMIDLIST pidl) 00765 { 00766 int nIndex; 00767 00768 TRACE("(%p)(pidl=%p)\n", this, pidl); 00769 00770 nIndex = LV_FindItemByPidl(ILFindLastID(pidl)); 00771 00772 return (-1 == ListView_DeleteItem(hWndList, nIndex)) ? FALSE : TRUE; 00773 } 00774 00775 /********************************************************** 00776 * LV_RenameItem() 00777 */ 00778 BOOLEAN CDefView::LV_RenameItem(LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew) 00779 { 00780 int nItem; 00781 LVITEMW lvItem; 00782 00783 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", this, pidlOld, pidlNew); 00784 00785 nItem = LV_FindItemByPidl(ILFindLastID(pidlOld)); 00786 00787 if ( -1 != nItem ) 00788 { 00789 lvItem.mask = LVIF_PARAM; /* only the pidl */ 00790 lvItem.iItem = nItem; 00791 SendMessageW(hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem); 00792 00793 SHFree((LPITEMIDLIST)lvItem.lParam); 00794 lvItem.mask = LVIF_PARAM|LVIF_IMAGE; 00795 lvItem.iItem = nItem; 00796 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */ 00797 lvItem.iImage = SHMapPIDLToSystemImageListIndex(pSFParent, pidlNew, 0); 00798 SendMessageW(hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem); 00799 SendMessageW(hWndList, LVM_UPDATE, nItem, 0); 00800 return TRUE; /* FIXME: better handling */ 00801 } 00802 00803 return FALSE; 00804 } 00805 00806 /********************************************************** 00807 * ShellView_FillList() 00808 * 00809 * - gets the objectlist from the shellfolder 00810 * - sorts the list 00811 * - fills the list into the view 00812 */ 00813 INT CALLBACK CDefView::fill_list( LPVOID ptr, LPVOID arg ) 00814 { 00815 LPITEMIDLIST pidl = (LPITEMIDLIST)ptr; 00816 CDefView *pThis = (CDefView *)arg; 00817 /* in a commdlg This works as a filemask*/ 00818 if (pThis->IncludeObject(pidl) == S_OK) 00819 pThis->LV_AddItem(pidl); 00820 00821 SHFree(pidl); 00822 return TRUE; 00823 } 00824 00825 HRESULT CDefView::FillList() 00826 { 00827 LPENUMIDLIST pEnumIDList; 00828 LPITEMIDLIST pidl; 00829 DWORD dwFetched; 00830 HRESULT hRes; 00831 HDPA hdpa; 00832 00833 TRACE("%p\n", this); 00834 00835 /* get the itemlist from the shfolder*/ 00836 hRes = pSFParent->EnumObjects(m_hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList); 00837 if (hRes != S_OK) 00838 { 00839 if (hRes == S_FALSE) 00840 return(NOERROR); 00841 return(hRes); 00842 } 00843 00844 /* create a pointer array */ 00845 hdpa = DPA_Create(16); 00846 if (!hdpa) 00847 { 00848 return(E_OUTOFMEMORY); 00849 } 00850 00851 /* copy the items into the array*/ 00852 while((S_OK == pEnumIDList->Next(1, &pidl, &dwFetched)) && dwFetched) 00853 { 00854 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1) 00855 { 00856 SHFree(pidl); 00857 } 00858 } 00859 00860 /* sort the array */ 00861 DPA_Sort(hdpa, CompareItems, (LPARAM)pSFParent.p); 00862 00863 /*turn the listview's redrawing off*/ 00864 SendMessageA(hWndList, WM_SETREDRAW, FALSE, 0); 00865 00866 DPA_DestroyCallback( hdpa, fill_list, (void *)this); 00867 00868 /*turn the listview's redrawing back on and force it to draw*/ 00869 SendMessageA(hWndList, WM_SETREDRAW, TRUE, 0); 00870 00871 pEnumIDList->Release(); /* destroy the list*/ 00872 00873 return S_OK; 00874 } 00875 00876 LRESULT CDefView::OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 00877 { 00878 ::UpdateWindow(hWndList); 00879 bHandled = FALSE; 00880 return 0; 00881 } 00882 00883 LRESULT CDefView::OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 00884 { 00885 return SendMessageW(hWndList, uMsg, 0, 0); 00886 } 00887 00888 LRESULT CDefView::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 00889 { 00890 RevokeDragDrop(m_hWnd); 00891 SHChangeNotifyDeregister(hNotify); 00892 bHandled = FALSE; 00893 return 0; 00894 } 00895 00896 LRESULT CDefView::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 00897 { 00898 if (FolderSettings.fFlags & (FWF_DESKTOP | FWF_TRANSPARENT)) 00899 return SendMessageW(GetParent(), WM_ERASEBKGND, wParam, lParam); /* redirect to parent */ 00900 00901 bHandled = FALSE; 00902 return 0; 00903 } 00904 00905 LRESULT CDefView::OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 00906 { 00907 /* Update desktop labels color */ 00908 UpdateListColors(); 00909 00910 /* Forward WM_SYSCOLORCHANGE to common controls */ 00911 return SendMessageW(hWndList, uMsg, 0, 0); 00912 } 00913 00914 LRESULT CDefView::OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 00915 { 00916 return (LRESULT)pShellBrowser.p; 00917 } 00918 00919 /********************************************************** 00920 * ShellView_OnCreate() 00921 */ 00922 LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 00923 { 00924 CComPtr<IDropTarget> pdt; 00925 SHChangeNotifyEntry ntreg; 00926 CComPtr<IPersistFolder2> ppf2; 00927 00928 TRACE("%p\n", this); 00929 00930 if(CreateList()) 00931 { 00932 if(InitList()) 00933 { 00934 FillList(); 00935 } 00936 } 00937 00938 if (SUCCEEDED(this->QueryInterface(IID_IDropTarget, (LPVOID*)&pdt))) 00939 RegisterDragDrop(m_hWnd, pdt); 00940 00941 /* register for receiving notifications */ 00942 pSFParent->QueryInterface(IID_IPersistFolder2, (LPVOID*)&ppf2); 00943 if (ppf2) 00944 { 00945 ppf2->GetCurFolder((LPITEMIDLIST*)&ntreg.pidl); 00946 ntreg.fRecursive = TRUE; 00947 hNotify = SHChangeNotifyRegister(m_hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg); 00948 SHFree((LPITEMIDLIST)ntreg.pidl); 00949 } 00950 00951 hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel"); 00952 00953 return S_OK; 00954 } 00955 00956 /********************************************************** 00957 * #### Handling of the menus #### 00958 */ 00959 00960 /********************************************************** 00961 * ShellView_BuildFileMenu() 00962 */ 00963 HMENU CDefView::BuildFileMenu() 00964 { WCHAR szText[MAX_PATH]; 00965 MENUITEMINFOW mii; 00966 int nTools, i; 00967 HMENU hSubMenu; 00968 00969 TRACE("(%p)\n", this); 00970 00971 hSubMenu = CreatePopupMenu(); 00972 if (hSubMenu) 00973 { 00974 /*get the number of items in our global array*/ 00975 for(nTools = 0; Tools[nTools].idCommand != -1; nTools++) {} 00976 00977 /*add the menu items*/ 00978 for(i = 0; i < nTools; i++) 00979 { 00980 LoadStringW(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH); 00981 00982 ZeroMemory(&mii, sizeof(mii)); 00983 mii.cbSize = sizeof(mii); 00984 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE; 00985 00986 if(BTNS_SEP != Tools[i].bStyle) /* no separator*/ 00987 { 00988 mii.fType = MFT_STRING; 00989 mii.fState = MFS_ENABLED; 00990 mii.dwTypeData = szText; 00991 mii.wID = Tools[i].idCommand; 00992 } 00993 else 00994 { 00995 mii.fType = MFT_SEPARATOR; 00996 } 00997 /* tack This item onto the end of the menu */ 00998 InsertMenuItemW(hSubMenu, (UINT) - 1, TRUE, &mii); 00999 } 01000 } 01001 01002 TRACE("-- return (menu=%p)\n", hSubMenu); 01003 return hSubMenu; 01004 } 01005 01006 /********************************************************** 01007 * ShellView_MergeFileMenu() 01008 */ 01009 void CDefView::MergeFileMenu(HMENU hSubMenu) 01010 { 01011 TRACE("(%p)->(submenu=%p) stub\n", this, hSubMenu); 01012 01013 if (hSubMenu) 01014 { /*insert This item at the beginning of the menu */ 01015 _InsertMenuItemW(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); 01016 _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, L"dummy45", MFS_ENABLED); 01017 } 01018 01019 TRACE("--\n"); 01020 } 01021 01022 /********************************************************** 01023 * ShellView_MergeViewMenu() 01024 */ 01025 void CDefView::MergeViewMenu(HMENU hSubMenu) 01026 { 01027 TRACE("(%p)->(submenu=%p)\n", this, hSubMenu); 01028 01029 if (hSubMenu) 01030 { 01031 /*add a separator at the correct position in the menu*/ 01032 MENUITEMINFOW mii; 01033 static WCHAR view[] = L"View"; 01034 01035 _InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED); 01036 01037 ZeroMemory(&mii, sizeof(mii)); 01038 mii.cbSize = sizeof(mii); 01039 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA; 01040 mii.fType = MFT_STRING; 01041 mii.dwTypeData = view; 01042 mii.hSubMenu = LoadMenuW(shell32_hInstance, L"MENU_001"); 01043 InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii); 01044 } 01045 } 01046 01047 /********************************************************** 01048 * ShellView_GetSelections() 01049 * 01050 * - fills the this->apidl list with the selected objects 01051 * 01052 * RETURNS 01053 * number of selected items 01054 */ 01055 UINT CDefView::GetSelections() 01056 { 01057 LVITEMW lvItem; 01058 UINT i = 0; 01059 01060 SHFree(apidl); 01061 01062 cidl = ListView_GetSelectedCount(hWndList); 01063 apidl = (LPITEMIDLIST*)SHAlloc(cidl * sizeof(LPITEMIDLIST)); 01064 01065 TRACE("selected=%i\n", cidl); 01066 01067 if (apidl) 01068 { 01069 TRACE("-- Items selected =%u\n", cidl); 01070 01071 lvItem.mask = LVIF_STATE | LVIF_PARAM; 01072 lvItem.stateMask = LVIS_SELECTED; 01073 lvItem.iItem = 0; 01074 lvItem.iSubItem = 0; 01075 lvItem.state = 0; 01076 01077 while(SendMessageW(hWndList, LVM_GETITEMW, 0, (LPARAM)&lvItem) && (i < cidl)) 01078 { 01079 if(lvItem.state & LVIS_SELECTED) 01080 { 01081 apidl[i] = (LPITEMIDLIST)lvItem.lParam; 01082 i++; 01083 if (i == cidl) 01084 break; 01085 TRACE("-- selected Item found\n"); 01086 } 01087 lvItem.iItem++; 01088 } 01089 } 01090 01091 return cidl; 01092 } 01093 01094 /********************************************************** 01095 * ShellView_OpenSelectedItems() 01096 */ 01097 HRESULT CDefView::OpenSelectedItems() 01098 { 01099 static UINT CF_IDLIST = 0; 01100 HRESULT hr; 01101 CComPtr<IDataObject> selection; 01102 CComPtr<IContextMenu> cm; 01103 HMENU hmenu; 01104 FORMATETC fetc; 01105 STGMEDIUM stgm; 01106 LPIDA pIDList; 01107 LPCITEMIDLIST parent_pidl; 01108 WCHAR parent_path[MAX_PATH]; 01109 LPCWSTR parent_dir = NULL; 01110 SFGAOF attribs; 01111 int i; 01112 CMINVOKECOMMANDINFOEX ici; 01113 MENUITEMINFOW info; 01114 01115 if (0 == GetSelections()) 01116 { 01117 return S_OK; 01118 } 01119 01120 hr = pSFParent->GetUIObjectOf(m_hWnd, cidl, 01121 (LPCITEMIDLIST*)apidl, IID_IContextMenu, 01122 0, (LPVOID *)&cm); 01123 01124 if (SUCCEEDED(hr)) 01125 { 01126 hmenu = CreatePopupMenu(); 01127 if (hmenu) 01128 { 01129 hr = IUnknown_SetSite(cm, (IShellView *)this); 01130 if (SUCCEEDED(cm->QueryContextMenu(hmenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY))) 01131 { 01132 INT def = -1, n = GetMenuItemCount(hmenu); 01133 01134 for ( i = 0; i < n; i++ ) 01135 { 01136 memset( &info, 0, sizeof info ); 01137 info.cbSize = sizeof info; 01138 info.fMask = MIIM_FTYPE | MIIM_STATE | MIIM_ID; 01139 if (GetMenuItemInfoW( hmenu, i, TRUE, &info)) 01140 { 01141 if (info.fState & MFS_DEFAULT) 01142 { 01143 def = info.wID; 01144 break; 01145 } 01146 } 01147 } 01148 if (def != -1) 01149 { 01150 memset( &ici, 0, sizeof ici ); 01151 ici.cbSize = sizeof ici; 01152 ici.lpVerb = MAKEINTRESOURCEA( def ); 01153 ici.hwnd = m_hWnd; 01154 01155 hr = cm->InvokeCommand((LPCMINVOKECOMMANDINFO)&ici); 01156 if (hr == S_OK) 01157 { 01158 DestroyMenu(hmenu); 01159 hr = IUnknown_SetSite(cm, NULL); 01160 return S_OK; 01161 } 01162 else 01163 ERR("InvokeCommand failed: %x\n", hr); 01164 } 01165 else 01166 ERR("No default context menu item\n"); 01167 01168 } 01169 DestroyMenu( hmenu ); 01170 hr = IUnknown_SetSite(cm, NULL); 01171 } 01172 } 01173 01174 01175 01176 hr = pSFParent->GetUIObjectOf(m_hWnd, cidl, 01177 (LPCITEMIDLIST*)apidl, IID_IDataObject, 01178 0, (LPVOID *)&selection); 01179 01180 01181 01182 if (FAILED(hr)) 01183 return hr; 01184 01185 if (0 == CF_IDLIST) 01186 { 01187 CF_IDLIST = RegisterClipboardFormatW(CFSTR_SHELLIDLIST); 01188 } 01189 01190 fetc.cfFormat = CF_IDLIST; 01191 fetc.ptd = NULL; 01192 fetc.dwAspect = DVASPECT_CONTENT; 01193 fetc.lindex = -1; 01194 fetc.tymed = TYMED_HGLOBAL; 01195 01196 hr = selection->QueryGetData(&fetc); 01197 if (FAILED(hr)) 01198 return hr; 01199 01200 hr = selection->GetData(&fetc, &stgm); 01201 if (FAILED(hr)) 01202 return hr; 01203 01204 pIDList = (LPIDA)GlobalLock(stgm.hGlobal); 01205 01206 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList + pIDList->aoffset[0]); 01207 hr = pSFParent->GetAttributesOf(1, &parent_pidl, &attribs); 01208 if (SUCCEEDED(hr) && (attribs & SFGAO_FILESYSTEM) && 01209 SHGetPathFromIDListW(parent_pidl, parent_path)) 01210 { 01211 parent_dir = parent_path; 01212 } 01213 01214 for (i = pIDList->cidl; i > 0; --i) 01215 { 01216 LPCITEMIDLIST pidl; 01217 01218 pidl = (LPCITEMIDLIST)((LPBYTE)pIDList + pIDList->aoffset[i]); 01219 01220 attribs = SFGAO_FOLDER; 01221 hr = pSFParent->GetAttributesOf(1, &pidl, &attribs); 01222 01223 if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER)) 01224 { 01225 SHELLEXECUTEINFOW shexinfo; 01226 01227 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOW); 01228 shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */ 01229 shexinfo.hwnd = NULL; 01230 shexinfo.lpVerb = NULL; 01231 shexinfo.lpFile = NULL; 01232 shexinfo.lpParameters = NULL; 01233 shexinfo.lpDirectory = parent_dir; 01234 shexinfo.nShow = SW_NORMAL; 01235 shexinfo.lpIDList = ILCombine(parent_pidl, pidl); 01236 01237 ShellExecuteExW(&shexinfo); /* Discard error/success info */ 01238 01239 ILFree((LPITEMIDLIST)shexinfo.lpIDList); 01240 } 01241 } 01242 01243 GlobalUnlock(stgm.hGlobal); 01244 ReleaseStgMedium(&stgm); 01245 01246 return S_OK; 01247 } 01248 01249 /********************************************************** 01250 * ShellView_DoContextMenu() 01251 */ 01252 LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 01253 { 01254 WORD x; 01255 WORD y; 01256 UINT uCommand; 01257 DWORD wFlags; 01258 HMENU hMenu; 01259 BOOL fExplore; 01260 HWND hwndTree; 01261 CMINVOKECOMMANDINFO cmi; 01262 HRESULT hResult; 01263 01264 // for some reason I haven't figured out, we sometimes recurse into this method 01265 if (pCM != NULL) 01266 return 0; 01267 01268 x = LOWORD(lParam); 01269 y = HIWORD(lParam); 01270 01271 TRACE("(%p)->(0x%08x 0x%08x) stub\n", this, x, y); 01272 01273 fExplore = FALSE; 01274 hwndTree = NULL; 01275 01276 /* look, what's selected and create a context menu object of it*/ 01277 if (GetSelections()) 01278 { 01279 pSFParent->GetUIObjectOf(hWndParent, cidl, (LPCITEMIDLIST*)apidl, IID_IContextMenu, NULL, (LPVOID *)&pCM); 01280 01281 if (pCM) 01282 { 01283 TRACE("-- pContextMenu\n"); 01284 hMenu = CreatePopupMenu(); 01285 01286 if (hMenu) 01287 { 01288 hResult = IUnknown_SetSite(pCM, (IShellView *)this); 01289 01290 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/ 01291 if (SUCCEEDED(pShellBrowser->GetControlWindow(FCW_TREE, &hwndTree)) && hwndTree) 01292 { 01293 TRACE("-- explore mode\n"); 01294 fExplore = TRUE; 01295 } 01296 01297 /* build the flags depending on what we can do with the selected item */ 01298 wFlags = CMF_NORMAL | (cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0); 01299 01300 /* let the ContextMenu merge its items in */ 01301 if (SUCCEEDED(pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags ))) 01302 { 01303 if (FolderSettings.fFlags & FWF_DESKTOP) 01304 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND); 01305 01306 TRACE("-- track popup\n"); 01307 uCommand = TrackPopupMenu(hMenu, 01308 TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, 01309 x, y, 0, m_hWnd, NULL); 01310 01311 if (uCommand > 0) 01312 { 01313 TRACE("-- uCommand=%u\n", uCommand); 01314 01315 if (uCommand == FCIDM_SHVIEW_OPEN && pCommDlgBrowser.p != NULL) 01316 { 01317 TRACE("-- dlg: OnDefaultCommand\n"); 01318 if (OnDefaultCommand() != S_OK) 01319 OpenSelectedItems(); 01320 } 01321 else 01322 { 01323 TRACE("-- explore -- invoke command\n"); 01324 ZeroMemory(&cmi, sizeof(cmi)); 01325 cmi.cbSize = sizeof(cmi); 01326 cmi.hwnd = hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */ 01327 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand); 01328 pCM->InvokeCommand(&cmi); 01329 } 01330 } 01331 01332 hResult = IUnknown_SetSite(pCM, NULL); 01333 DestroyMenu(hMenu); 01334 } 01335 } 01336 pCM.Release(); 01337 } 01338 } 01339 else /* background context menu */ 01340 { 01341 hMenu = CreatePopupMenu(); 01342 01343 CDefFolderMenu_Create2(NULL, NULL, cidl, (LPCITEMIDLIST*)apidl, pSFParent, NULL, 0, NULL, (IContextMenu**)&pCM); 01344 pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0); 01345 01346 uCommand = TrackPopupMenu(hMenu, 01347 TPM_LEFTALIGN | TPM_RETURNCMD | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, 01348 x, y, 0, m_hWnd, NULL); 01349 DestroyMenu(hMenu); 01350 01351 TRACE("-- (%p)->(uCommand=0x%08x )\n", this, uCommand); 01352 01353 ZeroMemory(&cmi, sizeof(cmi)); 01354 cmi.cbSize = sizeof(cmi); 01355 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand); 01356 cmi.hwnd = hWndParent; 01357 pCM->InvokeCommand(&cmi); 01358 01359 pCM.Release(); 01360 } 01361 01362 return 0; 01363 } 01364 01365 /********************************************************** 01366 * ##### message handling ##### 01367 */ 01368 01369 /********************************************************** 01370 * ShellView_OnSize() 01371 */ 01372 LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 01373 { 01374 WORD wWidth; 01375 WORD wHeight; 01376 01377 wWidth = LOWORD(lParam); 01378 wHeight = HIWORD(lParam); 01379 01380 TRACE("%p width=%u height=%u\n", this, wWidth, wHeight); 01381 01382 /*resize the ListView to fit our window*/ 01383 if (hWndList) 01384 { 01385 ::MoveWindow(hWndList, 0, 0, wWidth, wHeight, TRUE); 01386 } 01387 01388 return 0; 01389 } 01390 01391 /********************************************************** 01392 * ShellView_OnDeactivate() 01393 * 01394 * NOTES 01395 * internal 01396 */ 01397 void CDefView::OnDeactivate() 01398 { 01399 TRACE("%p\n", this); 01400 01401 if (uState != SVUIA_DEACTIVATE) 01402 { 01403 if (hMenu) 01404 { 01405 pShellBrowser->SetMenuSB(0, 0, 0); 01406 pShellBrowser->RemoveMenusSB(hMenu); 01407 DestroyMenu(hMenu); 01408 hMenu = 0; 01409 } 01410 01411 uState = SVUIA_DEACTIVATE; 01412 } 01413 } 01414 01415 void CDefView::DoActivate(UINT uState) 01416 { 01417 OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} }; 01418 MENUITEMINFOA mii; 01419 CHAR szText[MAX_PATH]; 01420 01421 TRACE("%p uState=%x\n", this, uState); 01422 01423 /*don't do anything if the state isn't really changing */ 01424 if (this->uState == uState) 01425 { 01426 return; 01427 } 01428 01429 OnDeactivate(); 01430 01431 /*only do This if we are active */ 01432 if(uState != SVUIA_DEACTIVATE) 01433 { 01434 /*merge the menus */ 01435 hMenu = CreateMenu(); 01436 01437 if(hMenu) 01438 { 01439 pShellBrowser->InsertMenusSB(hMenu, &omw); 01440 TRACE("-- after fnInsertMenusSB\n"); 01441 01442 /*build the top level menu get the menu item's text*/ 01443 strcpy(szText, "dummy 31"); 01444 01445 ZeroMemory(&mii, sizeof(mii)); 01446 mii.cbSize = sizeof(mii); 01447 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE; 01448 mii.fType = MFT_STRING; 01449 mii.fState = MFS_ENABLED; 01450 mii.dwTypeData = szText; 01451 mii.hSubMenu = BuildFileMenu(); 01452 01453 /*insert our menu into the menu bar*/ 01454 if (mii.hSubMenu) 01455 { 01456 InsertMenuItemA(hMenu, FCIDM_MENU_HELP, FALSE, &mii); 01457 } 01458 01459 /*get the view menu so we can merge with it*/ 01460 ZeroMemory(&mii, sizeof(mii)); 01461 mii.cbSize = sizeof(mii); 01462 mii.fMask = MIIM_SUBMENU; 01463 01464 if (GetMenuItemInfoA(hMenu, FCIDM_MENU_VIEW, FALSE, &mii)) 01465 { 01466 MergeViewMenu(mii.hSubMenu); 01467 } 01468 01469 /*add the items that should only be added if we have the focus*/ 01470 if (SVUIA_ACTIVATE_FOCUS == uState) 01471 { 01472 /*get the file menu so we can merge with it */ 01473 ZeroMemory(&mii, sizeof(mii)); 01474 mii.cbSize = sizeof(mii); 01475 mii.fMask = MIIM_SUBMENU; 01476 01477 if (GetMenuItemInfoA(hMenu, FCIDM_MENU_FILE, FALSE, &mii)) 01478 { 01479 MergeFileMenu(mii.hSubMenu); 01480 } 01481 } 01482 01483 TRACE("-- before fnSetMenuSB\n"); 01484 pShellBrowser->SetMenuSB(hMenu, 0, m_hWnd); 01485 } 01486 } 01487 this->uState = uState; 01488 TRACE("--\n"); 01489 } 01490 01491 /********************************************************** 01492 * ShellView_OnActivate() 01493 */ 01494 LRESULT CDefView::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 01495 { 01496 DoActivate(SVUIA_ACTIVATE_FOCUS); 01497 return 0; 01498 } 01499 01500 /********************************************************** 01501 * ShellView_OnSetFocus() 01502 * 01503 */ 01504 LRESULT CDefView::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 01505 { 01506 TRACE("%p\n", this); 01507 01508 /* Tell the browser one of our windows has received the focus. This 01509 should always be done before merging menus (OnActivate merges the 01510 menus) if one of our windows has the focus.*/ 01511 01512 pShellBrowser->OnViewWindowActive((IShellView *)this); 01513 DoActivate(SVUIA_ACTIVATE_FOCUS); 01514 01515 /* Set the focus to the listview */ 01516 ::SetFocus(hWndList); 01517 01518 /* Notify the ICommDlgBrowser interface */ 01519 OnStateChange(CDBOSC_SETFOCUS); 01520 01521 return 0; 01522 } 01523 01524 /********************************************************** 01525 * ShellView_OnKillFocus() 01526 */ 01527 LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 01528 { 01529 TRACE("(%p) stub\n", this); 01530 01531 DoActivate(SVUIA_ACTIVATE_NOFOCUS); 01532 /* Notify the ICommDlgBrowser */ 01533 OnStateChange(CDBOSC_KILLFOCUS); 01534 01535 return 0; 01536 } 01537 01538 /********************************************************** 01539 * ShellView_OnCommand() 01540 * 01541 * NOTES 01542 * the CmdID's are the ones from the context menu 01543 */ 01544 LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 01545 { 01546 DWORD dwCmdID; 01547 DWORD dwCmd; 01548 HWND hwndCmd; 01549 01550 dwCmdID = GET_WM_COMMAND_ID(wParam, lParam); 01551 dwCmd = GET_WM_COMMAND_CMD(wParam, lParam); 01552 hwndCmd = GET_WM_COMMAND_HWND(wParam, lParam); 01553 01554 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n", this, dwCmdID, dwCmd, hwndCmd); 01555 01556 switch (dwCmdID) 01557 { 01558 case FCIDM_SHVIEW_SMALLICON: 01559 FolderSettings.ViewMode = FVM_SMALLICON; 01560 SetStyle (LVS_SMALLICON, LVS_TYPEMASK); 01561 CheckToolbar(); 01562 break; 01563 01564 case FCIDM_SHVIEW_BIGICON: 01565 FolderSettings.ViewMode = FVM_ICON; 01566 SetStyle (LVS_ICON, LVS_TYPEMASK); 01567 CheckToolbar(); 01568 break; 01569 01570 case FCIDM_SHVIEW_LISTVIEW: 01571 FolderSettings.ViewMode = FVM_LIST; 01572 SetStyle (LVS_LIST, LVS_TYPEMASK); 01573 CheckToolbar(); 01574 break; 01575 01576 case FCIDM_SHVIEW_REPORTVIEW: 01577 FolderSettings.ViewMode = FVM_DETAILS; 01578 SetStyle (LVS_REPORT, LVS_TYPEMASK); 01579 CheckToolbar(); 01580 break; 01581 01582 /* the menu-ID's for sorting are 0x30... see shrec.rc */ 01583 case 0x30: 01584 case 0x31: 01585 case 0x32: 01586 case 0x33: 01587 ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30); 01588 ListViewSortInfo.bIsAscending = TRUE; 01589 ListViewSortInfo.nLastHeaderID = ListViewSortInfo.nHeaderID; 01590 SendMessageA(hWndList, LVM_SORTITEMS, (WPARAM) &ListViewSortInfo, (LPARAM)ListViewCompareItems); 01591 break; 01592 01593 default: 01594 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID); 01595 } 01596 01597 return 0; 01598 } 01599 01600 /********************************************************** 01601 * ShellView_OnNotify() 01602 */ 01603 01604 LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 01605 { 01606 UINT CtlID; 01607 LPNMHDR lpnmh; 01608 LPNMLISTVIEW lpnmlv; 01609 NMLVDISPINFOW *lpdi; 01610 LPITEMIDLIST pidl; 01611 BOOL unused; 01612 01613 CtlID = wParam; 01614 lpnmh = (LPNMHDR)lParam; 01615 lpnmlv = (LPNMLISTVIEW)lpnmh; 01616 lpdi = (NMLVDISPINFOW *)lpnmh; 01617 01618 TRACE("%p CtlID=%u lpnmh->code=%x\n", this, CtlID, lpnmh->code); 01619 01620 switch (lpnmh->code) 01621 { 01622 case NM_SETFOCUS: 01623 TRACE("-- NM_SETFOCUS %p\n", this); 01624 OnSetFocus(0, 0, 0, unused); 01625 break; 01626 01627 case NM_KILLFOCUS: 01628 TRACE("-- NM_KILLFOCUS %p\n", this); 01629 OnDeactivate(); 01630 /* Notify the ICommDlgBrowser interface */ 01631 OnStateChange(CDBOSC_KILLFOCUS); 01632 break; 01633 01634 case NM_CUSTOMDRAW: 01635 TRACE("-- NM_CUSTOMDRAW %p\n", this); 01636 return CDRF_DODEFAULT; 01637 01638 case NM_RELEASEDCAPTURE: 01639 TRACE("-- NM_RELEASEDCAPTURE %p\n", this); 01640 break; 01641 01642 case NM_CLICK: 01643 TRACE("-- NM_CLICK %p\n", this); 01644 break; 01645 01646 case NM_RCLICK: 01647 TRACE("-- NM_RCLICK %p\n", this); 01648 break; 01649 01650 case NM_DBLCLK: 01651 TRACE("-- NM_DBLCLK %p\n", this); 01652 if (OnDefaultCommand() != S_OK) OpenSelectedItems(); 01653 break; 01654 01655 case NM_RETURN: 01656 TRACE("-- NM_RETURN %p\n", this); 01657 if (OnDefaultCommand() != S_OK) OpenSelectedItems(); 01658 break; 01659 01660 case HDN_ENDTRACKW: 01661 TRACE("-- HDN_ENDTRACKW %p\n", this); 01662 /*nColumn1 = ListView_GetColumnWidth(hWndList, 0); 01663 nColumn2 = ListView_GetColumnWidth(hWndList, 1);*/ 01664 break; 01665 01666 case LVN_DELETEITEM: 01667 TRACE("-- LVN_DELETEITEM %p\n", this); 01668 SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/ 01669 break; 01670 01671 case LVN_DELETEALLITEMS: 01672 TRACE("-- LVN_DELETEALLITEMS %p\n", this); 01673 return FALSE; 01674 01675 case LVN_INSERTITEM: 01676 TRACE("-- LVN_INSERTITEM (STUB)%p\n", this); 01677 break; 01678 01679 case LVN_ITEMACTIVATE: 01680 TRACE("-- LVN_ITEMACTIVATE %p\n", this); 01681 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */ 01682 break; 01683 01684 case LVN_COLUMNCLICK: 01685 ListViewSortInfo.nHeaderID = lpnmlv->iSubItem; 01686 if (ListViewSortInfo.nLastHeaderID == ListViewSortInfo.nHeaderID) 01687 { 01688 ListViewSortInfo.bIsAscending = !ListViewSortInfo.bIsAscending; 01689 } 01690 else 01691 { 01692 ListViewSortInfo.bIsAscending = TRUE; 01693 } 01694 ListViewSortInfo.nLastHeaderID = ListViewSortInfo.nHeaderID; 01695 01696 SendMessageW(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &ListViewSortInfo, (LPARAM)ListViewCompareItems); 01697 break; 01698 01699 case LVN_GETDISPINFOA: 01700 case LVN_GETDISPINFOW: 01701 TRACE("-- LVN_GETDISPINFO %p\n", this); 01702 pidl = (LPITEMIDLIST)lpdi->item.lParam; 01703 01704 if (lpdi->item.mask & LVIF_TEXT) /* text requested */ 01705 { 01706 if (pSF2Parent) 01707 { 01708 SHELLDETAILS sd; 01709 if (FAILED(pSF2Parent->GetDetailsOf(pidl, lpdi->item.iSubItem, &sd))) 01710 { 01711 FIXME("failed to get details\n"); 01712 break; 01713 } 01714 01715 if (lpnmh->code == LVN_GETDISPINFOA) 01716 { 01717 /* shouldn't happen */ 01718 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh; 01719 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL); 01720 TRACE("-- text=%s\n", lpdiA->item.pszText); 01721 } 01722 else /* LVN_GETDISPINFOW */ 01723 { 01724 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL); 01725 TRACE("-- text=%s\n", debugstr_w(lpdi->item.pszText)); 01726 } 01727 } 01728 else 01729 { 01730 FIXME("no SF2\n"); 01731 } 01732 } 01733 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */ 01734 { 01735 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(pSFParent, pidl, 0); 01736 } 01737 lpdi->item.mask |= LVIF_DI_SETITEM; 01738 break; 01739 01740 case LVN_ITEMCHANGED: 01741 TRACE("-- LVN_ITEMCHANGED %p\n", this); 01742 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */ 01743 break; 01744 01745 case LVN_BEGINDRAG: 01746 case LVN_BEGINRDRAG: 01747 TRACE("-- LVN_BEGINDRAG\n"); 01748 01749 if (GetSelections()) 01750 { 01751 IDataObject * pda; 01752 DWORD dwAttributes = SFGAO_CANLINK; 01753 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE; 01754 01755 if (SUCCEEDED(pSFParent->GetUIObjectOf(m_hWnd, cidl, (LPCITEMIDLIST*)apidl, IID_IDataObject, 0, (LPVOID *)&pda))) 01756 { 01757 IDropSource * pds = (IDropSource *)this; /* own DropSource interface */ 01758 01759 if (SUCCEEDED(pSFParent->GetAttributesOf(cidl, (LPCITEMIDLIST*)apidl, &dwAttributes))) 01760 { 01761 if (dwAttributes & SFGAO_CANLINK) 01762 { 01763 dwEffect |= DROPEFFECT_LINK; 01764 } 01765 } 01766 01767 if (pds) 01768 { 01769 DWORD dwEffect2; 01770 DoDragDrop(pda, pds, dwEffect, &dwEffect2); 01771 } 01772 pda->Release(); 01773 } 01774 } 01775 break; 01776 01777 case LVN_BEGINLABELEDITW: 01778 { 01779 DWORD dwAttr = SFGAO_CANRENAME; 01780 pidl = (LPITEMIDLIST)lpdi->item.lParam; 01781 01782 TRACE("-- LVN_BEGINLABELEDITW %p\n", this); 01783 01784 pSFParent->GetAttributesOf(1, (LPCITEMIDLIST*)&pidl, &dwAttr); 01785 if (SFGAO_CANRENAME & dwAttr) 01786 { 01787 return FALSE; 01788 } 01789 return TRUE; 01790 } 01791 01792 case LVN_ENDLABELEDITW: 01793 { 01794 TRACE("-- LVN_ENDLABELEDITW %p\n", this); 01795 if (lpdi->item.pszText) 01796 { 01797 HRESULT hr; 01798 LVITEMW lvItem; 01799 01800 lvItem.iItem = lpdi->item.iItem; 01801 lvItem.iSubItem = 0; 01802 lvItem.mask = LVIF_PARAM; 01803 SendMessageW(hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem); 01804 01805 pidl = (LPITEMIDLIST)lpdi->item.lParam; 01806 hr = pSFParent->SetNameOf(0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidl); 01807 01808 if (SUCCEEDED(hr) && pidl) 01809 { 01810 lvItem.mask = LVIF_PARAM|LVIF_IMAGE; 01811 lvItem.lParam = (LPARAM)pidl; 01812 lvItem.iImage = SHMapPIDLToSystemImageListIndex(pSFParent, pidl, 0); 01813 SendMessageW(hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem); 01814 SendMessageW(hWndList, LVM_UPDATE, lpdi->item.iItem, 0); 01815 01816 return TRUE; 01817 } 01818 } 01819 01820 return FALSE; 01821 } 01822 01823 case LVN_KEYDOWN: 01824 { 01825 /* MSG msg; 01826 msg.hwnd = m_hWnd; 01827 msg.message = WM_KEYDOWN; 01828 msg.wParam = plvKeyDown->wVKey; 01829 msg.lParam = 0; 01830 msg.time = 0; 01831 msg.pt = 0;*/ 01832 01833 LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh; 01834 SHORT ctrl = GetKeyState(VK_CONTROL) & 0x8000; 01835 01836 /* initiate a rename of the selected file or directory */ 01837 if (plvKeyDown->wVKey == VK_F2) 01838 { 01839 /* see how many files are selected */ 01840 int i = ListView_GetSelectedCount(hWndList); 01841 01842 /* get selected item */ 01843 if (i == 1) 01844 { 01845 /* get selected item */ 01846 i = ListView_GetNextItem(hWndList, -1, LVNI_SELECTED); 01847 01848 SendMessageW(hWndList, LVM_ENSUREVISIBLE, i, 0); 01849 SendMessageW(hWndList, LVM_EDITLABELW, i, 0); 01850 } 01851 } 01852 #if 0 01853 TranslateAccelerator(m_hWnd, hAccel, &msg) 01854 #endif 01855 else if(plvKeyDown->wVKey == VK_DELETE) 01856 { 01857 UINT i; 01858 int item_index; 01859 LVITEMA item; 01860 LPITEMIDLIST* pItems; 01861 ISFHelper *psfhlp; 01862 01863 pSFParent->QueryInterface(IID_ISFHelper, 01864 (LPVOID*)&psfhlp); 01865 01866 if (psfhlp == NULL) 01867 break; 01868 01869 if (!(i = ListView_GetSelectedCount(hWndList))) 01870 break; 01871 01872 /* allocate memory for the pidl array */ 01873 pItems = (LPITEMIDLIST *)HeapAlloc(GetProcessHeap(), 0, 01874 sizeof(LPITEMIDLIST) * i); 01875 01876 /* retrieve all selected items */ 01877 i = 0; 01878 item_index = -1; 01879 while (ListView_GetSelectedCount(hWndList) > i) 01880 { 01881 /* get selected item */ 01882 item_index = ListView_GetNextItem(hWndList, 01883 item_index, LVNI_SELECTED); 01884 item.iItem = item_index; 01885 item.mask = LVIF_PARAM; 01886 SendMessageA(hWndList, LVM_GETITEMA, 0, (LPARAM) &item); 01887 01888 /* get item pidl */ 01889 pItems[i] = (LPITEMIDLIST)item.lParam; 01890 01891 i++; 01892 } 01893 01894 /* perform the item deletion */ 01895 psfhlp->DeleteItems(i, (LPCITEMIDLIST*)pItems); 01896 01897 /* free pidl array memory */ 01898 HeapFree(GetProcessHeap(), 0, pItems); 01899 } 01900 /* Initiate a refresh */ 01901 else if (plvKeyDown->wVKey == VK_F5) 01902 { 01903 Refresh(); 01904 } 01905 else if (plvKeyDown->wVKey == VK_BACK) 01906 { 01907 LPSHELLBROWSER lpSb; 01908 if ((lpSb = (LPSHELLBROWSER)SendMessageW(hWndParent, CWM_GETISHELLBROWSER, 0, 0))) 01909 { 01910 lpSb->BrowseObject(NULL, SBSP_PARENT); 01911 } 01912 } 01913 else if (plvKeyDown->wVKey == 'C' && ctrl) 01914 { 01915 if (GetSelections()) 01916 { 01917 CComPtr<IDataObject> pda; 01918 01919 if (SUCCEEDED(pSFParent->GetUIObjectOf(m_hWnd, cidl, (LPCITEMIDLIST*)apidl, IID_IDataObject, 0, (LPVOID *)&pda))) 01920 { 01921 HRESULT hr = OleSetClipboard(pda); 01922 if (FAILED(hr)) 01923 { 01924 WARN("OleSetClipboard failed"); 01925 } 01926 } 01927 } 01928 break; 01929 } 01930 else if(plvKeyDown->wVKey == 'V' && ctrl) 01931 { 01932 CComPtr<IDataObject> pda; 01933 STGMEDIUM medium; 01934 FORMATETC formatetc; 01935 LPITEMIDLIST * apidl; 01936 LPITEMIDLIST pidl; 01937 CComPtr<IShellFolder> psfFrom; 01938 CComPtr<IShellFolder> psfDesktop; 01939 CComPtr<IShellFolder> psfTarget; 01940 LPIDA lpcida; 01941 CComPtr<ISFHelper> psfhlpdst; 01942 CComPtr<ISFHelper> psfhlpsrc; 01943 HRESULT hr; 01944 01945 hr = OleGetClipboard(&pda); 01946 if (hr != S_OK) 01947 { 01948 ERR("Failed to get clipboard with %lx\n", hr); 01949 return E_FAIL; 01950 } 01951 01952 InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL); 01953 hr = pda->GetData(&formatetc, &medium); 01954 01955 if (FAILED(hr)) 01956 { 01957 ERR("Failed to get clipboard data with %lx\n", hr); 01958 return E_FAIL; 01959 } 01960 01961 /* lock the handle */ 01962 lpcida = (LPIDA)GlobalLock(medium.hGlobal); 01963 if (!lpcida) 01964 { 01965 ERR("failed to lock pidl\n"); 01966 ReleaseStgMedium(&medium); 01967 return E_FAIL; 01968 } 01969 01970 /* convert the data into pidl */ 01971 apidl = _ILCopyCidaToaPidl(&pidl, lpcida); 01972 01973 if (!apidl) 01974 { 01975 ERR("failed to copy pidl\n"); 01976 return E_FAIL; 01977 } 01978 01979 if (FAILED(SHGetDesktopFolder(&psfDesktop))) 01980 { 01981 ERR("failed to get desktop folder\n"); 01982 SHFree(pidl); 01983 _ILFreeaPidl(apidl, lpcida->cidl); 01984 ReleaseStgMedium(&medium); 01985 return E_FAIL; 01986 } 01987 01988 if (_ILIsDesktop(pidl)) 01989 { 01990 /* use desktop shellfolder */ 01991 psfFrom = psfDesktop; 01992 } 01993 else if (FAILED(psfDesktop->BindToObject(pidl, NULL, IID_IShellFolder, (LPVOID*)&psfFrom))) 01994 { 01995 ERR("no IShellFolder\n"); 01996 01997 SHFree(pidl); 01998 _ILFreeaPidl(apidl, lpcida->cidl); 01999 ReleaseStgMedium(&medium); 02000 02001 return E_FAIL; 02002 } 02003 02004 psfTarget = pSFParent; 02005 02006 02007 /* get source and destination shellfolder */ 02008 if (FAILED(psfTarget->QueryInterface(IID_ISFHelper, (LPVOID*)&psfhlpdst))) 02009 { 02010 ERR("no IID_ISFHelper for destination\n"); 02011 02012 SHFree(pidl); 02013 _ILFreeaPidl(apidl, lpcida->cidl); 02014 ReleaseStgMedium(&medium); 02015 02016 return E_FAIL; 02017 } 02018 02019 if (FAILED(psfFrom->QueryInterface(IID_ISFHelper, (LPVOID*)&psfhlpsrc))) 02020 { 02021 ERR("no IID_ISFHelper for source\n"); 02022 02023 SHFree(pidl); 02024 _ILFreeaPidl(apidl, lpcida->cidl); 02025 ReleaseStgMedium(&medium); 02026 return E_FAIL; 02027 } 02028 02029 /* FIXXME 02030 * do we want to perform a copy or move ??? 02031 */ 02032 hr = psfhlpdst->CopyItems(psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl); 02033 02034 SHFree(pidl); 02035 _ILFreeaPidl(apidl, lpcida->cidl); 02036 ReleaseStgMedium(&medium); 02037 02038 TRACE("paste end hr %x\n", hr); 02039 break; 02040 } 02041 else 02042 FIXME("LVN_KEYDOWN key=0x%08x\n", plvKeyDown->wVKey); 02043 } 02044 break; 02045 02046 default: 02047 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh->code); 02048 break; 02049 } 02050 02051 return 0; 02052 } 02053 02054 /********************************************************** 02055 * ShellView_OnChange() 02056 */ 02057 LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 02058 { 02059 LPITEMIDLIST *Pidls; 02060 02061 Pidls = (LPITEMIDLIST *)wParam; 02062 02063 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam); 02064 02065 switch (lParam) 02066 { 02067 case SHCNE_MKDIR: 02068 case SHCNE_CREATE: 02069 LV_AddItem(Pidls[0]); 02070 break; 02071 02072 case SHCNE_RMDIR: 02073 case SHCNE_DELETE: 02074 LV_DeleteItem(Pidls[0]); 02075 break; 02076 02077 case SHCNE_RENAMEFOLDER: 02078 case SHCNE_RENAMEITEM: 02079 LV_RenameItem(Pidls[0], Pidls[1]); 02080 break; 02081 02082 case SHCNE_UPDATEITEM: 02083 break; 02084 } 02085 02086 return TRUE; 02087 } 02088 02089 /********************************************************** 02090 * CDefView::OnCustomItem 02091 */ 02092 LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 02093 { 02094 if (!pCM.p) 02095 { 02096 /* no menu */ 02097 ERR("no menu!!!\n"); 02098 return FALSE; 02099 } 02100 02101 if (pCM.p->HandleMenuMsg(uMsg, (WPARAM)m_hWnd, lParam) == S_OK) 02102 return TRUE; 02103 else 02104 return FALSE; 02105 } 02106 02107 LRESULT CDefView::OnSettingChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) 02108 { 02109 /* Wallpaper setting affects drop shadows effect */ 02110 if (wParam == SPI_SETDESKWALLPAPER || wParam == 0) 02111 UpdateListColors(); 02112 02113 return S_OK; 02114 } 02115 02116 /********************************************************** 02117 * 02118 * 02119 * The INTERFACE of the IShellView object 02120 * 02121 * 02122 ********************************************************** 02123 */ 02124 02125 /********************************************************** 02126 * ShellView_GetWindow 02127 */ 02128 HRESULT WINAPI CDefView::GetWindow(HWND *phWnd) 02129 { 02130 TRACE("(%p)\n", this); 02131 02132 *phWnd = m_hWnd; 02133 02134 return S_OK; 02135 } 02136 02137 HRESULT WINAPI CDefView::ContextSensitiveHelp(BOOL fEnterMode) 02138 { 02139 FIXME("(%p) stub\n", this); 02140 02141 return E_NOTIMPL; 02142 } 02143 02144 /********************************************************** 02145 * IShellView_TranslateAccelerator 02146 * 02147 * FIXME: 02148 * use the accel functions 02149 */ 02150 HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg) 02151 { 02152 #if 0 02153 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n", this, lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam); 02154 #endif 02155 02156 if (lpmsg->message >= WM_KEYFIRST && lpmsg->message >= WM_KEYLAST) 02157 { 02158 TRACE("-- key=0x04%lx\n", lpmsg->wParam) ; 02159 } 02160 02161 return S_FALSE; /* not handled */ 02162 } 02163 02164 HRESULT WINAPI CDefView::EnableModeless(BOOL fEnable) 02165 { 02166 FIXME("(%p) stub\n", this); 02167 02168 return E_NOTIMPL; 02169 } 02170 02171 HRESULT WINAPI CDefView::UIActivate(UINT uState) 02172 { 02173 /* 02174 CHAR szName[MAX_PATH]; 02175 */ 02176 LRESULT lResult; 02177 int nPartArray[1] = { -1}; 02178 02179 TRACE("(%p)->(state=%x) stub\n", this, uState); 02180 02181 /*don't do anything if the state isn't really changing*/ 02182 if (this->uState == uState) 02183 { 02184 return S_OK; 02185 } 02186 02187 /*OnActivate handles the menu merging and internal state*/ 02188 DoActivate(uState); 02189 02190 /*only do This if we are active*/ 02191 if (uState != SVUIA_DEACTIVATE) 02192 { 02193 02194 /* 02195 GetFolderPath is not a method of IShellFolder 02196 IShellFolder_GetFolderPath( pSFParent, szName, sizeof(szName) ); 02197 */ 02198 /* set the number of parts */ 02199 pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult); 02200 02201 /* set the text for the parts */ 02202 /* 02203 pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult); 02204 */ 02205 } 02206 02207 return S_OK; 02208 } 02209 02210 HRESULT WINAPI CDefView::Refresh() 02211 { 02212 TRACE("(%p)\n", this); 02213 02214 SendMessageW(hWndList, LVM_DELETEALLITEMS, 0, 0); 02215 FillList(); 02216 02217 return S_OK; 02218 } 02219 02220 HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd) 02221 { 02222 *phWnd = 0; 02223 02224 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n", this, lpPrevView, lpfs, psb, prcView, phWnd); 02225 02226 if (lpfs != NULL) 02227 TRACE("-- vmode=%x flags=%x\n", lpfs->ViewMode, lpfs->fFlags); 02228 if (prcView != NULL) 02229 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom); 02230 02231 /* Validate the Shell Browser */ 02232 if (psb == NULL) 02233 return E_UNEXPECTED; 02234 02235 /*set up the member variables*/ 02236 pShellBrowser = psb; 02237 FolderSettings = *lpfs; 02238 02239 /*get our parent window*/ 02240 pShellBrowser->GetWindow(&hWndParent); 02241 02242 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */ 02243 pCommDlgBrowser = NULL; 02244 if (SUCCEEDED(pShellBrowser->QueryInterface(IID_ICommDlgBrowser, (LPVOID *)&pCommDlgBrowser))) 02245 { 02246 TRACE("-- CommDlgBrowser\n"); 02247 } 02248 02249 Create(hWndParent, prcView, NULL, WS_CHILD | WS_TABSTOP, 0, 0U); 02250 if (m_hWnd == NULL) 02251 return E_FAIL; 02252 02253 *phWnd = m_hWnd; 02254 02255 CheckToolbar(); 02256 02257 if (!*phWnd) 02258 return E_FAIL; 02259 02260 SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); 02261 UpdateWindow(); 02262 02263 return S_OK; 02264 } 02265 02266 HRESULT WINAPI CDefView::DestroyViewWindow() 02267 { 02268 TRACE("(%p)\n", this); 02269 02270 /*Make absolutely sure all our UI is cleaned up.*/ 02271 UIActivate(SVUIA_DEACTIVATE); 02272 02273 if (hMenu) 02274 { 02275 DestroyMenu(hMenu); 02276 } 02277 02278 DestroyWindow(); 02279 pShellBrowser.Release(); 02280 pCommDlgBrowser.Release(); 02281 02282 return S_OK; 02283 } 02284 02285 HRESULT WINAPI CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs) 02286 { 02287 TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs, 02288 FolderSettings.ViewMode, FolderSettings.fFlags); 02289 02290 if (!lpfs) 02291 return E_INVALIDARG; 02292 02293 *lpfs = FolderSettings; 02294 return NOERROR; 02295 } 02296 02297 HRESULT WINAPI CDefView::AddPropertySheetPages(DWORD dwReserved, LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam) 02298 { 02299 FIXME("(%p) stub\n", this); 02300 02301 return E_NOTIMPL; 02302 } 02303 02304 HRESULT WINAPI CDefView::SaveViewState() 02305 { 02306 FIXME("(%p) stub\n", this); 02307 02308 return S_OK; 02309 } 02310 02311 HRESULT WINAPI CDefView::SelectItem(LPCITEMIDLIST pidl, UINT uFlags) 02312 { 02313 int i; 02314 02315 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl, uFlags); 02316 02317 i = LV_FindItemByPidl(pidl); 02318 02319 if (i != -1) 02320 { 02321 LVITEMW lvItem; 02322 02323 if(uFlags & SVSI_ENSUREVISIBLE) 02324 SendMessageW(hWndList, LVM_ENSUREVISIBLE, i, 0); 02325 02326 lvItem.mask = LVIF_STATE; 02327 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED; 02328 lvItem.iItem = 0; 02329 lvItem.iSubItem = 0; 02330 02331 while (SendMessageW(hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem)) 02332 { 02333 if (lvItem.iItem == i) 02334 { 02335 if (uFlags & SVSI_SELECT) 02336 lvItem.state |= LVIS_SELECTED; 02337 else 02338 lvItem.state &= ~LVIS_SELECTED; 02339 02340 if (uFlags & SVSI_FOCUSED) 02341 lvItem.state &= ~LVIS_FOCUSED; 02342 } 02343 else 02344 { 02345 if (uFlags & SVSI_DESELECTOTHERS) 02346 lvItem.state &= ~LVIS_SELECTED; 02347 } 02348 02349 SendMessageW(hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem); 02350 lvItem.iItem++; 02351 } 02352 02353 02354 if(uFlags & SVSI_EDIT) 02355 SendMessageW(hWndList, LVM_EDITLABELW, i, 0); 02356 } 02357 02358 return S_OK; 02359 } 02360 02361 HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut) 02362 { 02363 HRESULT hr = E_NOINTERFACE; 02364 02365 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem, debugstr_guid(&riid), ppvOut); 02366 02367 *ppvOut = NULL; 02368 02369 switch (uItem) 02370 { 02371 case SVGIO_BACKGROUND: 02372 if (IsEqualIID(riid, IID_IContextMenu)) 02373 { 02374 //*ppvOut = ISvBgCm_Constructor(pSFParent, FALSE); 02375 CDefFolderMenu_Create2(NULL, NULL, cidl, (LPCITEMIDLIST*)apidl, pSFParent, NULL, 0, NULL, (IContextMenu**)ppvOut); 02376 if (!ppvOut) 02377 hr = E_OUTOFMEMORY; 02378 else 02379 hr = S_OK; 02380 } 02381 break; 02382 02383 case SVGIO_SELECTION: 02384 GetSelections(); 02385 hr = pSFParent->GetUIObjectOf(m_hWnd, cidl, (LPCITEMIDLIST*)apidl, riid, 0, ppvOut); 02386 break; 02387 } 02388 02389 TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut); 02390 02391 return hr; 02392 } 02393 02394 HRESULT STDMETHODCALLTYPE CDefView::GetCurrentViewMode(UINT *pViewMode) 02395 { 02396 TRACE("(%p)->(%p), stub\n", this, pViewMode); 02397 02398 if (!pViewMode) 02399 return E_INVALIDARG; 02400 02401 *pViewMode = this->FolderSettings.ViewMode; 02402 return S_OK; 02403 } 02404 02405 HRESULT STDMETHODCALLTYPE CDefView::SetCurrentViewMode(UINT ViewMode) 02406 { 02407 DWORD dwStyle; 02408 TRACE("(%p)->(%u), stub\n", this, ViewMode); 02409 02410 if ((ViewMode < FVM_FIRST || ViewMode > FVM_LAST) /* && (ViewMode != FVM_AUTO) */ ) 02411 return E_INVALIDARG; 02412 02413 /* Windows before Vista uses LVM_SETVIEW and possibly 02414 LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview, 02415 while later versions seem to accomplish this through other 02416 means. */ 02417 switch (ViewMode) 02418 { 02419 case FVM_ICON: 02420 dwStyle = LVS_ICON; 02421 break; 02422 case FVM_DETAILS: 02423 dwStyle = LVS_REPORT; 02424 break; 02425 case FVM_SMALLICON: 02426 dwStyle = LVS_SMALLICON; 02427 break; 02428 case FVM_LIST: 02429 dwStyle = LVS_LIST; 02430 break; 02431 default: 02432 { 02433 FIXME("ViewMode %d not implemented\n", ViewMode); 02434 dwStyle = LVS_LIST; 02435 break; 02436 } 02437 } 02438 02439 SetStyle(dwStyle, LVS_TYPEMASK); 02440 02441 /* This will not necessarily be the actual mode set above. 02442 This mimics the behavior of Windows XP. */ 02443 this->FolderSettings.ViewMode = ViewMode; 02444 02445 return S_OK; 02446 } 02447 02448 HRESULT STDMETHODCALLTYPE CDefView::GetFolder(REFIID riid, void **ppv) 02449 { 02450 if (pSFParent == NULL) 02451 return E_FAIL; 02452 02453 return pSFParent->QueryInterface(riid, ppv); 02454 } 02455 02456 HRESULT STDMETHODCALLTYPE CDefView::Item(int iItemIndex, LPITEMIDLIST *ppidl) 02457 { 02458 LVITEMW item; 02459 02460 TRACE("(%p)->(%d %p)\n", this, iItemIndex, ppidl); 02461 02462 item.mask = LVIF_PARAM; 02463 item.iItem = iItemIndex; 02464 02465 if (SendMessageW(this->hWndList, LVM_GETITEMW, 0, (LPARAM)&item)) 02466 { 02467 *ppidl = ILClone((PITEMID_CHILD)item.lParam); 02468 return S_OK; 02469 } 02470 02471 *ppidl = 0; 02472 02473 return E_INVALIDARG; 02474 } 02475 02476 HRESULT STDMETHODCALLTYPE CDefView::ItemCount(UINT uFlags, int *pcItems) 02477 { 02478 TRACE("(%p)->(%u %p)\n", this, uFlags, pcItems); 02479 02480 if (uFlags != SVGIO_ALLVIEW) 02481 FIXME("some flags unsupported, %x\n", uFlags & ~SVGIO_ALLVIEW); 02482 02483 *pcItems = SendMessageW(this->hWndList, LVM_GETITEMCOUNT, 0, 0); 02484 02485 return S_OK; 02486 } 02487 02488 HRESULT STDMETHODCALLTYPE CDefView::Items(UINT uFlags, REFIID riid, void **ppv) 02489 { 02490 return E_NOTIMPL; 02491 } 02492 02493 HRESULT STDMETHODCALLTYPE CDefView::GetSelectionMarkedItem(int *piItem) 02494 { 02495 TRACE("(%p)->(%p)\n", this, piItem); 02496 02497 *piItem = SendMessageW(this->hWndList, LVM_GETSELECTIONMARK, 0, 0); 02498 02499 return S_OK; 02500 } 02501 02502 HRESULT STDMETHODCALLTYPE CDefView::GetFocusedItem(int *piItem) 02503 { 02504 TRACE("(%p)->(%p)\n", this, piItem); 02505 02506 *piItem = SendMessageW(this->hWndList, LVM_GETNEXTITEM, -1, LVNI_FOCUSED); 02507 02508 return S_OK; 02509 } 02510 02511 HRESULT STDMETHODCALLTYPE CDefView::GetItemPosition(LPCITEMIDLIST pidl, POINT *ppt) 02512 { 02513 return E_NOTIMPL; 02514 } 02515 02516 HRESULT STDMETHODCALLTYPE CDefView::GetSpacing(POINT *ppt) 02517 { 02518 TRACE("(%p)->(%p)\n", this, ppt); 02519 02520 if (NULL == this->hWndList) return S_FALSE; 02521 02522 if (ppt) 02523 { 02524 const DWORD ret = SendMessageW(this->hWndList, LVM_GETITEMSPACING, 0, 0); 02525 02526 ppt->x = LOWORD(ret); 02527 ppt->y = HIWORD(ret); 02528 } 02529 02530 return S_OK; 02531 } 02532 02533 HRESULT STDMETHODCALLTYPE CDefView::GetDefaultSpacing(POINT *ppt) 02534 { 02535 return E_NOTIMPL; 02536 } 02537 02538 HRESULT STDMETHODCALLTYPE CDefView::GetAutoArrange() 02539 { 02540 return E_NOTIMPL; 02541 } 02542 02543 HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags) 02544 { 02545 LVITEMW lvItem; 02546 02547 TRACE("(%p)->(%d, %x)\n", this, iItem, dwFlags); 02548 02549 lvItem.state = 0; 02550 lvItem.stateMask = LVIS_SELECTED; 02551 02552 if (dwFlags & SVSI_ENSUREVISIBLE) 02553 SendMessageW(this->hWndList, LVM_ENSUREVISIBLE, iItem, 0); 02554 02555 /* all items */ 02556 if (dwFlags & SVSI_DESELECTOTHERS) 02557 SendMessageW(this->hWndList, LVM_SETITEMSTATE, -1, (LPARAM)&lvItem); 02558 02559 /* this item */ 02560 if (dwFlags & SVSI_SELECT) 02561 lvItem.state |= LVIS_SELECTED; 02562 02563 if (dwFlags & SVSI_FOCUSED) 02564 lvItem.stateMask |= LVIS_FOCUSED; 02565 02566 SendMessageW(this->hWndList, LVM_SETITEMSTATE, iItem, (LPARAM)&lvItem); 02567 02568 if (dwFlags & SVSI_EDIT) 02569 SendMessageW(this->hWndList, LVM_EDITLABELW, iItem, 0); 02570 02571 return S_OK; 02572 } 02573 02574 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, LPCITEMIDLIST *apidl, POINT *apt, DWORD dwFlags) 02575 { 02576 return E_NOTIMPL; 02577 } 02578 02579 /********************************************************** 02580 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget) 02581 */ 02582 HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText) 02583 { 02584 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n", 02585 this, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText); 02586 02587 if (!prgCmds) 02588 return E_INVALIDARG; 02589 02590 for (UINT i = 0; i < cCmds; i++) 02591 { 02592 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID); 02593 prgCmds[i].cmdf = 0; 02594 } 02595 02596 return OLECMDERR_E_UNKNOWNGROUP; 02597 } 02598 02599 /********************************************************** 02600 * ISVOleCmdTarget_Exec (IOleCommandTarget) 02601 * 02602 * nCmdID is the OLECMDID_* enumeration 02603 */ 02604 HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) 02605 { 02606 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n", 02607 this, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut); 02608 02609 if (!pguidCmdGroup) 02610 return OLECMDERR_E_UNKNOWNGROUP; 02611 02612 if (IsEqualIID(*pguidCmdGroup, CGID_Explorer) && 02613 (nCmdID == 0x29) && 02614 (nCmdexecopt == 4) && pvaOut) 02615 return S_OK; 02616 02617 if (IsEqualIID(*pguidCmdGroup, CGID_ShellDocView) && 02618 (nCmdID == 9) && 02619 (nCmdexecopt == 0)) 02620 return 1; 02621 02622 return OLECMDERR_E_UNKNOWNGROUP; 02623 } 02624 02625 /********************************************************** 02626 * ISVDropTarget implementation 02627 */ 02628 02629 /****************************************************************************** 02630 * drag_notify_subitem [Internal] 02631 * 02632 * Figure out the shellfolder object, which is currently under the mouse cursor 02633 * and notify it via the IDropTarget interface. 02634 */ 02635 02636 #define SCROLLAREAWIDTH 20 02637 02638 HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 02639 { 02640 LVHITTESTINFO htinfo; 02641 LVITEMW lvItem; 02642 LONG lResult; 02643 HRESULT hr; 02644 RECT clientRect; 02645 02646 /* Map from global to client coordinates and query the index of the listview-item, which is 02647 * currently under the mouse cursor. */ 02648 htinfo.pt.x = pt.x; 02649 htinfo.pt.y = pt.y; 02650 htinfo.flags = LVHT_ONITEM; 02651 ::ScreenToClient(hWndList, &htinfo.pt); 02652 lResult = SendMessageW(hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo); 02653 02654 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */ 02655 ::GetClientRect(hWndList, &clientRect); 02656 if (htinfo.pt.x == ptLastMousePos.x && htinfo.pt.y == ptLastMousePos.y && 02657 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH || 02658 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH )) 02659 { 02660 cScrollDelay = (cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */ 02661 if (cScrollDelay == 0) 02662 { 02663 /* Mouse did hover another 250 ms over the scroll-area */ 02664 if (htinfo.pt.x < SCROLLAREAWIDTH) 02665 SendMessageW(hWndList, WM_HSCROLL, SB_LINEUP, 0); 02666 02667 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH) 02668 SendMessageW(hWndList, WM_HSCROLL, SB_LINEDOWN, 0); 02669 02670 if (htinfo.pt.y < SCROLLAREAWIDTH) 02671 SendMessageW(hWndList, WM_VSCROLL, SB_LINEUP, 0); 02672 02673 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH) 02674 SendMessageW(hWndList, WM_VSCROLL, SB_LINEDOWN, 0); 02675 } 02676 } 02677 else 02678 { 02679 cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */ 02680 } 02681 02682 ptLastMousePos = htinfo.pt; 02683 02684 /* If we are still over the previous sub-item, notify it via DragOver and return. */ 02685 if (pCurDropTarget && lResult == iDragOverItem) 02686 return pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect); 02687 02688 /* We've left the previous sub-item, notify it via DragLeave and Release it. */ 02689 if (pCurDropTarget) 02690 { 02691 pCurDropTarget->DragLeave(); 02692 pCurDropTarget.Release(); 02693 } 02694 02695 iDragOverItem = lResult; 02696 if (lResult == -1) 02697 { 02698 /* We are not above one of the listview's subitems. Bind to the parent folder's 02699 * DropTarget interface. */ 02700 hr = pSFParent->QueryInterface(IID_IDropTarget, 02701 (LPVOID*)&pCurDropTarget); 02702 } 02703 else 02704 { 02705 /* Query the relative PIDL of the shellfolder object represented by the currently 02706 * dragged over listview-item ... */ 02707 lvItem.mask = LVIF_PARAM; 02708 lvItem.iItem = lResult; 02709 lvItem.iSubItem = 0; 02710 SendMessageW(hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem); 02711 02712 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */ 02713 hr = pSFParent->GetUIObjectOf(hWndList, 1, 02714 (LPCITEMIDLIST*)&lvItem.lParam, IID_IDropTarget, NULL, (LPVOID*)&pCurDropTarget); 02715 } 02716 02717 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */ 02718 if (FAILED(hr)) 02719 return hr; 02720 02721 /* Notify the item just entered via DragEnter. */ 02722 return pCurDropTarget->DragEnter(pCurDataObject, grfKeyState, pt, pdwEffect); 02723 } 02724 02725 HRESULT WINAPI CDefView::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 02726 { 02727 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */ 02728 pCurDataObject = pDataObject; 02729 pDataObject->AddRef(); 02730 02731 return drag_notify_subitem(grfKeyState, pt, pdwEffect); 02732 } 02733 02734 HRESULT WINAPI CDefView::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 02735 { 02736 return drag_notify_subitem(grfKeyState, pt, pdwEffect); 02737 } 02738 02739 HRESULT WINAPI CDefView::DragLeave() 02740 { 02741 if (pCurDropTarget) 02742 { 02743 pCurDropTarget->DragLeave(); 02744 pCurDropTarget.Release(); 02745 } 02746 02747 if (pCurDataObject != NULL) 02748 { 02749 pCurDataObject.Release(); 02750 } 02751 02752 iDragOverItem = 0; 02753 02754 return S_OK; 02755 } 02756 02757 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect) 02758 { 02759 if (pCurDropTarget) 02760 { 02761 pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect); 02762 pCurDropTarget.Release(); 02763 } 02764 02765 pCurDataObject.Release(); 02766 iDragOverItem = 0; 02767 02768 return S_OK; 02769 } 02770 02771 /********************************************************** 02772 * ISVDropSource implementation 02773 */ 02774 02775 HRESULT WINAPI CDefView::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) 02776 { 02777 TRACE("(%p)\n", this); 02778 02779 if (fEscapePressed) 02780 return DRAGDROP_S_CANCEL; 02781 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON)) 02782 return DRAGDROP_S_DROP; 02783 else 02784 return NOERROR; 02785 } 02786 02787 HRESULT WINAPI CDefView::GiveFeedback(DWORD dwEffect) 02788 { 02789 TRACE("(%p)\n", this); 02790 02791 return DRAGDROP_S_USEDEFAULTCURSORS; 02792 } 02793 02794 /********************************************************** 02795 * ISVViewObject implementation 02796 */ 02797 02798 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) 02799 { 02800 FIXME("Stub: this=%p\n", this); 02801 02802 return E_NOTIMPL; 02803 } 02804 02805 HRESULT WINAPI CDefView::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet) 02806 { 02807 FIXME("Stub: this=%p\n", this); 02808 02809 return E_NOTIMPL; 02810 } 02811 02812 HRESULT WINAPI CDefView::Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze) 02813 { 02814 FIXME("Stub: this=%p\n", this); 02815 02816 return E_NOTIMPL; 02817 } 02818 02819 HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze) 02820 { 02821 FIXME("Stub: this=%p\n", this); 02822 02823 return E_NOTIMPL; 02824 } 02825 02826 HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink) 02827 { 02828 FIXME("partial stub: %p %08x %08x %p\n", this, aspects, advf, pAdvSink); 02829 02830 /* FIXME: we set the AdviseSink, but never use it to send any advice */ 02831 pAdvSink = pAdvSink; 02832 dwAspects = aspects; 02833 dwAdvf = advf; 02834 02835 return S_OK; 02836 } 02837 02838 HRESULT WINAPI CDefView::GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink) 02839 { 02840 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects, pAdvf, ppAdvSink); 02841 02842 if (ppAdvSink) 02843 { 02844 *ppAdvSink = pAdvSink; 02845 pAdvSink.p->AddRef(); 02846 } 02847 02848 if (pAspects) 02849 *pAspects = dwAspects; 02850 02851 if (pAdvf) 02852 *pAdvf = dwAdvf; 02853 02854 return S_OK; 02855 } 02856 02857 HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) 02858 { 02859 if (IsEqualIID(guidService, SID_IShellBrowser)) 02860 return pShellBrowser->QueryInterface(riid, ppvObject); 02861 else if(IsEqualIID(guidService, SID_IFolderView)) 02862 return QueryInterface(riid, ppvObject); 02863 02864 return E_NOINTERFACE; 02865 } 02866 02867 /********************************************************** 02868 * IShellView_Constructor 02869 */ 02870 HRESULT WINAPI IShellView_Constructor(IShellFolder *pFolder, IShellView **newView) 02871 { 02872 CComObject<CDefView> *theView; 02873 CComPtr<IShellView> result; 02874 HRESULT hResult; 02875 02876 if (newView == NULL) 02877 return E_POINTER; 02878 02879 *newView = NULL; 02880 ATLTRY (theView = new CComObject<CDefView>); 02881 02882 if (theView == NULL) 02883 return E_OUTOFMEMORY; 02884 02885 hResult = theView->QueryInterface (IID_IShellView, (void **)&result); 02886 if (FAILED (hResult)) 02887 { 02888 delete theView; 02889 return hResult; 02890 } 02891 02892 hResult = theView->Initialize (pFolder); 02893 if (FAILED (hResult)) 02894 return hResult; 02895 *newView = result.Detach (); 02896 02897 return S_OK; 02898 } Generated on Sun May 27 2012 04:26:28 for ReactOS by
1.7.6.1
|