4 * Copyright 1998,1999 <juergen.schmied@debitel.net>
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.
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.
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.
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
23 * FIXME: The order by part of the background context menu should be
24 * built according to the columns shown.
26 * FIXME: Load/Save the view state from/into the stream provided by
29 * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
31 * FIXME: ShellView_FillList: consider sort orders
33 * FIXME: implement the drag and drop in the old (msg-based) way
35 * FIXME: when the ShellView_WndProc gets a WM_NCDESTROY should we do a
40 #include "wine/port.h"
47 #define NONAMELESSUNION
48 #define NONAMELESSSTRUCT
61 #include "undocshell.h"
63 #include "wine/debug.h"
67 #include "shell32_main.h"
68 #include "shellfolder.h"
70 WINE_DEFAULT_DEBUG_CHANNEL(shell);
72 static const WCHAR SV_CLASS_NAME[] = {'S','H','E','L','L','D','L','L','_','D','e','f','V','i','e','w',0};
78 }LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;
82 const IShellView2Vtbl* lpVtbl;
84 const IOleCommandTargetVtbl* lpvtblOleCommandTarget;
85 const IDropTargetVtbl* lpvtblDropTarget;
86 const IDropSourceVtbl* lpvtblDropSource;
87 const IViewObjectVtbl* lpvtblViewObject;
88 const IFolderViewVtbl* lpvtblFolderView;
89 IShellFolder* pSFParent;
90 IShellFolder2* pSF2Parent;
91 IShellBrowser* pShellBrowser;
92 ICommDlgBrowser* pCommDlgBrowser;
93 HWND hWnd; /* SHELLDLL_DefView */
94 HWND hWndList; /* ListView control */
96 FOLDERSETTINGS FolderSettings;
101 LISTVIEW_SORT_INFO ListViewSortInfo;
102 ULONG hNotify; /* change notification handle */
106 IAdviseSink *pAdvSink;
107 IDropTarget* pCurDropTarget; /* The sub-item, which is currently dragged over */
108 IDataObject* pCurDataObject; /* The dragged data-object */
109 LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */
110 UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
111 POINT ptLastMousePos; /* Mouse position at last DragOver call */
114 static const IShellView2Vtbl svvt;
115 static const IOleCommandTargetVtbl ctvt;
116 static const IDropTargetVtbl dtvt;
117 static const IDropSourceVtbl dsvt;
118 static const IViewObjectVtbl vovt;
119 static const IFolderViewVtbl fviewvt;
121 static inline IShellViewImpl *impl_from_IOleCommandTarget( IOleCommandTarget *iface )
123 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblOleCommandTarget));
126 static inline IShellViewImpl *impl_from_IDropTarget( IDropTarget *iface )
128 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropTarget));
131 static inline IShellViewImpl *impl_from_IDropSource( IDropSource *iface )
133 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropSource));
136 static inline IShellViewImpl *impl_from_IViewObject( IViewObject *iface )
138 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblViewObject));
141 static inline IShellViewImpl *impl_from_IFolderView( IFolderView *iface )
143 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblFolderView));
146 /* ListView Header ID's */
147 #define LISTVIEW_COLUMN_NAME 0
148 #define LISTVIEW_COLUMN_SIZE 1
149 #define LISTVIEW_COLUMN_TYPE 2
150 #define LISTVIEW_COLUMN_TIME 3
151 #define LISTVIEW_COLUMN_ATTRIB 4
154 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
155 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
156 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
158 #define ID_LISTVIEW 1
160 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
163 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
164 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
165 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
168 Items merged into the toolbar and the filemenu
177 } MYTOOLINFO, *LPMYTOOLINFO;
179 static const MYTOOLINFO Tools[] =
181 { FCIDM_SHVIEW_BIGICON, 0, 0, IDS_VIEW_LARGE, TBSTATE_ENABLED, BTNS_BUTTON },
182 { FCIDM_SHVIEW_SMALLICON, 0, 0, IDS_VIEW_SMALL, TBSTATE_ENABLED, BTNS_BUTTON },
183 { FCIDM_SHVIEW_LISTVIEW, 0, 0, IDS_VIEW_LIST, TBSTATE_ENABLED, BTNS_BUTTON },
184 { FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON },
188 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
190 /**********************************************************
191 * IShellView_Constructor
193 IShellView * IShellView_Constructor( IShellFolder * pFolder)
194 { IShellViewImpl * sv;
195 sv=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellViewImpl));
198 sv->lpvtblOleCommandTarget=&ctvt;
199 sv->lpvtblDropTarget=&dtvt;
200 sv->lpvtblDropSource=&dsvt;
201 sv->lpvtblViewObject=&vovt;
202 sv->lpvtblFolderView=&fviewvt;
204 sv->pSFParent = pFolder;
205 if(pFolder) IShellFolder_AddRef(pFolder);
206 IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent);
208 sv->pCurDropTarget = NULL;
209 sv->pCurDataObject = NULL;
210 sv->iDragOverItem = 0;
211 sv->cScrollDelay = 0;
212 sv->ptLastMousePos.x = 0;
213 sv->ptLastMousePos.y = 0;
215 TRACE("(%p)->(%p)\n",sv, pFolder);
216 return (IShellView *) sv;
219 /**********************************************************
221 * ##### helperfunctions for communication with ICommDlgBrowser #####
223 static BOOL IsInCommDlg(IShellViewImpl * This)
224 { return(This->pCommDlgBrowser != NULL);
227 static HRESULT IncludeObject(IShellViewImpl * This, LPCITEMIDLIST pidl)
231 if ( IsInCommDlg(This) )
233 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
234 ret = ICommDlgBrowser_IncludeObject(This->pCommDlgBrowser, (IShellView*)This, pidl);
235 TRACE("--0x%08x\n", ret);
240 static HRESULT OnDefaultCommand(IShellViewImpl * This)
242 HRESULT ret = S_FALSE;
244 if (IsInCommDlg(This))
246 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
247 ret = ICommDlgBrowser_OnDefaultCommand(This->pCommDlgBrowser, (IShellView*)This);
248 TRACE("-- returns %08x\n", ret);
253 static HRESULT OnStateChange(IShellViewImpl * This, UINT uFlags)
255 HRESULT ret = S_FALSE;
257 if (IsInCommDlg(This))
259 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
260 ret = ICommDlgBrowser_OnStateChange(This->pCommDlgBrowser, (IShellView*)This, uFlags);
265 /**********************************************************
266 * set the toolbar of the filedialog buttons
268 * - activates the buttons from the shellbrowser according to
271 static void CheckToolbar(IShellViewImpl * This)
277 if (IsInCommDlg(This))
279 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
280 FCIDM_TB_SMALLICON, (This->FolderSettings.ViewMode==FVM_LIST)? TRUE : FALSE, &result);
281 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
282 FCIDM_TB_REPORTVIEW, (This->FolderSettings.ViewMode==FVM_DETAILS)? TRUE : FALSE, &result);
283 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
284 FCIDM_TB_SMALLICON, TRUE, &result);
285 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
286 FCIDM_TB_REPORTVIEW, TRUE, &result);
290 /**********************************************************
292 * ##### helperfunctions for initializing the view #####
294 /**********************************************************
295 * change the style of the listview control
297 static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove)
301 TRACE("(%p)\n", This);
303 tmpstyle = GetWindowLongW(This->hWndList, GWL_STYLE);
304 SetWindowLongW(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
307 /**********************************************************
308 * ShellView_CreateList()
310 * - creates the list view window
312 static BOOL ShellView_CreateList (IShellViewImpl * This)
313 { DWORD dwStyle, dwExStyle;
317 dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
318 LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT | LVS_AUTOARRANGE;
319 dwExStyle = WS_EX_CLIENTEDGE;
321 switch (This->FolderSettings.ViewMode)
323 case FVM_ICON: dwStyle |= LVS_ICON; break;
324 case FVM_DETAILS: dwStyle |= LVS_REPORT; break;
325 case FVM_SMALLICON: dwStyle |= LVS_SMALLICON; break;
326 case FVM_LIST: dwStyle |= LVS_LIST; break;
329 FIXME("ViewMode %d not implemented\n", This->FolderSettings.ViewMode);
335 if (This->FolderSettings.fFlags & FWF_AUTOARRANGE) dwStyle |= LVS_AUTOARRANGE;
336 if (This->FolderSettings.fFlags & FWF_DESKTOP)
337 This->FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
338 if (This->FolderSettings.fFlags & FWF_SINGLESEL) dwStyle |= LVS_SINGLESEL;
339 if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE)
340 dwExStyle &= ~WS_EX_CLIENTEDGE;
342 This->hWndList=CreateWindowExW( dwExStyle,
355 This->ListViewSortInfo.bIsAscending = TRUE;
356 This->ListViewSortInfo.nHeaderID = -1;
357 This->ListViewSortInfo.nLastHeaderID = -1;
359 if (This->FolderSettings.fFlags & FWF_DESKTOP) {
361 * FIXME: look at the registry value
362 * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
363 * and activate drop shadows if necessary
366 SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, CLR_NONE);
368 SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, GetSysColor(COLOR_DESKTOP));
370 SendMessageW(This->hWndList, LVM_SETTEXTCOLOR, 0, RGB(255,255,255));
373 /* UpdateShellSettings(); */
377 /**********************************************************
378 * ShellView_InitList()
380 * - adds all needed columns to the shellview
382 static BOOL ShellView_InitList(IShellViewImpl * This)
391 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
393 lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
394 lvColumn.pszText = szTemp;
396 if (This->pSF2Parent)
400 if (FAILED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd)))
402 lvColumn.fmt = sd.fmt;
403 lvColumn.cx = sd.cxChar*8; /* chars->pixel */
404 StrRetToStrNW( szTemp, 50, &sd.str, NULL);
405 SendMessageW(This->hWndList, LVM_INSERTCOLUMNW, i, (LPARAM) &lvColumn);
413 SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ShellSmallIconList);
414 SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)ShellBigIconList);
418 /**********************************************************
419 * ShellView_CompareItems()
422 * internal, CALLBACK for DSA_Sort
424 static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
427 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
429 if(!lpData) return 0;
431 ret = (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2));
432 TRACE("ret=%i\n",ret);
436 /*************************************************************************
437 * ShellView_ListViewCompareItems
439 * Compare Function for the Listview (FileOpen Dialog)
442 * lParam1 [I] the first ItemIdList to compare with
443 * lParam2 [I] the second ItemIdList to compare with
444 * lpData [I] The column ID for the header Ctrl to process
447 * A negative value if the first item should precede the second,
448 * a positive value if the first item should follow the second,
449 * or zero if the two items are equivalent
452 * FIXME: function does what ShellView_CompareItems is supposed to do.
453 * unify it and figure out how to use the undocumented first parameter
454 * of IShellFolder_CompareIDs to do the job this function does and
455 * move this code to IShellFolder.
456 * make LISTVIEW_SORT_INFO obsolete
457 * the way this function works is only usable if we had only
458 * filesystemfolders (25/10/99 jsch)
460 static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
464 char strName1[MAX_PATH], strName2[MAX_PATH];
465 BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
466 LPITEMIDLIST pItemIdList1 = lParam1;
467 LPITEMIDLIST pItemIdList2 = lParam2;
468 LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData;
471 bIsFolder1 = _ILIsFolder(pItemIdList1);
472 bIsFolder2 = _ILIsFolder(pItemIdList2);
473 bIsBothFolder = bIsFolder1 && bIsFolder2;
475 /* When sorting between a File and a Folder, the Folder gets sorted first */
476 if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
478 nDiff = bIsFolder1 ? -1 : 1;
482 /* Sort by Time: Folders or Files can be sorted */
484 if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
486 _ILGetFileDateTime(pItemIdList1, &fd1);
487 _ILGetFileDateTime(pItemIdList2, &fd2);
488 nDiff = CompareFileTime(&fd2, &fd1);
490 /* Sort by Attribute: Folder or Files can be sorted */
491 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
493 _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH);
494 _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH);
495 nDiff = lstrcmpiA(strName1, strName2);
497 /* Sort by FileName: Folder or Files can be sorted */
498 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
501 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
502 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
503 nDiff = lstrcmpiA(strName1, strName2);
505 /* Sort by File Size, Only valid for Files */
506 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
508 nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0));
510 /* Sort by File Type, Only valid for Files */
511 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
514 _ILGetFileType(pItemIdList1, strName1, MAX_PATH);
515 _ILGetFileType(pItemIdList2, strName2, MAX_PATH);
516 nDiff = lstrcmpiA(strName1, strName2);
519 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
523 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
524 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
525 nDiff = lstrcmpiA(strName1, strName2);
528 if(!pSortInfo->bIsAscending)
537 /**********************************************************
538 * LV_FindItemByPidl()
540 static int LV_FindItemByPidl(
541 IShellViewImpl * This,
546 lvItem.mask = LVIF_PARAM;
547 for(lvItem.iItem = 0;
548 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
551 LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam;
552 HRESULT hr = IShellFolder_CompareIDs(This->pSFParent, 0, pidl, currentpidl);
553 if(SUCCEEDED(hr) && !HRESULT_CODE(hr))
561 /**********************************************************
564 static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
568 TRACE("(%p)(pidl=%p)\n", This, pidl);
570 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/
571 lvItem.iItem = SendMessageW(This->hWndList, LVM_GETITEMCOUNT, 0, 0); /*add the item to the end of the list*/
573 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/
574 lvItem.pszText = LPSTR_TEXTCALLBACKW; /*get text on a callback basis*/
575 lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/
576 return (-1==ListView_InsertItemW(This->hWndList, &lvItem))? FALSE: TRUE;
579 /**********************************************************
582 static BOOLEAN LV_DeleteItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
586 TRACE("(%p)(pidl=%p)\n", This, pidl);
588 nIndex = LV_FindItemByPidl(This, ILFindLastID(pidl));
589 return (-1==SendMessageW(This->hWndList, LVM_DELETEITEM, nIndex, 0))? FALSE: TRUE;
592 /**********************************************************
595 static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew )
600 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew);
602 nItem = LV_FindItemByPidl(This, ILFindLastID(pidlOld));
605 lvItem.mask = LVIF_PARAM; /* only the pidl */
606 lvItem.iItem = nItem;
607 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
609 SHFree((LPITEMIDLIST)lvItem.lParam);
610 lvItem.mask = LVIF_PARAM;
611 lvItem.iItem = nItem;
612 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */
613 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
614 SendMessageW(This->hWndList, LVM_UPDATE, nItem, 0);
615 return TRUE; /* FIXME: better handling */
619 /**********************************************************
620 * ShellView_FillList()
622 * - gets the objectlist from the shellfolder
624 * - fills the list into the view
627 static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg )
629 LPITEMIDLIST pidl = ptr;
630 IShellViewImpl *This = arg;
631 /* in a commdlg This works as a filemask*/
632 if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl);
637 static HRESULT ShellView_FillList(IShellViewImpl *This)
639 LPENUMIDLIST pEnumIDList;
645 TRACE("(%p)\n", This);
647 /* get the itemlist from the shfolder*/
648 hr = IShellFolder_EnumObjects(This->pSFParent, This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
649 if (hr != S_OK) return hr;
651 /* create a pointer array */
652 hdpa = DPA_Create(16);
655 IEnumIDList_Release(pEnumIDList);
656 return E_OUTOFMEMORY;
659 /* copy the items into the array*/
660 while((S_OK == IEnumIDList_Next(pEnumIDList, 1, &pidl, &fetched)) && fetched)
662 if (DPA_InsertPtr(hdpa, DPA_GetPtrCount(hdpa), pidl) == -1)
669 DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent);
671 SendMessageW(This->hWndList, WM_SETREDRAW, FALSE, 0);
672 DPA_DestroyCallback(hdpa, fill_list, This);
673 SendMessageW(This->hWndList, WM_SETREDRAW, TRUE, 0);
675 IEnumIDList_Release(pEnumIDList);
680 /**********************************************************
681 * ShellView_OnCreate()
683 static LRESULT ShellView_OnCreate(IShellViewImpl *This)
685 IShellView2 *iface = (IShellView2*)This;
686 static const WCHAR accel_nameW[] = {'s','h','v','_','a','c','c','e','l',0};
687 IPersistFolder2 *ppf2;
691 TRACE("(%p)\n", This);
693 if (ShellView_CreateList(This))
695 if (ShellView_InitList(This))
697 ShellView_FillList(This);
701 hr = IShellView2_QueryInterface(iface, &IID_IDropTarget, (LPVOID*)&pdt);
704 RegisterDragDrop(This->hWnd, pdt);
705 IDropTarget_Release(pdt);
708 /* register for receiving notifications */
709 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
712 SHChangeNotifyEntry ntreg;
714 hr = IPersistFolder2_GetCurFolder(ppf2, (LPITEMIDLIST*)&ntreg.pidl);
717 ntreg.fRecursive = TRUE;
718 This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS,
719 SHV_CHANGE_NOTIFY, 1, &ntreg);
720 SHFree((LPITEMIDLIST)ntreg.pidl);
722 IPersistFolder2_Release(ppf2);
725 This->hAccel = LoadAcceleratorsW(shell32_hInstance, accel_nameW);
730 /**********************************************************
731 * #### Handling of the menus ####
734 /**********************************************************
735 * ShellView_BuildFileMenu()
737 static HMENU ShellView_BuildFileMenu(IShellViewImpl * This)
738 { WCHAR szText[MAX_PATH];
743 TRACE("(%p)\n",This);
745 hSubMenu = CreatePopupMenu();
747 { /*get the number of items in our global array*/
748 for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
750 /*add the menu items*/
751 for(i = 0; i < nTools; i++)
753 LoadStringW(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
755 ZeroMemory(&mii, sizeof(mii));
756 mii.cbSize = sizeof(mii);
757 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
759 if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
761 mii.fType = MFT_STRING;
762 mii.fState = MFS_ENABLED;
763 mii.dwTypeData = szText;
764 mii.wID = Tools[i].idCommand;
768 mii.fType = MFT_SEPARATOR;
770 /* tack This item onto the end of the menu */
771 InsertMenuItemW(hSubMenu, (UINT)-1, TRUE, &mii);
774 TRACE("-- return (menu=%p)\n",hSubMenu);
777 /**********************************************************
778 * ShellView_MergeFileMenu()
780 static void ShellView_MergeFileMenu(IShellViewImpl *This, HMENU hSubMenu)
782 TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu);
786 static const WCHAR dummyW[] = {'d','u','m','m','y','4','5',0};
789 /* insert This item at the beginning of the menu */
791 mii.cbSize = sizeof(mii);
792 mii.fMask = MIIM_ID | MIIM_TYPE;
794 mii.fType = MFT_SEPARATOR;
795 InsertMenuItemW(hSubMenu, 0, TRUE, &mii);
797 mii.cbSize = sizeof(mii);
798 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
799 mii.dwTypeData = (LPWSTR)dummyW;
800 mii.fState = MFS_ENABLED;
801 mii.wID = IDM_MYFILEITEM;
802 mii.fType = MFT_STRING;
803 InsertMenuItemW(hSubMenu, 0, TRUE, &mii);
809 /**********************************************************
810 * ShellView_MergeViewMenu()
813 static void ShellView_MergeViewMenu(IShellViewImpl *This, HMENU hSubMenu)
815 TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
817 /* add a separator at the correct position in the menu */
820 static const WCHAR menuW[] = {'M','E','N','U','_','0','0','1',0};
821 static const WCHAR viewW[] = {'V','i','e','w',0};
824 memset(&mii, 0, sizeof(mii));
825 mii.cbSize = sizeof(mii);
826 mii.fMask = MIIM_ID | MIIM_TYPE;
828 mii.fType = MFT_SEPARATOR;
829 InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
831 mii.cbSize = sizeof(mii);
832 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
833 mii.fType = MFT_STRING;
834 mii.dwTypeData = (LPWSTR)viewW;
835 mii.hSubMenu = LoadMenuW(shell32_hInstance, menuW);
836 InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
840 /**********************************************************
841 * ShellView_GetSelections()
843 * - fills the this->apidl list with the selected objects
846 * number of selected items
848 static UINT ShellView_GetSelections(IShellViewImpl * This)
855 This->cidl = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0);
856 This->apidl = SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
858 TRACE("selected=%i\n", This->cidl);
862 TRACE("-- Items selected =%u\n", This->cidl);
864 lvItem.mask = LVIF_STATE | LVIF_PARAM;
865 lvItem.stateMask = LVIS_SELECTED;
869 while(ListView_GetItemW(This->hWndList, &lvItem) && (i < This->cidl))
871 if(lvItem.state & LVIS_SELECTED)
873 This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
875 TRACE("-- selected Item found\n");
884 /**********************************************************
885 * ShellView_OpenSelectedItems()
887 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
889 static UINT CF_IDLIST = 0;
891 IDataObject* selection;
895 LPCITEMIDLIST parent_pidl;
896 WCHAR parent_path[MAX_PATH];
897 LPCWSTR parent_dir = NULL;
901 if (0 == ShellView_GetSelections(This))
905 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
906 (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
907 0, (LPVOID *)&selection);
913 CF_IDLIST = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
915 fetc.cfFormat = CF_IDLIST;
917 fetc.dwAspect = DVASPECT_CONTENT;
919 fetc.tymed = TYMED_HGLOBAL;
921 hr = IDataObject_QueryGetData(selection, &fetc);
925 hr = IDataObject_GetData(selection, &fetc, &stgm);
929 pIDList = GlobalLock(stgm.u.hGlobal);
931 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
932 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &parent_pidl, &attribs);
933 if (SUCCEEDED(hr) && (attribs & SFGAO_FILESYSTEM) &&
934 SHGetPathFromIDListW(parent_pidl, parent_path))
936 parent_dir = parent_path;
939 for (i = pIDList->cidl; i > 0; --i)
943 pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
945 attribs = SFGAO_FOLDER;
946 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
948 if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
950 SHELLEXECUTEINFOW shexinfo;
952 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
953 shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */
954 shexinfo.hwnd = NULL;
955 shexinfo.lpVerb = NULL;
956 shexinfo.lpFile = NULL;
957 shexinfo.lpParameters = NULL;
958 shexinfo.lpDirectory = parent_dir;
959 shexinfo.nShow = SW_NORMAL;
960 shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
962 ShellExecuteExW(&shexinfo); /* Discard error/success info */
964 ILFree(shexinfo.lpIDList);
968 GlobalUnlock(stgm.u.hGlobal);
969 ReleaseStgMedium(&stgm);
971 IDataObject_Release(selection);
976 /**********************************************************
977 * ShellView_DoContextMenu()
979 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
983 BOOL fExplore = FALSE;
985 LPCONTEXTMENU pContextMenu = NULL;
986 IContextMenu2 *pCM = NULL;
987 CMINVOKECOMMANDINFO cmi;
989 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
991 /* look, what's selected and create a context menu object of it*/
992 if( ShellView_GetSelections(This) )
994 IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
995 &IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
999 TRACE("-- pContextMenu\n");
1000 hMenu = CreatePopupMenu();
1004 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
1005 if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
1007 TRACE("-- explore mode\n");
1011 /* build the flags depending on what we can do with the selected item */
1012 wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
1014 /* let the ContextMenu merge its items in */
1015 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
1017 if (This->FolderSettings.fFlags & FWF_DESKTOP)
1018 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
1022 TRACE("-- get menu default command\n");
1023 uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
1027 TRACE("-- track popup\n");
1028 uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1033 TRACE("-- uCommand=%u\n", uCommand);
1034 if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
1036 TRACE("-- dlg: OnDefaultCommand\n");
1037 if (OnDefaultCommand(This) != S_OK)
1039 ShellView_OpenSelectedItems(This);
1044 TRACE("-- explore -- invoke command\n");
1045 ZeroMemory(&cmi, sizeof(cmi));
1046 cmi.cbSize = sizeof(cmi);
1047 cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
1048 cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1049 IContextMenu_InvokeCommand(pContextMenu, &cmi);
1056 IContextMenu_Release(pContextMenu);
1059 else /* background context menu */
1061 hMenu = CreatePopupMenu();
1063 pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
1064 IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1066 uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1069 TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1071 ZeroMemory(&cmi, sizeof(cmi));
1072 cmi.cbSize = sizeof(cmi);
1073 cmi.lpVerb = MAKEINTRESOURCEA(uCommand);
1074 cmi.hwnd = This->hWndParent;
1075 IContextMenu2_InvokeCommand(pCM, &cmi);
1077 IContextMenu2_Release(pCM);
1081 /**********************************************************
1082 * ##### message handling #####
1085 /**********************************************************
1086 * ShellView_OnSize()
1088 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1090 TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1092 /*resize the ListView to fit our window*/
1095 MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1100 /**********************************************************
1101 * ShellView_OnDeactivate()
1106 static void ShellView_OnDeactivate(IShellViewImpl * This)
1110 if(This->uState != SVUIA_DEACTIVATE)
1114 IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1115 IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1116 DestroyMenu(This->hMenu);
1120 This->uState = SVUIA_DEACTIVATE;
1124 /**********************************************************
1125 * ShellView_OnActivate()
1127 static LRESULT ShellView_OnActivate(IShellViewImpl *This, UINT uState)
1129 OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} };
1132 TRACE("(%p) uState=%x\n",This,uState);
1134 /* don't do anything if the state isn't really changing */
1135 if (This->uState == uState) return S_OK;
1137 ShellView_OnDeactivate(This);
1139 /* only do This if we are active */
1140 if (uState != SVUIA_DEACTIVATE)
1142 /* merge the menus */
1143 This->hMenu = CreateMenu();
1147 static const WCHAR dummyW[] = {'d','u','m','m','y',' ','3','1',0};
1149 IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1150 TRACE("-- after fnInsertMenusSB\n");
1152 mii.cbSize = sizeof(mii);
1153 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1154 mii.fType = MFT_STRING;
1155 mii.fState = MFS_ENABLED;
1157 mii.hSubMenu = ShellView_BuildFileMenu(This);
1158 mii.hbmpChecked = NULL;
1159 mii.hbmpUnchecked = NULL;
1161 /* build the top level menu get the menu item's text */
1162 mii.dwTypeData = (LPWSTR)dummyW;
1164 mii.hbmpItem = NULL;
1166 /* insert our menu into the menu bar */
1168 InsertMenuItemW(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1170 /* get the view menu so we can merge with it */
1171 memset(&mii, 0, sizeof(mii));
1172 mii.cbSize = sizeof(mii);
1173 mii.fMask = MIIM_SUBMENU;
1175 if (GetMenuItemInfoW(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1176 ShellView_MergeViewMenu(This, mii.hSubMenu);
1178 /* add the items that should only be added if we have the focus */
1179 if (SVUIA_ACTIVATE_FOCUS == uState)
1181 /* get the file menu so we can merge with it */
1182 memset(&mii, 0, sizeof(mii));
1183 mii.cbSize = sizeof(mii);
1184 mii.fMask = MIIM_SUBMENU;
1186 if (GetMenuItemInfoW(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1187 ShellView_MergeFileMenu(This, mii.hSubMenu);
1190 TRACE("-- before fnSetMenuSB\n");
1191 IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1194 This->uState = uState;
1199 /**********************************************************
1200 * ShellView_OnSetFocus()
1203 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1207 /* Tell the browser one of our windows has received the focus. This
1208 should always be done before merging menus (OnActivate merges the
1209 menus) if one of our windows has the focus.*/
1211 IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1212 ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1214 /* Set the focus to the listview */
1215 SetFocus(This->hWndList);
1217 /* Notify the ICommDlgBrowser interface */
1218 OnStateChange(This,CDBOSC_SETFOCUS);
1223 /**********************************************************
1224 * ShellView_OnKillFocus()
1226 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1228 TRACE("(%p) stub\n",This);
1230 ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1231 /* Notify the ICommDlgBrowser */
1232 OnStateChange(This,CDBOSC_KILLFOCUS);
1237 /**********************************************************
1238 * ShellView_OnCommand()
1241 * the CmdID's are the ones from the context menu
1243 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1245 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1249 case FCIDM_SHVIEW_SMALLICON:
1250 This->FolderSettings.ViewMode = FVM_SMALLICON;
1251 SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1255 case FCIDM_SHVIEW_BIGICON:
1256 This->FolderSettings.ViewMode = FVM_ICON;
1257 SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1261 case FCIDM_SHVIEW_LISTVIEW:
1262 This->FolderSettings.ViewMode = FVM_LIST;
1263 SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1267 case FCIDM_SHVIEW_REPORTVIEW:
1268 This->FolderSettings.ViewMode = FVM_DETAILS;
1269 SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1273 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1278 This->ListViewSortInfo.nHeaderID = dwCmdID - 0x30;
1279 This->ListViewSortInfo.bIsAscending = TRUE;
1280 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1281 SendMessageW(This->hWndList, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1285 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID);
1290 /**********************************************************
1291 * ShellView_OnNotify()
1294 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1295 { LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1296 NMLVDISPINFOW *lpdi = (NMLVDISPINFOW *)lpnmh;
1299 TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1304 TRACE("-- NM_SETFOCUS %p\n",This);
1305 ShellView_OnSetFocus(This);
1309 TRACE("-- NM_KILLFOCUS %p\n",This);
1310 ShellView_OnDeactivate(This);
1311 /* Notify the ICommDlgBrowser interface */
1312 OnStateChange(This,CDBOSC_KILLFOCUS);
1316 TRACE("-- NM_CUSTOMDRAW %p\n",This);
1317 return CDRF_DODEFAULT;
1319 case NM_RELEASEDCAPTURE:
1320 TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1324 TRACE("-- NM_CLICK %p\n",This);
1328 TRACE("-- NM_RCLICK %p\n",This);
1332 TRACE("-- NM_DBLCLK %p\n",This);
1333 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1337 TRACE("-- NM_RETURN %p\n",This);
1338 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1342 TRACE("-- HDN_ENDTRACKW %p\n",This);
1343 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1344 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1347 case LVN_DELETEITEM:
1348 TRACE("-- LVN_DELETEITEM %p\n",This);
1349 SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/
1352 case LVN_DELETEALLITEMS:
1353 TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1356 case LVN_INSERTITEM:
1357 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1360 case LVN_ITEMACTIVATE:
1361 TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1362 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1365 case LVN_COLUMNCLICK:
1366 This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1367 if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1369 This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1373 This->ListViewSortInfo.bIsAscending = TRUE;
1375 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1377 SendMessageW(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1380 case LVN_GETDISPINFOA:
1381 case LVN_GETDISPINFOW:
1382 TRACE("-- LVN_GETDISPINFO %p\n",This);
1383 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1385 if(lpdi->item.mask & LVIF_TEXT) /* text requested */
1387 if (This->pSF2Parent)
1390 IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1391 if (lpnmh->code == LVN_GETDISPINFOA)
1393 /* shouldn't happen */
1394 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1395 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1396 TRACE("-- text=%s\n",lpdiA->item.pszText);
1398 else /* LVN_GETDISPINFOW */
1400 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1401 TRACE("-- text=%s\n",debugstr_w(lpdi->item.pszText));
1409 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1411 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1415 case LVN_ITEMCHANGED:
1416 TRACE("-- LVN_ITEMCHANGED %p\n",This);
1417 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1421 case LVN_BEGINRDRAG:
1422 TRACE("-- LVN_BEGINDRAG\n");
1424 if (ShellView_GetSelections(This))
1427 DWORD dwAttributes = SFGAO_CANLINK;
1428 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1430 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1432 IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource); /* own DropSource interface */
1434 if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1436 if (dwAttributes & SFGAO_CANLINK)
1438 dwEffect |= DROPEFFECT_LINK;
1445 DoDragDrop(pda, pds, dwEffect, &dwEffect2);
1447 IDataObject_Release(pda);
1452 case LVN_BEGINLABELEDITW:
1454 DWORD dwAttr = SFGAO_CANRENAME;
1455 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1457 TRACE("-- LVN_BEGINLABELEDITW %p\n",This);
1459 IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1460 if (SFGAO_CANRENAME & dwAttr)
1467 case LVN_ENDLABELEDITW:
1469 TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1470 if (lpdi->item.pszText)
1475 lvItem.iItem = lpdi->item.iItem;
1476 lvItem.iSubItem = 0;
1477 lvItem.mask = LVIF_PARAM;
1478 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
1480 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1481 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidl);
1483 if(SUCCEEDED(hr) && pidl)
1485 lvItem.mask = LVIF_PARAM;
1486 lvItem.lParam = (LPARAM)pidl;
1487 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
1497 msg.hwnd = This->hWnd;
1498 msg.message = WM_KEYDOWN;
1499 msg.wParam = plvKeyDown->wVKey;
1504 LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1506 /* initiate a rename of the selected file or directory */
1507 if(plvKeyDown->wVKey == VK_F2)
1509 /* see how many files are selected */
1510 int i = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0);
1512 /* get selected item */
1515 /* get selected item */
1516 i = SendMessageW(This->hWndList, LVM_GETNEXTITEM, -1, MAKELPARAM (LVNI_SELECTED, 0));
1518 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1519 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
1523 TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1525 else if(plvKeyDown->wVKey == VK_DELETE)
1530 LPITEMIDLIST* pItems;
1533 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1539 if(!(i = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0)))
1542 /* allocate memory for the pidl array */
1543 pItems = HeapAlloc(GetProcessHeap(), 0,
1544 sizeof(LPITEMIDLIST) * i);
1546 /* retrieve all selected items */
1549 while(SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0) > i)
1551 /* get selected item */
1552 item_index = SendMessageW(This->hWndList, LVM_GETNEXTITEM, item_index,
1553 MAKELPARAM (LVNI_SELECTED, 0));
1554 item.iItem = item_index;
1555 item.mask = LVIF_PARAM;
1556 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &item);
1559 pItems[i] = (LPITEMIDLIST)item.lParam;
1564 /* perform the item deletion */
1565 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1567 /* free pidl array memory */
1568 HeapFree(GetProcessHeap(), 0, pItems);
1571 /* Initiate a refresh */
1572 else if(plvKeyDown->wVKey == VK_F5)
1574 IShellView_Refresh((IShellView*)This);
1577 else if(plvKeyDown->wVKey == VK_BACK)
1579 LPSHELLBROWSER lpSb;
1580 if((lpSb = (LPSHELLBROWSER)SendMessageW(This->hWndParent, CWM_GETISHELLBROWSER, 0, 0)))
1582 IShellBrowser_BrowseObject(lpSb, NULL, SBSP_PARENT);
1587 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1592 TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1598 /**********************************************************
1599 * ShellView_OnChange()
1602 static LRESULT ShellView_OnChange(IShellViewImpl * This, const LPCITEMIDLIST * Pidls, LONG wEventId)
1605 TRACE("(%p)(%p,%p,0x%08x)\n", This, Pidls[0], Pidls[1], wEventId);
1610 LV_AddItem(This, Pidls[0]);
1614 LV_DeleteItem(This, Pidls[0]);
1616 case SHCNE_RENAMEFOLDER:
1617 case SHCNE_RENAMEITEM:
1618 LV_RenameItem(This, Pidls[0], Pidls[1]);
1620 case SHCNE_UPDATEITEM:
1625 /**********************************************************
1629 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1631 IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1632 LPCREATESTRUCTW lpcs;
1634 TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1639 lpcs = (LPCREATESTRUCTW)lParam;
1640 pThis = lpcs->lpCreateParams;
1641 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1642 pThis->hWnd = hWnd; /*set the window handle*/
1645 case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1646 case WM_SETFOCUS: return ShellView_OnSetFocus(pThis);
1647 case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis);
1648 case WM_CREATE: return ShellView_OnCreate(pThis);
1649 case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1650 case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1651 case WM_COMMAND: return ShellView_OnCommand(pThis,
1652 GET_WM_COMMAND_ID(wParam, lParam),
1653 GET_WM_COMMAND_CMD(wParam, lParam),
1654 GET_WM_COMMAND_HWND(wParam, lParam));
1655 case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (const LPCITEMIDLIST*)wParam, (LONG)lParam);
1657 case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1660 case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
1663 case WM_GETDLGCODE: return SendMessageW(pThis->hWndList, uMessage, 0, 0);
1666 RevokeDragDrop(pThis->hWnd);
1667 SHChangeNotifyDeregister(pThis->hNotify);
1671 if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1672 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1677 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
1679 /**********************************************************
1682 * The INTERFACE of the IShellView object
1685 **********************************************************
1686 * IShellView_QueryInterface
1688 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView2 * iface,REFIID riid, LPVOID *ppvObj)
1690 IShellViewImpl *This = (IShellViewImpl *)iface;
1692 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1696 if(IsEqualIID(riid, &IID_IUnknown))
1700 else if(IsEqualIID(riid, &IID_IShellView))
1704 else if(IsEqualIID(riid, &IID_IShellView2))
1708 else if(IsEqualIID(riid, &IID_IFolderView))
1710 *ppvObj = &This->lpvtblFolderView;
1712 else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1714 *ppvObj = &This->lpvtblOleCommandTarget;
1716 else if(IsEqualIID(riid, &IID_IDropTarget))
1718 *ppvObj = &This->lpvtblDropTarget;
1720 else if(IsEqualIID(riid, &IID_IDropSource))
1722 *ppvObj = &This->lpvtblDropSource;
1724 else if(IsEqualIID(riid, &IID_IViewObject))
1726 *ppvObj = &This->lpvtblViewObject;
1731 IUnknown_AddRef( (IUnknown*)*ppvObj );
1732 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1735 TRACE("-- Interface: E_NOINTERFACE\n");
1736 return E_NOINTERFACE;
1739 /**********************************************************
1742 static ULONG WINAPI IShellView_fnAddRef(IShellView2 * iface)
1744 IShellViewImpl *This = (IShellViewImpl *)iface;
1745 ULONG refCount = InterlockedIncrement(&This->ref);
1747 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
1751 /**********************************************************
1752 * IShellView_Release
1754 static ULONG WINAPI IShellView_fnRelease(IShellView2 * iface)
1756 IShellViewImpl *This = (IShellViewImpl *)iface;
1757 ULONG refCount = InterlockedDecrement(&This->ref);
1759 TRACE("(%p)->(count=%i)\n", This, refCount + 1);
1763 TRACE(" destroying IShellView(%p)\n",This);
1765 DestroyWindow(This->hWndList);
1768 IShellFolder_Release(This->pSFParent);
1770 if(This->pSF2Parent)
1771 IShellFolder2_Release(This->pSF2Parent);
1773 SHFree(This->apidl);
1776 IAdviseSink_Release(This->pAdvSink);
1778 HeapFree(GetProcessHeap(),0,This);
1783 /**********************************************************
1784 * ShellView_GetWindow
1786 static HRESULT WINAPI IShellView_fnGetWindow(IShellView2 * iface,HWND * phWnd)
1788 IShellViewImpl *This = (IShellViewImpl *)iface;
1790 TRACE("(%p)\n",This);
1792 *phWnd = This->hWnd;
1797 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView2 * iface,BOOL fEnterMode)
1799 IShellViewImpl *This = (IShellViewImpl *)iface;
1801 FIXME("(%p) stub\n",This);
1806 /**********************************************************
1807 * IShellView_TranslateAccelerator
1810 * use the accel functions
1812 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView2 * iface,LPMSG lpmsg)
1815 IShellViewImpl *This = (IShellViewImpl *)iface;
1817 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1820 if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1822 TRACE("-- key=0x04%lx\n",lpmsg->wParam) ;
1824 return S_FALSE; /* not handled */
1827 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView2 * iface,BOOL fEnable)
1829 IShellViewImpl *This = (IShellViewImpl *)iface;
1831 FIXME("(%p) stub\n",This);
1836 static HRESULT WINAPI IShellView_fnUIActivate(IShellView2 * iface,UINT uState)
1838 IShellViewImpl *This = (IShellViewImpl *)iface;
1841 CHAR szName[MAX_PATH];
1844 int nPartArray[1] = {-1};
1846 TRACE("(%p)->(state=%x) stub\n",This, uState);
1848 /*don't do anything if the state isn't really changing*/
1849 if(This->uState == uState)
1854 /*OnActivate handles the menu merging and internal state*/
1855 ShellView_OnActivate(This, uState);
1857 /*only do This if we are active*/
1858 if(uState != SVUIA_DEACTIVATE)
1862 GetFolderPath is not a method of IShellFolder
1863 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1865 /* set the number of parts */
1866 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1867 (LPARAM)nPartArray, &lResult);
1869 /* set the text for the parts */
1871 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1872 0, (LPARAM)szName, &lResult);
1879 static HRESULT WINAPI IShellView_fnRefresh(IShellView2 * iface)
1881 IShellViewImpl *This = (IShellViewImpl *)iface;
1883 TRACE("(%p)\n", This);
1885 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
1886 ShellView_FillList(This);
1891 static HRESULT WINAPI IShellView_fnCreateViewWindow(IShellView2 *iface, IShellView *lpPrevView,
1892 LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd)
1895 SV2CVW2_PARAMS view_params;
1896 view_params.cbSize = sizeof(view_params);
1897 view_params.psvPrev = lpPrevView;
1898 view_params.pfs = lpfs;
1899 view_params.psbOwner = psb;
1900 view_params.prcView = prcView;
1901 view_params.pvid = NULL;
1902 view_params.hwndView = 0;
1904 TRACE("(%p) Forwarding to CreateViewWindow2\n", iface);
1906 hr = IShellView2_CreateViewWindow2(iface, &view_params);
1907 *phWnd = view_params.hwndView;
1912 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView2 * iface)
1914 IShellViewImpl *This = (IShellViewImpl *)iface;
1916 TRACE("(%p)\n",This);
1918 /*Make absolutely sure all our UI is cleaned up.*/
1919 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1923 DestroyMenu(This->hMenu);
1926 DestroyWindow(This->hWnd);
1927 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1928 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1934 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView2 * iface, LPFOLDERSETTINGS lpfs)
1936 IShellViewImpl *This = (IShellViewImpl *)iface;
1938 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1939 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1941 if (!lpfs) return E_INVALIDARG;
1943 *lpfs = This->FolderSettings;
1947 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView2 * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1949 IShellViewImpl *This = (IShellViewImpl *)iface;
1951 FIXME("(%p) stub\n",This);
1956 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView2 * iface)
1958 IShellViewImpl *This = (IShellViewImpl *)iface;
1960 FIXME("(%p) stub\n",This);
1965 static HRESULT WINAPI IShellView_fnSelectItem(
1966 IShellView2 * iface,
1970 IShellViewImpl *This = (IShellViewImpl *)iface;
1975 TRACE("(%p)->(pidl=%p, 0x%08x)\n",This, pidl, flags);
1977 i = LV_FindItemByPidl(This, pidl);
1978 if (i == -1) return S_OK;
1980 hr = IShellView2_QueryInterface(iface, &IID_IFolderView, (void**)&view);
1983 hr = IFolderView_SelectItem(view, i, flags);
1984 IFolderView_Release(view);
1990 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView2 * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
1992 IShellViewImpl *This = (IShellViewImpl *)iface;
1993 HRESULT hr = E_NOINTERFACE;
1995 TRACE("(%p)->(0x%08x, %s, %p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2001 case SVGIO_BACKGROUND:
2003 if (IsEqualIID(&IID_IContextMenu, riid))
2005 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2009 FIXME("unsupported interface requested %s\n", debugstr_guid(riid));
2013 case SVGIO_SELECTION:
2014 ShellView_GetSelections(This);
2015 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2019 FIXME("unimplemented for uItem = 0x%08x\n", uItem);
2021 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2026 static HRESULT WINAPI IShellView2_fnGetView(IShellView2* iface, SHELLVIEWID *view_guid, ULONG view_type)
2028 FIXME("(%p)->(view_guid %s, view_type %#x) stub!\n", iface, debugstr_guid(view_guid), view_type);
2032 static HRESULT WINAPI IShellView2_fnCreateViewWindow2(IShellView2* iface, LPSV2CVW2_PARAMS view_params)
2034 IShellViewImpl *This = (IShellViewImpl *)iface;
2039 TRACE("(%p)->(view_params %p)\n", iface, view_params);
2041 if (view_params->cbSize != sizeof(*view_params))
2043 FIXME("Got unexpected cbSize %#x\n", view_params->cbSize);
2047 TRACE("-- psvPrev %p, pfs %p, psbOwner %p, prcView %p\n",
2048 view_params->psvPrev, view_params->pfs, view_params->psbOwner, view_params->prcView);
2049 TRACE("-- vmode %#x, flags %#x, left %d, top %d, right %d, bottom %d\n",
2050 view_params->pfs->ViewMode, view_params->pfs->fFlags, view_params->prcView->left,
2051 view_params->prcView->top, view_params->prcView->right, view_params->prcView->bottom);
2053 if (!view_params->psbOwner) return E_UNEXPECTED;
2055 /* Set up the member variables */
2056 This->pShellBrowser = view_params->psbOwner;
2057 This->FolderSettings = *view_params->pfs;
2059 if (view_params->pvid)
2061 if (IsEqualGUID(view_params->pvid, &VID_LargeIcons))
2062 This->FolderSettings.ViewMode = FVM_ICON;
2063 else if (IsEqualGUID(view_params->pvid, &VID_SmallIcons))
2064 This->FolderSettings.ViewMode = FVM_SMALLICON;
2065 else if (IsEqualGUID(view_params->pvid, &VID_List))
2066 This->FolderSettings.ViewMode = FVM_LIST;
2067 else if (IsEqualGUID(view_params->pvid, &VID_Details))
2068 This->FolderSettings.ViewMode = FVM_DETAILS;
2069 else if (IsEqualGUID(view_params->pvid, &VID_Thumbnails))
2070 This->FolderSettings.ViewMode = FVM_THUMBNAIL;
2071 else if (IsEqualGUID(view_params->pvid, &VID_Tile))
2072 This->FolderSettings.ViewMode = FVM_TILE;
2073 else if (IsEqualGUID(view_params->pvid, &VID_ThumbStrip))
2074 This->FolderSettings.ViewMode = FVM_THUMBSTRIP;
2076 FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_params->pvid));
2079 /* Get our parent window */
2080 IShellBrowser_AddRef(This->pShellBrowser);
2081 IShellBrowser_GetWindow(This->pShellBrowser, &This->hWndParent);
2083 /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
2084 This->pCommDlgBrowser = NULL;
2085 hr = IShellBrowser_QueryInterface(This->pShellBrowser, &IID_ICommDlgBrowser, (void **)&This->pCommDlgBrowser);
2087 TRACE("-- CommDlgBrowser %p\n", This->pCommDlgBrowser);
2089 /* If our window class has not been registered, then do so */
2090 if (!GetClassInfoW(shell32_hInstance, SV_CLASS_NAME, &wc))
2092 wc.style = CS_HREDRAW | CS_VREDRAW;
2093 wc.lpfnWndProc = ShellView_WndProc;
2096 wc.hInstance = shell32_hInstance;
2098 wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
2099 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2100 wc.lpszMenuName = NULL;
2101 wc.lpszClassName = SV_CLASS_NAME;
2103 if (!RegisterClassW(&wc)) return E_FAIL;
2106 wnd = CreateWindowExW(0, SV_CLASS_NAME, NULL, WS_CHILD | WS_TABSTOP,
2107 view_params->prcView->left, view_params->prcView->top,
2108 view_params->prcView->right - view_params->prcView->left,
2109 view_params->prcView->bottom - view_params->prcView->top,
2110 This->hWndParent, 0, shell32_hInstance, This);
2116 IShellBrowser_Release(This->pShellBrowser);
2120 SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
2123 view_params->hwndView = wnd;
2128 static HRESULT WINAPI IShellView2_fnHandleRename(IShellView2* iface, LPCITEMIDLIST new_pidl)
2130 FIXME("(%p)->(new_pidl %p) stub!\n", iface, new_pidl);
2134 static HRESULT WINAPI IShellView2_fnSelectAndPositionItem(
2140 IShellViewImpl *This = (IShellViewImpl *)iface;
2144 TRACE("(%p)->(item %p, flags %#x, point %p)\n", This, item, flags, point);
2146 hr = IShellView2_QueryInterface(iface, &IID_IFolderView, (void**)&view);
2149 hr = IFolderView_SelectAndPositionItems(view, 1, &item, point, flags);
2150 IFolderView_Release(view);
2156 static const IShellView2Vtbl svvt =
2158 IShellView_fnQueryInterface,
2159 IShellView_fnAddRef,
2160 IShellView_fnRelease,
2161 IShellView_fnGetWindow,
2162 IShellView_fnContextSensitiveHelp,
2163 IShellView_fnTranslateAccelerator,
2164 IShellView_fnEnableModeless,
2165 IShellView_fnUIActivate,
2166 IShellView_fnRefresh,
2167 IShellView_fnCreateViewWindow,
2168 IShellView_fnDestroyViewWindow,
2169 IShellView_fnGetCurrentInfo,
2170 IShellView_fnAddPropertySheetPages,
2171 IShellView_fnSaveViewState,
2172 IShellView_fnSelectItem,
2173 IShellView_fnGetItemObject,
2174 IShellView2_fnGetView,
2175 IShellView2_fnCreateViewWindow2,
2176 IShellView2_fnHandleRename,
2177 IShellView2_fnSelectAndPositionItem,
2181 /**********************************************************
2182 * ISVOleCmdTarget_QueryInterface (IUnknown)
2184 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2185 IOleCommandTarget * iface,
2189 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2191 return IShellView2_QueryInterface((IShellView2*)This, iid, ppvObj);
2194 /**********************************************************
2195 * ISVOleCmdTarget_AddRef (IUnknown)
2197 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2198 IOleCommandTarget * iface)
2200 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2202 return IShellView2_AddRef((IShellView2*)This);
2205 /**********************************************************
2206 * ISVOleCmdTarget_Release (IUnknown)
2208 static ULONG WINAPI ISVOleCmdTarget_Release(
2209 IOleCommandTarget * iface)
2211 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2213 return IShellView2_Release((IShellView2*)This);
2216 /**********************************************************
2217 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2219 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2220 IOleCommandTarget *iface,
2221 const GUID* pguidCmdGroup,
2224 OLECMDTEXT* pCmdText)
2227 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2229 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2230 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2234 for (i = 0; i < cCmds; i++)
2236 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2237 prgCmds[i].cmdf = 0;
2239 return OLECMDERR_E_UNKNOWNGROUP;
2242 /**********************************************************
2243 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2245 * nCmdID is the OLECMDID_* enumeration
2247 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2248 IOleCommandTarget *iface,
2249 const GUID* pguidCmdGroup,
2255 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2257 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2258 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2260 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2262 (nCmdexecopt == 4) && pvaOut)
2264 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2269 return OLECMDERR_E_UNKNOWNGROUP;
2272 static const IOleCommandTargetVtbl ctvt =
2274 ISVOleCmdTarget_QueryInterface,
2275 ISVOleCmdTarget_AddRef,
2276 ISVOleCmdTarget_Release,
2277 ISVOleCmdTarget_QueryStatus,
2278 ISVOleCmdTarget_Exec
2281 /**********************************************************
2282 * ISVDropTarget implementation
2285 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2290 IShellViewImpl *This = impl_from_IDropTarget(iface);
2292 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2294 return IShellView2_QueryInterface((IShellView2*)This, riid, ppvObj);
2297 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2299 IShellViewImpl *This = impl_from_IDropTarget(iface);
2301 TRACE("(%p)->(count=%u)\n",This,This->ref);
2303 return IShellView2_AddRef((IShellView2*)This);
2306 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2308 IShellViewImpl *This = impl_from_IDropTarget(iface);
2310 TRACE("(%p)->(count=%u)\n",This,This->ref);
2312 return IShellView2_Release((IShellView2*)This);
2315 /******************************************************************************
2316 * drag_notify_subitem [Internal]
2318 * Figure out the shellfolder object, which is currently under the mouse cursor
2319 * and notify it via the IDropTarget interface.
2322 #define SCROLLAREAWIDTH 20
2324 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2327 LVHITTESTINFO htinfo;
2333 /* Map from global to client coordinates and query the index of the listview-item, which is
2334 * currently under the mouse cursor. */
2337 htinfo.flags = LVHT_ONITEM;
2338 ScreenToClient(This->hWndList, &htinfo.pt);
2339 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2341 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2342 GetClientRect(This->hWndList, &clientRect);
2343 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2344 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2345 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2347 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2348 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2349 if (htinfo.pt.x < SCROLLAREAWIDTH)
2350 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2351 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2352 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2353 if (htinfo.pt.y < SCROLLAREAWIDTH)
2354 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2355 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2356 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2359 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2361 This->ptLastMousePos = htinfo.pt;
2363 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2364 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2365 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2367 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2368 if (This->pCurDropTarget) {
2369 IDropTarget_DragLeave(This->pCurDropTarget);
2370 IDropTarget_Release(This->pCurDropTarget);
2371 This->pCurDropTarget = NULL;
2374 This->iDragOverItem = lResult;
2375 if (lResult == -1) {
2376 /* We are not above one of the listview's subitems. Bind to the parent folder's
2377 * DropTarget interface. */
2378 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2379 (LPVOID*)&This->pCurDropTarget);
2381 /* Query the relative PIDL of the shellfolder object represented by the currently
2382 * dragged over listview-item ... */
2383 lvItem.mask = LVIF_PARAM;
2384 lvItem.iItem = lResult;
2385 lvItem.iSubItem = 0;
2386 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
2388 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2389 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2390 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2393 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2397 /* Notify the item just entered via DragEnter. */
2398 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2401 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2402 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2404 IShellViewImpl *This = impl_from_IDropTarget(iface);
2406 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2407 This->pCurDataObject = pDataObject;
2408 IDataObject_AddRef(pDataObject);
2410 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2413 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2416 IShellViewImpl *This = impl_from_IDropTarget(iface);
2417 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2420 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface)
2422 IShellViewImpl *This = impl_from_IDropTarget(iface);
2424 if (This->pCurDropTarget)
2426 IDropTarget_DragLeave(This->pCurDropTarget);
2427 IDropTarget_Release(This->pCurDropTarget);
2428 This->pCurDropTarget = NULL;
2431 if (This->pCurDataObject)
2433 IDataObject_Release(This->pCurDataObject);
2434 This->pCurDataObject = NULL;
2437 This->iDragOverItem = 0;
2442 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2443 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2445 IShellViewImpl *This = impl_from_IDropTarget(iface);
2447 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2449 IDropTarget_Release(This->pCurDropTarget);
2450 IDataObject_Release(This->pCurDataObject);
2451 This->pCurDataObject = NULL;
2452 This->pCurDropTarget = NULL;
2453 This->iDragOverItem = 0;
2458 static const IDropTargetVtbl dtvt =
2460 ISVDropTarget_QueryInterface,
2461 ISVDropTarget_AddRef,
2462 ISVDropTarget_Release,
2463 ISVDropTarget_DragEnter,
2464 ISVDropTarget_DragOver,
2465 ISVDropTarget_DragLeave,
2469 /**********************************************************
2470 * ISVDropSource implementation
2473 static HRESULT WINAPI ISVDropSource_QueryInterface(
2478 IShellViewImpl *This = impl_from_IDropSource(iface);
2480 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2482 return IShellView2_QueryInterface((IShellView2*)This, riid, ppvObj);
2485 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2487 IShellViewImpl *This = impl_from_IDropSource(iface);
2489 TRACE("(%p)->(count=%u)\n",This,This->ref);
2491 return IShellView2_AddRef((IShellView2*)This);
2494 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2496 IShellViewImpl *This = impl_from_IDropSource(iface);
2498 TRACE("(%p)->(count=%u)\n",This,This->ref);
2500 return IShellView2_Release((IShellView2*)This);
2503 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2505 BOOL fEscapePressed,
2508 IShellViewImpl *This = impl_from_IDropSource(iface);
2509 TRACE("(%p)\n",This);
2512 return DRAGDROP_S_CANCEL;
2513 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2514 return DRAGDROP_S_DROP;
2519 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2523 IShellViewImpl *This = impl_from_IDropSource(iface);
2524 TRACE("(%p)\n",This);
2526 return DRAGDROP_S_USEDEFAULTCURSORS;
2529 static const IDropSourceVtbl dsvt =
2531 ISVDropSource_QueryInterface,
2532 ISVDropSource_AddRef,
2533 ISVDropSource_Release,
2534 ISVDropSource_QueryContinueDrag,
2535 ISVDropSource_GiveFeedback
2537 /**********************************************************
2538 * ISVViewObject implementation
2541 static HRESULT WINAPI ISVViewObject_QueryInterface(
2546 IShellViewImpl *This = impl_from_IViewObject(iface);
2548 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2550 return IShellView2_QueryInterface((IShellView2*)This, riid, ppvObj);
2553 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2555 IShellViewImpl *This = impl_from_IViewObject(iface);
2557 TRACE("(%p)->(count=%u)\n",This,This->ref);
2559 return IShellView2_AddRef((IShellView2*)This);
2562 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2564 IShellViewImpl *This = impl_from_IViewObject(iface);
2566 TRACE("(%p)->(count=%u)\n",This,This->ref);
2568 return IShellView2_Release((IShellView2*)This);
2571 static HRESULT WINAPI ISVViewObject_Draw(
2576 DVTARGETDEVICE* ptd,
2579 LPCRECTL lprcBounds,
2580 LPCRECTL lprcWBounds,
2581 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2582 ULONG_PTR dwContinue)
2585 IShellViewImpl *This = impl_from_IViewObject(iface);
2587 FIXME("Stub: This=%p\n",This);
2591 static HRESULT WINAPI ISVViewObject_GetColorSet(
2596 DVTARGETDEVICE* ptd,
2597 HDC hicTargetDevice,
2598 LOGPALETTE** ppColorSet)
2601 IShellViewImpl *This = impl_from_IViewObject(iface);
2603 FIXME("Stub: This=%p\n",This);
2607 static HRESULT WINAPI ISVViewObject_Freeze(
2615 IShellViewImpl *This = impl_from_IViewObject(iface);
2617 FIXME("Stub: This=%p\n",This);
2621 static HRESULT WINAPI ISVViewObject_Unfreeze(
2626 IShellViewImpl *This = impl_from_IViewObject(iface);
2628 FIXME("Stub: This=%p\n",This);
2632 static HRESULT WINAPI ISVViewObject_SetAdvise(
2636 IAdviseSink* pAdvSink)
2639 IShellViewImpl *This = impl_from_IViewObject(iface);
2641 FIXME("partial stub: %p %08x %08x %p\n",
2642 This, aspects, advf, pAdvSink);
2644 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2645 This->pAdvSink = pAdvSink;
2646 This->dwAspects = aspects;
2647 This->dwAdvf = advf;
2652 static HRESULT WINAPI ISVViewObject_GetAdvise(
2656 IAdviseSink** ppAdvSink)
2659 IShellViewImpl *This = impl_from_IViewObject(iface);
2661 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2662 This, pAspects, pAdvf, ppAdvSink);
2666 IAdviseSink_AddRef( This->pAdvSink );
2667 *ppAdvSink = This->pAdvSink;
2670 *pAspects = This->dwAspects;
2672 *pAdvf = This->dwAdvf;
2678 static const IViewObjectVtbl vovt =
2680 ISVViewObject_QueryInterface,
2681 ISVViewObject_AddRef,
2682 ISVViewObject_Release,
2684 ISVViewObject_GetColorSet,
2685 ISVViewObject_Freeze,
2686 ISVViewObject_Unfreeze,
2687 ISVViewObject_SetAdvise,
2688 ISVViewObject_GetAdvise
2692 static HRESULT WINAPI IFView_QueryInterface(
2697 IShellViewImpl *This = impl_from_IFolderView(iface);
2698 TRACE("(%p)->(IID:%s,%p)\n", This, debugstr_guid(riid), ppvObj);
2699 return IShellView2_QueryInterface((IShellView2*)This, riid, ppvObj);
2702 static ULONG WINAPI IFView_AddRef( IFolderView *iface)
2704 IShellViewImpl *This = impl_from_IFolderView(iface);
2705 TRACE("(%p)->(count=%u)\n", This, This->ref);
2706 return IShellView2_AddRef((IShellView2*)This);
2709 static ULONG WINAPI IFView_Release( IFolderView *iface)
2711 IShellViewImpl *This = impl_from_IFolderView(iface);
2712 TRACE("(%p)->(count=%u)\n", This, This->ref);
2713 return IShellView2_Release((IShellView2*)This);
2716 static HRESULT WINAPI IFView_GetCurrentViewMode(IFolderView *iface, UINT *mode)
2718 IShellViewImpl *This = impl_from_IFolderView(iface);
2719 FIXME("(%p)->(%p), stub\n", This, mode);
2723 static HRESULT WINAPI IFView_SetCurrentViewMode(IFolderView *iface, UINT mode)
2725 IShellViewImpl *This = impl_from_IFolderView(iface);
2726 FIXME("(%p)->(%u), stub\n", This, mode);
2730 static HRESULT WINAPI IFView_GetFolder(IFolderView *iface, REFIID riid, void **ppv)
2732 IShellViewImpl *This = impl_from_IFolderView(iface);
2734 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
2736 if (!ppv) return E_POINTER;
2738 if (IsEqualIID(riid, &IID_IShellFolder))
2740 *ppv = This->pSFParent;
2744 return E_NOINTERFACE;
2747 static HRESULT WINAPI IFView_Item(IFolderView *iface, int index, PITEMID_CHILD *ppidl)
2749 IShellViewImpl *This = impl_from_IFolderView(iface);
2750 FIXME("(%p)->(%d %p), stub\n", This, index, ppidl);
2754 static HRESULT WINAPI IFView_ItemCount(IFolderView *iface, UINT flags, int *items)
2756 IShellViewImpl *This = impl_from_IFolderView(iface);
2758 TRACE("(%p)->(%u %p)\n", This, flags, items);
2760 if (flags != SVGIO_ALLVIEW)
2761 FIXME("some flags unsupported, %x\n", flags & ~SVGIO_ALLVIEW);
2763 *items = SendMessageW(This->hWndList, LVM_GETITEMCOUNT, 0, 0);
2768 static HRESULT WINAPI IFView_Items(IFolderView *iface, UINT flags, REFIID riid, void **ppv)
2770 IShellViewImpl *This = impl_from_IFolderView(iface);
2771 FIXME("(%p)->(%u %s %p), stub\n", This, flags, debugstr_guid(riid), ppv);
2775 static HRESULT WINAPI IFView_GetSelectionMarkedItem(IFolderView *iface, int *item)
2777 IShellViewImpl *This = impl_from_IFolderView(iface);
2779 TRACE("(%p)->(%p)\n", This, item);
2781 *item = SendMessageW(This->hWndList, LVM_GETSELECTIONMARK, 0, 0);
2786 static HRESULT WINAPI IFView_GetFocusedItem(IFolderView *iface, int *item)
2788 IShellViewImpl *This = impl_from_IFolderView(iface);
2790 TRACE("(%p)->(%p)\n", This, item);
2792 *item = SendMessageW(This->hWndList, LVM_GETNEXTITEM, -1, LVNI_FOCUSED);
2797 static HRESULT WINAPI IFView_GetItemPosition(IFolderView *iface, PCUITEMID_CHILD pidl, POINT *ppt)
2799 IShellViewImpl *This = impl_from_IFolderView(iface);
2800 FIXME("(%p)->(%p %p), stub\n", This, pidl, ppt);
2804 static HRESULT WINAPI IFView_GetSpacing(IFolderView *iface, POINT *pt)
2806 IShellViewImpl *This = impl_from_IFolderView(iface);
2808 TRACE("(%p)->(%p)\n", This, pt);
2810 if (!This->hWndList) return S_FALSE;
2815 ret = SendMessageW(This->hWndList, LVM_GETITEMSPACING, 0, 0);
2817 pt->x = LOWORD(ret);
2818 pt->y = HIWORD(ret);
2824 static HRESULT WINAPI IFView_GetDefaultSpacing(IFolderView *iface, POINT *pt)
2826 IShellViewImpl *This = impl_from_IFolderView(iface);
2827 FIXME("(%p)->(%p), stub\n", This, pt);
2831 static HRESULT WINAPI IFView_GetAutoArrange(IFolderView *iface)
2833 IShellViewImpl *This = impl_from_IFolderView(iface);
2834 FIXME("(%p), stub\n", This);
2838 static HRESULT WINAPI IFView_SelectItem(IFolderView *iface, int item, DWORD flags)
2840 IShellViewImpl *This = impl_from_IFolderView(iface);
2843 TRACE("(%p)->(%d, %x)\n", This, item, flags);
2846 lvItem.stateMask = LVIS_SELECTED;
2848 if (flags & SVSI_ENSUREVISIBLE)
2849 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, item, 0);
2852 if (flags & SVSI_DESELECTOTHERS)
2853 SendMessageW(This->hWndList, LVM_SETITEMSTATE, -1, (LPARAM)&lvItem);
2856 if (flags & SVSI_SELECT)
2857 lvItem.state |= LVIS_SELECTED;
2859 if (flags & SVSI_FOCUSED)
2860 lvItem.stateMask |= LVIS_FOCUSED;
2862 SendMessageW(This->hWndList, LVM_SETITEMSTATE, item, (LPARAM)&lvItem);
2864 if (flags & SVSI_EDIT)
2865 SendMessageW(This->hWndList, LVM_EDITLABELW, item, 0);
2870 static HRESULT WINAPI IFView_SelectAndPositionItems(IFolderView *iface, UINT cidl,
2871 PCUITEMID_CHILD_ARRAY apidl, POINT *apt, DWORD flags)
2873 IShellViewImpl *This = impl_from_IFolderView(iface);
2874 FIXME("(%p)->(%u %p %p %x), stub\n", This, cidl, apidl, apt, flags);
2878 static const IFolderViewVtbl fviewvt =
2880 IFView_QueryInterface,
2883 IFView_GetCurrentViewMode,
2884 IFView_SetCurrentViewMode,
2889 IFView_GetSelectionMarkedItem,
2890 IFView_GetFocusedItem,
2891 IFView_GetItemPosition,
2893 IFView_GetDefaultSpacing,
2894 IFView_GetAutoArrange,
2896 IFView_SelectAndPositionItems