4 * Copyright 1998,1999 <juergen.schmied@debitel.net>
6 * This is the view visualizing the data provied 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * FIXME: The order by part of the background context menu should be
24 * buily according to the columns shown.
26 * FIXME: Load/Save the view state from/into the stream provied 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
60 #include "undocshell.h"
62 #include "wine/debug.h"
66 #include "shell32_main.h"
67 #include "shellfolder.h"
69 WINE_DEFAULT_DEBUG_CHANNEL(shell);
75 }LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;
79 const IShellViewVtbl* lpVtbl;
81 const IOleCommandTargetVtbl* lpvtblOleCommandTarget;
82 const IDropTargetVtbl* lpvtblDropTarget;
83 const IDropSourceVtbl* lpvtblDropSource;
84 const IViewObjectVtbl* lpvtblViewObject;
85 IShellFolder* pSFParent;
86 IShellFolder2* pSF2Parent;
87 IShellBrowser* pShellBrowser;
88 ICommDlgBrowser* pCommDlgBrowser;
89 HWND hWnd; /* SHELLDLL_DefView */
90 HWND hWndList; /* ListView control */
92 FOLDERSETTINGS FolderSettings;
97 LISTVIEW_SORT_INFO ListViewSortInfo;
98 ULONG hNotify; /* change notification handle */
102 IAdviseSink *pAdvSink;
103 IDropTarget* pCurDropTarget; /* The sub-item, which is currently dragged over */
104 IDataObject* pCurDataObject; /* The dragged data-object */
105 LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */
106 UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
107 POINT ptLastMousePos; /* Mouse position at last DragOver call */
110 static const IShellViewVtbl svvt;
111 static const IOleCommandTargetVtbl ctvt;
112 static const IDropTargetVtbl dtvt;
113 static const IDropSourceVtbl dsvt;
114 static const IViewObjectVtbl vovt;
117 static inline IShellViewImpl *impl_from_IOleCommandTarget( IOleCommandTarget *iface )
119 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblOleCommandTarget));
122 static inline IShellViewImpl *impl_from_IDropTarget( IDropTarget *iface )
124 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropTarget));
127 static inline IShellViewImpl *impl_from_IDropSource( IDropSource *iface )
129 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropSource));
132 static inline IShellViewImpl *impl_from_IViewObject( IViewObject *iface )
134 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblViewObject));
137 /* ListView Header ID's */
138 #define LISTVIEW_COLUMN_NAME 0
139 #define LISTVIEW_COLUMN_SIZE 1
140 #define LISTVIEW_COLUMN_TYPE 2
141 #define LISTVIEW_COLUMN_TIME 3
142 #define LISTVIEW_COLUMN_ATTRIB 4
145 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
146 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
147 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
149 #define ID_LISTVIEW 1
151 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
154 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
155 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
156 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
159 Items merged into the toolbar and and the filemenu
168 } MYTOOLINFO, *LPMYTOOLINFO;
172 { FCIDM_SHVIEW_BIGICON, 0, 0, IDS_VIEW_LARGE, TBSTATE_ENABLED, BTNS_BUTTON },
173 { FCIDM_SHVIEW_SMALLICON, 0, 0, IDS_VIEW_SMALL, TBSTATE_ENABLED, BTNS_BUTTON },
174 { FCIDM_SHVIEW_LISTVIEW, 0, 0, IDS_VIEW_LIST, TBSTATE_ENABLED, BTNS_BUTTON },
175 { FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON },
179 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
181 /**********************************************************
182 * IShellView_Constructor
184 IShellView * IShellView_Constructor( IShellFolder * pFolder)
185 { IShellViewImpl * sv;
186 sv=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellViewImpl));
189 sv->lpvtblOleCommandTarget=&ctvt;
190 sv->lpvtblDropTarget=&dtvt;
191 sv->lpvtblDropSource=&dsvt;
192 sv->lpvtblViewObject=&vovt;
194 sv->pSFParent = pFolder;
195 if(pFolder) IShellFolder_AddRef(pFolder);
196 IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent);
198 sv->pCurDropTarget = NULL;
199 sv->pCurDataObject = NULL;
200 sv->iDragOverItem = 0;
201 sv->cScrollDelay = 0;
202 sv->ptLastMousePos.x = 0;
203 sv->ptLastMousePos.y = 0;
205 TRACE("(%p)->(%p)\n",sv, pFolder);
206 return (IShellView *) sv;
209 /**********************************************************
211 * ##### helperfunctions for communication with ICommDlgBrowser #####
213 static BOOL IsInCommDlg(IShellViewImpl * This)
214 { return(This->pCommDlgBrowser != NULL);
217 static HRESULT IncludeObject(IShellViewImpl * This, LPCITEMIDLIST pidl)
221 if ( IsInCommDlg(This) )
223 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
224 ret = ICommDlgBrowser_IncludeObject(This->pCommDlgBrowser, (IShellView*)This, pidl);
225 TRACE("--0x%08lx\n", ret);
230 static HRESULT OnDefaultCommand(IShellViewImpl * This)
232 HRESULT ret = S_FALSE;
234 if (IsInCommDlg(This))
236 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
237 ret = ICommDlgBrowser_OnDefaultCommand(This->pCommDlgBrowser, (IShellView*)This);
238 TRACE("-- returns %08lx\n", ret);
243 static HRESULT OnStateChange(IShellViewImpl * This, UINT uFlags)
245 HRESULT ret = S_FALSE;
247 if (IsInCommDlg(This))
249 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
250 ret = ICommDlgBrowser_OnStateChange(This->pCommDlgBrowser, (IShellView*)This, uFlags);
255 /**********************************************************
256 * set the toolbar of the filedialog buttons
258 * - activates the buttons from the shellbrowser according to
261 static void CheckToolbar(IShellViewImpl * This)
267 if (IsInCommDlg(This))
269 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
270 FCIDM_TB_SMALLICON, (This->FolderSettings.ViewMode==FVM_LIST)? TRUE : FALSE, &result);
271 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
272 FCIDM_TB_REPORTVIEW, (This->FolderSettings.ViewMode==FVM_DETAILS)? TRUE : FALSE, &result);
273 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
274 FCIDM_TB_SMALLICON, TRUE, &result);
275 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
276 FCIDM_TB_REPORTVIEW, TRUE, &result);
280 /**********************************************************
282 * ##### helperfunctions for initializing the view #####
284 /**********************************************************
285 * change the style of the listview control
287 static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove)
291 TRACE("(%p)\n", This);
293 tmpstyle = GetWindowLongA(This->hWndList, GWL_STYLE);
294 SetWindowLongA(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
297 /**********************************************************
298 * ShellView_CreateList()
300 * - creates the list view window
302 static BOOL ShellView_CreateList (IShellViewImpl * This)
303 { DWORD dwStyle, dwExStyle;
307 dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
308 LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT | LVS_AUTOARRANGE;
309 dwExStyle = WS_EX_CLIENTEDGE;
311 switch (This->FolderSettings.ViewMode)
313 case FVM_ICON: dwStyle |= LVS_ICON; break;
314 case FVM_DETAILS: dwStyle |= LVS_REPORT; break;
315 case FVM_SMALLICON: dwStyle |= LVS_SMALLICON; break;
316 case FVM_LIST: dwStyle |= LVS_LIST; break;
317 default: dwStyle |= LVS_LIST; break;
320 if (This->FolderSettings.fFlags & FWF_AUTOARRANGE) dwStyle |= LVS_AUTOARRANGE;
321 if (This->FolderSettings.fFlags & FWF_DESKTOP)
322 This->FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
323 if (This->FolderSettings.fFlags & FWF_SINGLESEL) dwStyle |= LVS_SINGLESEL;
324 if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE)
325 dwExStyle &= ~WS_EX_CLIENTEDGE;
327 This->hWndList=CreateWindowExA( dwExStyle,
340 This->ListViewSortInfo.bIsAscending = TRUE;
341 This->ListViewSortInfo.nHeaderID = -1;
342 This->ListViewSortInfo.nLastHeaderID = -1;
344 if (This->FolderSettings.fFlags & FWF_DESKTOP) {
345 if (0) /* FIXME: look into registry vale HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow and activate drop shadows */
346 ListView_SetTextBkColor(This->hWndList, CLR_NONE);
348 ListView_SetTextBkColor(This->hWndList, GetSysColor(COLOR_DESKTOP));
350 ListView_SetTextColor(This->hWndList, RGB(255,255,255));
353 /* UpdateShellSettings(); */
357 /**********************************************************
358 * ShellView_InitList()
360 * - adds all needed columns to the shellview
362 static BOOL ShellView_InitList(IShellViewImpl * This)
371 ListView_DeleteAllItems(This->hWndList);
373 lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
374 lvColumn.pszText = szTemp;
376 if (This->pSF2Parent)
380 if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd)))
382 lvColumn.fmt = sd.fmt;
383 lvColumn.cx = sd.cxChar*8; /* chars->pixel */
384 StrRetToStrNA( szTemp, 50, &sd.str, NULL);
385 ListView_InsertColumnA(This->hWndList, i, &lvColumn);
393 ListView_SetImageList(This->hWndList, ShellSmallIconList, LVSIL_SMALL);
394 ListView_SetImageList(This->hWndList, ShellBigIconList, LVSIL_NORMAL);
398 /**********************************************************
399 * ShellView_CompareItems()
402 * internal, CALLBACK for DSA_Sort
404 static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
407 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
409 if(!lpData) return 0;
411 ret = (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2));
412 TRACE("ret=%i\n",ret);
416 /*************************************************************************
417 * ShellView_ListViewCompareItems
419 * Compare Function for the Listview (FileOpen Dialog)
422 * lParam1 [I] the first ItemIdList to compare with
423 * lParam2 [I] the second ItemIdList to compare with
424 * lpData [I] The column ID for the header Ctrl to process
427 * A negative value if the first item should precede the second,
428 * a positive value if the first item should follow the second,
429 * or zero if the two items are equivalent
432 * FIXME: function does what ShellView_CompareItems is supposed to do.
433 * unify it and figure out how to use the undocumented first parameter
434 * of IShellFolder_CompareIDs to do the job this function does and
435 * move this code to IShellFolder.
436 * make LISTVIEW_SORT_INFO obsolete
437 * the way this function works is only usable if we had only
438 * filesystemfolders (25/10/99 jsch)
440 static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
444 char strName1[MAX_PATH], strName2[MAX_PATH];
445 BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
446 LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1;
447 LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2;
448 LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData;
451 bIsFolder1 = _ILIsFolder(pItemIdList1);
452 bIsFolder2 = _ILIsFolder(pItemIdList2);
453 bIsBothFolder = bIsFolder1 && bIsFolder2;
455 /* When sorting between a File and a Folder, the Folder gets sorted first */
456 if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
458 nDiff = bIsFolder1 ? -1 : 1;
462 /* Sort by Time: Folders or Files can be sorted */
464 if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
466 _ILGetFileDateTime(pItemIdList1, &fd1);
467 _ILGetFileDateTime(pItemIdList2, &fd2);
468 nDiff = CompareFileTime(&fd2, &fd1);
470 /* Sort by Attribute: Folder or Files can be sorted */
471 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
473 _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH);
474 _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH);
475 nDiff = lstrcmpiA(strName1, strName2);
477 /* Sort by FileName: Folder or Files can be sorted */
478 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
481 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
482 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
483 nDiff = lstrcmpiA(strName1, strName2);
485 /* Sort by File Size, Only valid for Files */
486 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
488 nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0));
490 /* Sort by File Type, Only valid for Files */
491 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
494 _ILGetFileType(pItemIdList1, strName1, MAX_PATH);
495 _ILGetFileType(pItemIdList2, strName2, MAX_PATH);
496 nDiff = lstrcmpiA(strName1, strName2);
499 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
503 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
504 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
505 nDiff = lstrcmpiA(strName1, strName2);
508 if(!pSortInfo->bIsAscending)
517 /**********************************************************
518 * LV_FindItemByPidl()
520 static int LV_FindItemByPidl(
521 IShellViewImpl * This,
525 ZeroMemory(&lvItem, sizeof(LVITEMA));
526 lvItem.mask = LVIF_PARAM;
527 for(lvItem.iItem = 0; ListView_GetItemA(This->hWndList, &lvItem); lvItem.iItem++)
529 LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam;
530 HRESULT hr = IShellFolder_CompareIDs(This->pSFParent, 0, pidl, currentpidl);
531 if(SUCCEEDED(hr) && !HRESULT_CODE(hr))
539 /**********************************************************
542 static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
546 TRACE("(%p)(pidl=%p)\n", This, pidl);
548 ZeroMemory(&lvItem, sizeof(lvItem)); /* create the listview item*/
549 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/
550 lvItem.iItem = ListView_GetItemCount(This->hWndList); /*add the item to the end of the list*/
551 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/
552 lvItem.pszText = LPSTR_TEXTCALLBACKA; /*get text on a callback basis*/
553 lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/
554 return (-1==ListView_InsertItemA(This->hWndList, &lvItem))? FALSE: TRUE;
557 /**********************************************************
560 static BOOLEAN LV_DeleteItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
564 TRACE("(%p)(pidl=%p)\n", This, pidl);
566 nIndex = LV_FindItemByPidl(This, ILFindLastID(pidl));
567 return (-1==ListView_DeleteItem(This->hWndList, nIndex))? FALSE: TRUE;
570 /**********************************************************
573 static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew )
578 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew);
580 nItem = LV_FindItemByPidl(This, ILFindLastID(pidlOld));
583 ZeroMemory(&lvItem, sizeof(lvItem)); /* create the listview item*/
584 lvItem.mask = LVIF_PARAM; /* only the pidl */
585 lvItem.iItem = nItem;
586 ListView_GetItemA(This->hWndList, &lvItem);
588 SHFree((LPITEMIDLIST)lvItem.lParam);
589 lvItem.mask = LVIF_PARAM;
590 lvItem.iItem = nItem;
591 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */
592 ListView_SetItemA(This->hWndList, &lvItem);
593 ListView_Update(This->hWndList, nItem);
594 return TRUE; /* FIXME: better handling */
598 /**********************************************************
599 * ShellView_FillList()
601 * - gets the objectlist from the shellfolder
603 * - fills the list into the view
606 static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg )
608 LPITEMIDLIST pidl = ptr;
609 IShellViewImpl *This = arg;
610 /* in a commdlg This works as a filemask*/
611 if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl);
616 static HRESULT ShellView_FillList(IShellViewImpl * This)
618 LPENUMIDLIST pEnumIDList;
626 /* get the itemlist from the shfolder*/
627 hRes = IShellFolder_EnumObjects(This->pSFParent,This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
635 /* create a pointer array */
636 hdpa = DPA_Create(16);
639 return(E_OUTOFMEMORY);
642 /* copy the items into the array*/
643 while((S_OK == IEnumIDList_Next(pEnumIDList,1, &pidl, &dwFetched)) && dwFetched)
645 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
652 DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent);
654 /*turn the listview's redrawing off*/
655 SendMessageA(This->hWndList, WM_SETREDRAW, FALSE, 0);
657 DPA_DestroyCallback( hdpa, fill_list, This );
659 /*turn the listview's redrawing back on and force it to draw*/
660 SendMessageA(This->hWndList, WM_SETREDRAW, TRUE, 0);
662 IEnumIDList_Release(pEnumIDList); /* destroy the list*/
667 /**********************************************************
668 * ShellView_OnCreate()
670 static LRESULT ShellView_OnCreate(IShellViewImpl * This)
673 SHChangeNotifyEntry ntreg;
674 IPersistFolder2 * ppf2 = NULL;
678 if(ShellView_CreateList(This))
680 if(ShellView_InitList(This))
682 ShellView_FillList(This);
686 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown*)&This->lpVtbl, &IID_IDropTarget, (LPVOID*)&pdt)))
688 RegisterDragDrop(This->hWnd, pdt);
689 IDropTarget_Release(pdt);
692 /* register for receiving notifications */
693 IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
696 IPersistFolder2_GetCurFolder(ppf2, (LPITEMIDLIST*)&ntreg.pidl);
697 ntreg.fRecursive = TRUE;
698 This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
699 SHFree((LPITEMIDLIST)ntreg.pidl);
700 IPersistFolder2_Release(ppf2);
703 This->hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel");
708 /**********************************************************
709 * #### Handling of the menus ####
712 /**********************************************************
713 * ShellView_BuildFileMenu()
715 static HMENU ShellView_BuildFileMenu(IShellViewImpl * This)
716 { CHAR szText[MAX_PATH];
721 TRACE("(%p)\n",This);
723 hSubMenu = CreatePopupMenu();
725 { /*get the number of items in our global array*/
726 for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
728 /*add the menu items*/
729 for(i = 0; i < nTools; i++)
731 LoadStringA(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
733 ZeroMemory(&mii, sizeof(mii));
734 mii.cbSize = sizeof(mii);
735 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
737 if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
739 mii.fType = MFT_STRING;
740 mii.fState = MFS_ENABLED;
741 mii.dwTypeData = szText;
742 mii.wID = Tools[i].idCommand;
746 mii.fType = MFT_SEPARATOR;
748 /* tack This item onto the end of the menu */
749 InsertMenuItemA(hSubMenu, (UINT)-1, TRUE, &mii);
752 TRACE("-- return (menu=%p)\n",hSubMenu);
755 /**********************************************************
756 * ShellView_MergeFileMenu()
758 static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu)
759 { TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu);
762 { /*insert This item at the beginning of the menu */
763 _InsertMenuItem(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
764 _InsertMenuItem(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, "dummy45", MFS_ENABLED);
770 /**********************************************************
771 * ShellView_MergeViewMenu()
774 static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu)
777 TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
780 { /*add a separator at the correct position in the menu*/
781 _InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
783 ZeroMemory(&mii, sizeof(mii));
784 mii.cbSize = sizeof(mii);
785 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
786 mii.fType = MFT_STRING;
787 mii.dwTypeData = "View";
788 mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
789 InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
793 /**********************************************************
794 * ShellView_GetSelections()
796 * - fills the this->apidl list with the selected objects
799 * number of selected items
801 static UINT ShellView_GetSelections(IShellViewImpl * This)
811 This->cidl = ListView_GetSelectedCount(This->hWndList);
812 This->apidl = (LPITEMIDLIST*)SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
814 TRACE("selected=%i\n", This->cidl);
818 TRACE("-- Items selected =%u\n", This->cidl);
820 ZeroMemory(&lvItem, sizeof(lvItem));
821 lvItem.mask = LVIF_STATE | LVIF_PARAM;
822 lvItem.stateMask = LVIS_SELECTED;
824 while(ListView_GetItemA(This->hWndList, &lvItem) && (i < This->cidl))
826 if(lvItem.state & LVIS_SELECTED)
828 This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
830 TRACE("-- selected Item found\n");
839 /**********************************************************
840 * ShellView_OpenSelectedItems()
842 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
844 static UINT CF_IDLIST = 0;
846 IDataObject* selection;
850 LPCITEMIDLIST parent_pidl;
853 if (0 == ShellView_GetSelections(This))
857 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
858 (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
859 0, (LPVOID *)&selection);
865 CF_IDLIST = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
867 fetc.cfFormat = CF_IDLIST;
869 fetc.dwAspect = DVASPECT_CONTENT;
871 fetc.tymed = TYMED_HGLOBAL;
873 hr = IDataObject_QueryGetData(selection, &fetc);
877 hr = IDataObject_GetData(selection, &fetc, &stgm);
881 pIDList = GlobalLock(stgm.u.hGlobal);
883 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
884 for (i = pIDList->cidl; i > 0; --i)
889 pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
891 attribs = SFGAO_FOLDER;
892 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
894 if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
896 SHELLEXECUTEINFOA shexinfo;
898 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOA);
899 shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */
900 shexinfo.hwnd = NULL;
901 shexinfo.lpVerb = NULL;
902 shexinfo.lpFile = NULL;
903 shexinfo.lpParameters = NULL;
904 shexinfo.lpDirectory = NULL;
905 shexinfo.nShow = SW_NORMAL;
906 shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
908 ShellExecuteExA(&shexinfo); /* Discard error/success info */
910 ILFree((LPITEMIDLIST)shexinfo.lpIDList);
914 GlobalUnlock(stgm.u.hGlobal);
915 ReleaseStgMedium(&stgm);
917 IDataObject_Release(selection);
922 /**********************************************************
923 * ShellView_DoContextMenu()
925 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
929 BOOL fExplore = FALSE;
931 LPCONTEXTMENU pContextMenu = NULL;
932 IContextMenu2 *pCM = NULL;
933 CMINVOKECOMMANDINFO cmi;
935 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
937 /* look, what's selected and create a context menu object of it*/
938 if( ShellView_GetSelections(This) )
940 IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
941 (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
945 TRACE("-- pContextMenu\n");
946 hMenu = CreatePopupMenu();
950 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
951 if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
953 TRACE("-- explore mode\n");
957 /* build the flags depending on what we can do with the selected item */
958 wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
960 /* let the ContextMenu merge its items in */
961 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
963 if (This->FolderSettings.fFlags & FWF_DESKTOP)
964 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
968 TRACE("-- get menu default command\n");
969 uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
973 TRACE("-- track popup\n");
974 uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
979 TRACE("-- uCommand=%u\n", uCommand);
980 if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
982 TRACE("-- dlg: OnDefaultCommand\n");
983 if (OnDefaultCommand(This) != S_OK)
985 ShellView_OpenSelectedItems(This);
990 TRACE("-- explore -- invoke command\n");
991 ZeroMemory(&cmi, sizeof(cmi));
992 cmi.cbSize = sizeof(cmi);
993 cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
994 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
995 IContextMenu_InvokeCommand(pContextMenu, &cmi);
1002 IContextMenu_Release(pContextMenu);
1005 else /* background context menu */
1007 hMenu = CreatePopupMenu();
1009 pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
1010 IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1012 uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1015 TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1017 ZeroMemory(&cmi, sizeof(cmi));
1018 cmi.cbSize = sizeof(cmi);
1019 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1020 cmi.hwnd = This->hWndParent;
1021 IContextMenu2_InvokeCommand(pCM, &cmi);
1023 IContextMenu2_Release(pCM);
1027 /**********************************************************
1028 * ##### message handling #####
1031 /**********************************************************
1032 * ShellView_OnSize()
1034 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1036 TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1038 /*resize the ListView to fit our window*/
1041 MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1046 /**********************************************************
1047 * ShellView_OnDeactivate()
1052 static void ShellView_OnDeactivate(IShellViewImpl * This)
1056 if(This->uState != SVUIA_DEACTIVATE)
1060 IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1061 IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1062 DestroyMenu(This->hMenu);
1066 This->uState = SVUIA_DEACTIVATE;
1070 /**********************************************************
1071 * ShellView_OnActivate()
1073 static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState)
1074 { OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} };
1076 CHAR szText[MAX_PATH];
1078 TRACE("%p uState=%x\n",This,uState);
1080 /*don't do anything if the state isn't really changing */
1081 if(This->uState == uState)
1086 ShellView_OnDeactivate(This);
1088 /*only do This if we are active */
1089 if(uState != SVUIA_DEACTIVATE)
1091 /*merge the menus */
1092 This->hMenu = CreateMenu();
1096 IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1097 TRACE("-- after fnInsertMenusSB\n");
1099 /*build the top level menu get the menu item's text*/
1100 strcpy(szText,"dummy 31");
1102 ZeroMemory(&mii, sizeof(mii));
1103 mii.cbSize = sizeof(mii);
1104 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1105 mii.fType = MFT_STRING;
1106 mii.fState = MFS_ENABLED;
1107 mii.dwTypeData = szText;
1108 mii.hSubMenu = ShellView_BuildFileMenu(This);
1110 /*insert our menu into the menu bar*/
1113 InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1116 /*get the view menu so we can merge with it*/
1117 ZeroMemory(&mii, sizeof(mii));
1118 mii.cbSize = sizeof(mii);
1119 mii.fMask = MIIM_SUBMENU;
1121 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1123 ShellView_MergeViewMenu(This, mii.hSubMenu);
1126 /*add the items that should only be added if we have the focus*/
1127 if(SVUIA_ACTIVATE_FOCUS == uState)
1129 /*get the file menu so we can merge with it */
1130 ZeroMemory(&mii, sizeof(mii));
1131 mii.cbSize = sizeof(mii);
1132 mii.fMask = MIIM_SUBMENU;
1134 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1136 ShellView_MergeFileMenu(This, mii.hSubMenu);
1139 TRACE("-- before fnSetMenuSB\n");
1140 IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1143 This->uState = uState;
1148 /**********************************************************
1149 * ShellView_OnSetFocus()
1152 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1156 /* Tell the browser one of our windows has received the focus. This
1157 should always be done before merging menus (OnActivate merges the
1158 menus) if one of our windows has the focus.*/
1160 IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1161 ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1163 /* Set the focus to the listview */
1164 SetFocus(This->hWndList);
1166 /* Notify the ICommDlgBrowser interface */
1167 OnStateChange(This,CDBOSC_SETFOCUS);
1172 /**********************************************************
1173 * ShellView_OnKillFocus()
1175 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1177 TRACE("(%p) stub\n",This);
1179 ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1180 /* Notify the ICommDlgBrowser */
1181 OnStateChange(This,CDBOSC_KILLFOCUS);
1186 /**********************************************************
1187 * ShellView_OnCommand()
1190 * the CmdID's are the ones from the context menu
1192 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1194 TRACE("(%p)->(0x%08lx 0x%08lx %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1198 case FCIDM_SHVIEW_SMALLICON:
1199 This->FolderSettings.ViewMode = FVM_SMALLICON;
1200 SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1204 case FCIDM_SHVIEW_BIGICON:
1205 This->FolderSettings.ViewMode = FVM_ICON;
1206 SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1210 case FCIDM_SHVIEW_LISTVIEW:
1211 This->FolderSettings.ViewMode = FVM_LIST;
1212 SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1216 case FCIDM_SHVIEW_REPORTVIEW:
1217 This->FolderSettings.ViewMode = FVM_DETAILS;
1218 SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1222 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1227 This->ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30);
1228 This->ListViewSortInfo.bIsAscending = TRUE;
1229 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1230 ListView_SortItems(This->hWndList, ShellView_ListViewCompareItems, (LPARAM) (&(This->ListViewSortInfo)));
1234 TRACE("-- COMMAND 0x%04lx unhandled\n", dwCmdID);
1239 /**********************************************************
1240 * ShellView_OnNotify()
1243 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1244 { LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1245 NMLVDISPINFOA *lpdi = (NMLVDISPINFOA *)lpnmh;
1248 TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1253 TRACE("-- NM_SETFOCUS %p\n",This);
1254 ShellView_OnSetFocus(This);
1258 TRACE("-- NM_KILLFOCUS %p\n",This);
1259 ShellView_OnDeactivate(This);
1260 /* Notify the ICommDlgBrowser interface */
1261 OnStateChange(This,CDBOSC_KILLFOCUS);
1265 TRACE("-- NM_CUSTOMDRAW %p\n",This);
1266 return CDRF_DODEFAULT;
1268 case NM_RELEASEDCAPTURE:
1269 TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1273 TRACE("-- NM_CLICK %p\n",This);
1277 TRACE("-- NM_RCLICK %p\n",This);
1281 TRACE("-- NM_DBLCLK %p\n",This);
1282 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1286 TRACE("-- NM_DBLCLK %p\n",This);
1287 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1291 TRACE("-- HDN_ENDTRACKA %p\n",This);
1292 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1293 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1296 case LVN_DELETEITEM:
1297 TRACE("-- LVN_DELETEITEM %p\n",This);
1298 SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/
1301 case LVN_DELETEALLITEMS:
1302 TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1305 case LVN_INSERTITEM:
1306 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1309 case LVN_ITEMACTIVATE:
1310 TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1311 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1314 case LVN_COLUMNCLICK:
1315 This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1316 if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1318 This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1322 This->ListViewSortInfo.bIsAscending = TRUE;
1324 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1326 ListView_SortItems(lpnmlv->hdr.hwndFrom, ShellView_ListViewCompareItems, (LPARAM) (&(This->ListViewSortInfo)));
1329 case LVN_GETDISPINFOA:
1330 case LVN_GETDISPINFOW:
1331 TRACE("-- LVN_GETDISPINFO %p\n",This);
1332 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1334 if(lpdi->item.mask & LVIF_TEXT) /* text requested */
1336 if (This->pSF2Parent)
1339 IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1340 if (lpnmh->code == LVN_GETDISPINFOA)
1342 StrRetToStrNA( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1343 TRACE("-- text=%s\n",lpdi->item.pszText);
1345 else /* LVN_GETDISPINFOW */
1347 StrRetToStrNW( ((NMLVDISPINFOW *)lpdi)->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1348 TRACE("-- text=%s\n",debugstr_w((WCHAR*)(lpdi->item.pszText)));
1356 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1358 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1362 case LVN_ITEMCHANGED:
1363 TRACE("-- LVN_ITEMCHANGED %p\n",This);
1364 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1368 case LVN_BEGINRDRAG:
1369 TRACE("-- LVN_BEGINDRAG\n");
1371 if (ShellView_GetSelections(This))
1374 DWORD dwAttributes = SFGAO_CANLINK;
1375 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1377 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1379 IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource); /* own DropSource interface */
1381 if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1383 if (dwAttributes & SFGAO_CANLINK)
1385 dwEffect |= DROPEFFECT_LINK;
1392 DoDragDrop(pda, pds, dwEffect, &dwEffect);
1394 IDataObject_Release(pda);
1399 case LVN_BEGINLABELEDITA:
1401 DWORD dwAttr = SFGAO_CANRENAME;
1402 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1404 TRACE("-- LVN_BEGINLABELEDITA %p\n",This);
1406 IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1407 if (SFGAO_CANRENAME & dwAttr)
1414 case LVN_ENDLABELEDITA:
1416 TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1417 if (lpdi->item.pszText)
1420 WCHAR wszNewName[MAX_PATH];
1423 ZeroMemory(&lvItem, sizeof(LVITEMA));
1424 lvItem.iItem = lpdi->item.iItem;
1425 lvItem.mask = LVIF_PARAM;
1426 ListView_GetItemA(This->hWndList, &lvItem);
1428 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1429 if (!MultiByteToWideChar( CP_ACP, 0, lpdi->item.pszText, -1, wszNewName, MAX_PATH ))
1430 wszNewName[MAX_PATH-1] = 0;
1431 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, wszNewName, SHGDN_INFOLDER, &pidl);
1433 if(SUCCEEDED(hr) && pidl)
1435 lvItem.mask = LVIF_PARAM;
1436 lvItem.lParam = (LPARAM)pidl;
1437 ListView_SetItemA(This->hWndList, &lvItem);
1447 msg.hwnd = This->hWnd;
1448 msg.message = WM_KEYDOWN;
1449 msg.wParam = plvKeyDown->wVKey;
1454 LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1456 /* initiate a rename of the selected file or directory */
1457 if(plvKeyDown->wVKey == VK_F2)
1459 /* see how many files are selected */
1460 int i = ListView_GetSelectedCount(This->hWndList);
1462 /* get selected item */
1465 /* get selected item */
1466 i = ListView_GetNextItem(This->hWndList, -1,
1469 ListView_EnsureVisible(This->hWndList, i, 0);
1470 ListView_EditLabelA(This->hWndList, i);
1474 TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1476 else if(plvKeyDown->wVKey == VK_DELETE)
1481 LPITEMIDLIST* pItems;
1484 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1490 if(!(i = ListView_GetSelectedCount(This->hWndList)))
1493 /* allocate memory for the pidl array */
1494 pItems = HeapAlloc(GetProcessHeap(), 0,
1495 sizeof(LPITEMIDLIST) * i);
1497 /* retrieve all selected items */
1500 while(ListView_GetSelectedCount(This->hWndList) > i)
1502 /* get selected item */
1503 item_index = ListView_GetNextItem(This->hWndList,
1504 item_index, LVNI_SELECTED);
1505 item.iItem = item_index;
1506 item.mask |= LVIF_PARAM;
1507 ListView_GetItemA(This->hWndList, &item);
1510 pItems[i] = (LPITEMIDLIST)item.lParam;
1515 /* perform the item deletion */
1516 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1518 /* free pidl array memory */
1519 HeapFree(GetProcessHeap(), 0, pItems);
1522 /* Initiate a refresh */
1523 else if(plvKeyDown->wVKey == VK_F5)
1525 IShellView_Refresh((IShellView*)This);
1529 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1534 TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1540 /**********************************************************
1541 * ShellView_OnChange()
1544 static LRESULT ShellView_OnChange(IShellViewImpl * This, LPITEMIDLIST * Pidls, LONG wEventId)
1547 TRACE("(%p)(%p,%p,0x%08lx)\n", This, Pidls[0], Pidls[1], wEventId);
1552 LV_AddItem(This, Pidls[0]);
1556 LV_DeleteItem(This, Pidls[0]);
1558 case SHCNE_RENAMEFOLDER:
1559 case SHCNE_RENAMEITEM:
1560 LV_RenameItem(This, Pidls[0], Pidls[1]);
1562 case SHCNE_UPDATEITEM:
1567 /**********************************************************
1571 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1573 IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1574 LPCREATESTRUCTA lpcs;
1576 TRACE("(hwnd=%p msg=%x wparm=%x lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1581 lpcs = (LPCREATESTRUCTA)lParam;
1582 pThis = (IShellViewImpl*)(lpcs->lpCreateParams);
1583 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1584 pThis->hWnd = hWnd; /*set the window handle*/
1587 case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1588 case WM_SETFOCUS: return ShellView_OnSetFocus(pThis);
1589 case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis);
1590 case WM_CREATE: return ShellView_OnCreate(pThis);
1591 case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1592 case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1593 case WM_COMMAND: return ShellView_OnCommand(pThis,
1594 GET_WM_COMMAND_ID(wParam, lParam),
1595 GET_WM_COMMAND_CMD(wParam, lParam),
1596 GET_WM_COMMAND_HWND(wParam, lParam));
1597 case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (LPITEMIDLIST*)wParam, (LONG)lParam);
1599 case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1602 case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
1605 case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0);
1608 RevokeDragDrop(pThis->hWnd);
1609 SHChangeNotifyDeregister(pThis->hNotify);
1613 if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1614 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1619 return DefWindowProcA (hWnd, uMessage, wParam, lParam);
1621 /**********************************************************
1624 * The INTERFACE of the IShellView object
1627 **********************************************************
1628 * IShellView_QueryInterface
1630 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj)
1632 IShellViewImpl *This = (IShellViewImpl *)iface;
1634 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1638 if(IsEqualIID(riid, &IID_IUnknown))
1642 else if(IsEqualIID(riid, &IID_IShellView))
1644 *ppvObj = (IShellView*)This;
1646 else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1648 *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget);
1650 else if(IsEqualIID(riid, &IID_IDropTarget))
1652 *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
1654 else if(IsEqualIID(riid, &IID_IDropSource))
1656 *ppvObj = (IDropSource*)&(This->lpvtblDropSource);
1658 else if(IsEqualIID(riid, &IID_IViewObject))
1660 *ppvObj = (IViewObject*)&(This->lpvtblViewObject);
1665 IUnknown_AddRef( (IUnknown*)*ppvObj );
1666 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1669 TRACE("-- Interface: E_NOINTERFACE\n");
1670 return E_NOINTERFACE;
1673 /**********************************************************
1676 static ULONG WINAPI IShellView_fnAddRef(IShellView * iface)
1678 IShellViewImpl *This = (IShellViewImpl *)iface;
1679 ULONG refCount = InterlockedIncrement(&This->ref);
1681 TRACE("(%p)->(count=%lu)\n", This, refCount - 1);
1685 /**********************************************************
1686 * IShellView_Release
1688 static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
1690 IShellViewImpl *This = (IShellViewImpl *)iface;
1691 ULONG refCount = InterlockedDecrement(&This->ref);
1693 TRACE("(%p)->(count=%li)\n", This, refCount + 1);
1697 TRACE(" destroying IShellView(%p)\n",This);
1699 DestroyWindow(This->hWndList);
1702 IShellFolder_Release(This->pSFParent);
1704 if(This->pSF2Parent)
1705 IShellFolder2_Release(This->pSF2Parent);
1708 SHFree(This->apidl);
1711 IAdviseSink_Release(This->pAdvSink);
1713 HeapFree(GetProcessHeap(),0,This);
1718 /**********************************************************
1719 * ShellView_GetWindow
1721 static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd)
1723 IShellViewImpl *This = (IShellViewImpl *)iface;
1725 TRACE("(%p)\n",This);
1727 *phWnd = This->hWnd;
1732 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode)
1734 IShellViewImpl *This = (IShellViewImpl *)iface;
1736 FIXME("(%p) stub\n",This);
1741 /**********************************************************
1742 * IShellView_TranslateAccelerator
1745 * use the accel functions
1747 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg)
1750 IShellViewImpl *This = (IShellViewImpl *)iface;
1752 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%lx wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1755 if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1757 TRACE("-- key=0x04%x\n",lpmsg->wParam) ;
1759 return S_FALSE; /* not handled */
1762 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable)
1764 IShellViewImpl *This = (IShellViewImpl *)iface;
1766 FIXME("(%p) stub\n",This);
1771 static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState)
1773 IShellViewImpl *This = (IShellViewImpl *)iface;
1776 CHAR szName[MAX_PATH];
1779 int nPartArray[1] = {-1};
1781 TRACE("(%p)->(state=%x) stub\n",This, uState);
1783 /*don't do anything if the state isn't really changing*/
1784 if(This->uState == uState)
1789 /*OnActivate handles the menu merging and internal state*/
1790 ShellView_OnActivate(This, uState);
1792 /*only do This if we are active*/
1793 if(uState != SVUIA_DEACTIVATE)
1797 GetFolderPath is not a method of IShellFolder
1798 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1800 /* set the number of parts */
1801 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1802 (LPARAM)nPartArray, &lResult);
1804 /* set the text for the parts */
1806 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1807 0, (LPARAM)szName, &lResult);
1814 static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface)
1816 IShellViewImpl *This = (IShellViewImpl *)iface;
1818 TRACE("(%p)\n",This);
1820 ListView_DeleteAllItems(This->hWndList);
1821 ShellView_FillList(This);
1826 static HRESULT WINAPI IShellView_fnCreateViewWindow(
1828 IShellView *lpPrevView,
1829 LPCFOLDERSETTINGS lpfs,
1830 IShellBrowser * psb,
1834 IShellViewImpl *This = (IShellViewImpl *)iface;
1840 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd);
1841 TRACE("-- vmode=%x flags=%x left=%li top=%li right=%li bottom=%li\n",lpfs->ViewMode, lpfs->fFlags ,prcView->left,prcView->top, prcView->right, prcView->bottom);
1843 /*set up the member variables*/
1844 This->pShellBrowser = psb;
1845 This->FolderSettings = *lpfs;
1847 /*get our parent window*/
1848 IShellBrowser_AddRef(This->pShellBrowser);
1849 IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
1851 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1852 This->pCommDlgBrowser=NULL;
1853 if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser,
1854 (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser)))
1856 TRACE("-- CommDlgBrowser\n");
1859 /*if our window class has not been registered, then do so*/
1860 if(!GetClassInfoA(shell32_hInstance, SV_CLASS_NAME, &wc))
1862 ZeroMemory(&wc, sizeof(wc));
1863 wc.style = CS_HREDRAW | CS_VREDRAW;
1864 wc.lpfnWndProc = ShellView_WndProc;
1867 wc.hInstance = shell32_hInstance;
1869 wc.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
1870 wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
1871 wc.lpszMenuName = NULL;
1872 wc.lpszClassName = SV_CLASS_NAME;
1874 if(!RegisterClassA(&wc))
1878 *phWnd = CreateWindowExA(0,
1881 WS_CHILD | WS_TABSTOP,
1884 prcView->right - prcView->left,
1885 prcView->bottom - prcView->top,
1893 if(!*phWnd) return E_FAIL;
1895 SetWindowPos(*phWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
1896 UpdateWindow(*phWnd);
1901 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
1903 IShellViewImpl *This = (IShellViewImpl *)iface;
1905 TRACE("(%p)\n",This);
1907 /*Make absolutely sure all our UI is cleaned up.*/
1908 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1912 DestroyMenu(This->hMenu);
1915 DestroyWindow(This->hWnd);
1916 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1917 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1923 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs)
1925 IShellViewImpl *This = (IShellViewImpl *)iface;
1927 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1928 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1930 if (!lpfs) return E_INVALIDARG;
1932 *lpfs = This->FolderSettings;
1936 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1938 IShellViewImpl *This = (IShellViewImpl *)iface;
1940 FIXME("(%p) stub\n",This);
1945 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface)
1947 IShellViewImpl *This = (IShellViewImpl *)iface;
1949 FIXME("(%p) stub\n",This);
1954 static HRESULT WINAPI IShellView_fnSelectItem(
1959 IShellViewImpl *This = (IShellViewImpl *)iface;
1962 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
1964 i = LV_FindItemByPidl(This, pidl);
1970 if(uFlags & SVSI_ENSUREVISIBLE)
1971 ListView_EnsureVisible(This->hWndList, i, 0);
1973 ZeroMemory(&lvItem, sizeof(LVITEMA));
1974 lvItem.mask = LVIF_STATE;
1977 while(ListView_GetItemA(This->hWndList, &lvItem))
1979 if (lvItem.iItem == i)
1981 if (uFlags & SVSI_SELECT)
1982 lvItem.state |= LVIS_SELECTED;
1984 lvItem.state &= ~LVIS_SELECTED;
1986 if(uFlags & SVSI_FOCUSED)
1987 lvItem.state &= ~LVIS_FOCUSED;
1991 if (uFlags & SVSI_DESELECTOTHERS)
1992 lvItem.state &= ~LVIS_SELECTED;
1994 ListView_SetItemA(This->hWndList, &lvItem);
1999 if(uFlags & SVSI_EDIT)
2000 ListView_EditLabelA(This->hWndList, i);
2006 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
2008 IShellViewImpl *This = (IShellViewImpl *)iface;
2010 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2016 case SVGIO_BACKGROUND:
2017 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2020 case SVGIO_SELECTION:
2021 ShellView_GetSelections(This);
2022 IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2025 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2027 if(!*ppvOut) return E_OUTOFMEMORY;
2032 static const IShellViewVtbl svvt =
2034 IShellView_fnQueryInterface,
2035 IShellView_fnAddRef,
2036 IShellView_fnRelease,
2037 IShellView_fnGetWindow,
2038 IShellView_fnContextSensitiveHelp,
2039 IShellView_fnTranslateAccelerator,
2040 IShellView_fnEnableModeless,
2041 IShellView_fnUIActivate,
2042 IShellView_fnRefresh,
2043 IShellView_fnCreateViewWindow,
2044 IShellView_fnDestroyViewWindow,
2045 IShellView_fnGetCurrentInfo,
2046 IShellView_fnAddPropertySheetPages,
2047 IShellView_fnSaveViewState,
2048 IShellView_fnSelectItem,
2049 IShellView_fnGetItemObject
2053 /**********************************************************
2054 * ISVOleCmdTarget_QueryInterface (IUnknown)
2056 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2057 IOleCommandTarget * iface,
2061 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2063 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2066 /**********************************************************
2067 * ISVOleCmdTarget_AddRef (IUnknown)
2069 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2070 IOleCommandTarget * iface)
2072 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2074 return IShellFolder_AddRef((IShellFolder*)This);
2077 /**********************************************************
2078 * ISVOleCmdTarget_Release (IUnknown)
2080 static ULONG WINAPI ISVOleCmdTarget_Release(
2081 IOleCommandTarget * iface)
2083 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2085 return IShellFolder_Release((IShellFolder*)This);
2088 /**********************************************************
2089 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2091 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2092 IOleCommandTarget *iface,
2093 const GUID* pguidCmdGroup,
2096 OLECMDTEXT* pCmdText)
2099 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2101 FIXME("(%p)->(%p(%s) 0x%08lx %p %p\n",
2102 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2106 for (i = 0; i < cCmds; i++)
2108 FIXME("\tprgCmds[%d].cmdID = %ld\n", i, prgCmds[i].cmdID);
2109 prgCmds[i].cmdf = 0;
2111 return OLECMDERR_E_UNKNOWNGROUP;
2114 /**********************************************************
2115 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2117 * nCmdID is the OLECMDID_* enumeration
2119 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2120 IOleCommandTarget *iface,
2121 const GUID* pguidCmdGroup,
2127 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2129 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08lx Opt:0x%08lx %p %p)\n",
2130 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2132 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2134 (nCmdexecopt == 4) && pvaOut)
2136 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2141 return OLECMDERR_E_UNKNOWNGROUP;
2144 static const IOleCommandTargetVtbl ctvt =
2146 ISVOleCmdTarget_QueryInterface,
2147 ISVOleCmdTarget_AddRef,
2148 ISVOleCmdTarget_Release,
2149 ISVOleCmdTarget_QueryStatus,
2150 ISVOleCmdTarget_Exec
2153 /**********************************************************
2154 * ISVDropTarget implementation
2157 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2162 IShellViewImpl *This = impl_from_IDropTarget(iface);
2164 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2166 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2169 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2171 IShellViewImpl *This = impl_from_IDropTarget(iface);
2173 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2175 return IShellFolder_AddRef((IShellFolder*)This);
2178 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2180 IShellViewImpl *This = impl_from_IDropTarget(iface);
2182 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2184 return IShellFolder_Release((IShellFolder*)This);
2187 /******************************************************************************
2188 * drag_notify_subitem [Internal]
2190 * Figure out the shellfolder object, which is currently under the mouse cursor
2191 * and notify it via the IDropTarget interface.
2194 #define SCROLLAREAWIDTH 20
2196 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2199 LVHITTESTINFO htinfo;
2205 /* Map from global to client coordinates and query the index of the listview-item, which is
2206 * currently under the mouse cursor. */
2209 htinfo.flags = LVHT_ONITEM;
2210 ScreenToClient(This->hWndList, &htinfo.pt);
2211 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2213 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2214 GetClientRect(This->hWndList, &clientRect);
2215 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2216 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2217 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2219 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2220 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2221 if (htinfo.pt.x < SCROLLAREAWIDTH)
2222 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2223 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2224 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2225 if (htinfo.pt.y < SCROLLAREAWIDTH)
2226 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2227 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2228 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2231 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2233 This->ptLastMousePos = htinfo.pt;
2235 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2236 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2237 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2239 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2240 if (This->pCurDropTarget) {
2241 IDropTarget_DragLeave(This->pCurDropTarget);
2242 IDropTarget_Release(This->pCurDropTarget);
2243 This->pCurDropTarget = NULL;
2246 This->iDragOverItem = lResult;
2247 if (lResult == -1) {
2248 /* We are not above one of the listview's subitems. Bind to the parent folder's
2249 * DropTarget interface. */
2250 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2251 (LPVOID*)&This->pCurDropTarget);
2253 /* Query the relative PIDL of the shellfolder object represented by the currently
2254 * dragged over listview-item ... */
2255 ZeroMemory(&lvItem, sizeof(lvItem));
2256 lvItem.mask = LVIF_PARAM;
2257 lvItem.iItem = lResult;
2258 ListView_GetItemA(This->hWndList, &lvItem);
2260 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2261 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2262 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2265 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2269 /* Notify the item just entered via DragEnter. */
2270 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2273 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2274 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2276 IShellViewImpl *This = impl_from_IDropTarget(iface);
2278 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2279 This->pCurDataObject = pDataObject;
2280 IDataObject_AddRef(pDataObject);
2282 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2285 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2288 IShellViewImpl *This = impl_from_IDropTarget(iface);
2289 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2292 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2293 IShellViewImpl *This = impl_from_IDropTarget(iface);
2295 IDropTarget_DragLeave(This->pCurDropTarget);
2297 IDropTarget_Release(This->pCurDropTarget);
2298 IDataObject_Release(This->pCurDataObject);
2299 This->pCurDataObject = NULL;
2300 This->pCurDropTarget = NULL;
2301 This->iDragOverItem = 0;
2306 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2307 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2309 IShellViewImpl *This = impl_from_IDropTarget(iface);
2311 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2313 IDropTarget_Release(This->pCurDropTarget);
2314 IDataObject_Release(This->pCurDataObject);
2315 This->pCurDataObject = NULL;
2316 This->pCurDropTarget = NULL;
2317 This->iDragOverItem = 0;
2322 static const IDropTargetVtbl dtvt =
2324 ISVDropTarget_QueryInterface,
2325 ISVDropTarget_AddRef,
2326 ISVDropTarget_Release,
2327 ISVDropTarget_DragEnter,
2328 ISVDropTarget_DragOver,
2329 ISVDropTarget_DragLeave,
2333 /**********************************************************
2334 * ISVDropSource implementation
2337 static HRESULT WINAPI ISVDropSource_QueryInterface(
2342 IShellViewImpl *This = impl_from_IDropSource(iface);
2344 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2346 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2349 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2351 IShellViewImpl *This = impl_from_IDropSource(iface);
2353 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2355 return IShellFolder_AddRef((IShellFolder*)This);
2358 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2360 IShellViewImpl *This = impl_from_IDropSource(iface);
2362 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2364 return IShellFolder_Release((IShellFolder*)This);
2366 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2368 BOOL fEscapePressed,
2371 IShellViewImpl *This = impl_from_IDropSource(iface);
2372 TRACE("(%p)\n",This);
2375 return DRAGDROP_S_CANCEL;
2376 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2377 return DRAGDROP_S_DROP;
2382 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2386 IShellViewImpl *This = impl_from_IDropSource(iface);
2387 TRACE("(%p)\n",This);
2389 return DRAGDROP_S_USEDEFAULTCURSORS;
2392 static const IDropSourceVtbl dsvt =
2394 ISVDropSource_QueryInterface,
2395 ISVDropSource_AddRef,
2396 ISVDropSource_Release,
2397 ISVDropSource_QueryContinueDrag,
2398 ISVDropSource_GiveFeedback
2400 /**********************************************************
2401 * ISVViewObject implementation
2404 static HRESULT WINAPI ISVViewObject_QueryInterface(
2409 IShellViewImpl *This = impl_from_IViewObject(iface);
2411 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2413 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2416 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2418 IShellViewImpl *This = impl_from_IViewObject(iface);
2420 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2422 return IShellFolder_AddRef((IShellFolder*)This);
2425 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2427 IShellViewImpl *This = impl_from_IViewObject(iface);
2429 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2431 return IShellFolder_Release((IShellFolder*)This);
2434 static HRESULT WINAPI ISVViewObject_Draw(
2439 DVTARGETDEVICE* ptd,
2442 LPCRECTL lprcBounds,
2443 LPCRECTL lprcWBounds,
2444 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2445 ULONG_PTR dwContinue)
2448 IShellViewImpl *This = impl_from_IViewObject(iface);
2450 FIXME("Stub: This=%p\n",This);
2454 static HRESULT WINAPI ISVViewObject_GetColorSet(
2459 DVTARGETDEVICE* ptd,
2460 HDC hicTargetDevice,
2461 LOGPALETTE** ppColorSet)
2464 IShellViewImpl *This = impl_from_IViewObject(iface);
2466 FIXME("Stub: This=%p\n",This);
2470 static HRESULT WINAPI ISVViewObject_Freeze(
2478 IShellViewImpl *This = impl_from_IViewObject(iface);
2480 FIXME("Stub: This=%p\n",This);
2484 static HRESULT WINAPI ISVViewObject_Unfreeze(
2489 IShellViewImpl *This = impl_from_IViewObject(iface);
2491 FIXME("Stub: This=%p\n",This);
2495 static HRESULT WINAPI ISVViewObject_SetAdvise(
2499 IAdviseSink* pAdvSink)
2502 IShellViewImpl *This = impl_from_IViewObject(iface);
2504 FIXME("partial stub: %p %08lx %08lx %p\n",
2505 This, aspects, advf, pAdvSink);
2507 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2508 This->pAdvSink = pAdvSink;
2509 This->dwAspects = aspects;
2510 This->dwAdvf = advf;
2515 static HRESULT WINAPI ISVViewObject_GetAdvise(
2519 IAdviseSink** ppAdvSink)
2522 IShellViewImpl *This = impl_from_IViewObject(iface);
2524 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2525 This, pAspects, pAdvf, ppAdvSink);
2529 IAdviseSink_AddRef( This->pAdvSink );
2530 *ppAdvSink = This->pAdvSink;
2533 *pAspects = This->dwAspects;
2535 *pAdvf = This->dwAdvf;
2541 static const IViewObjectVtbl vovt =
2543 ISVViewObject_QueryInterface,
2544 ISVViewObject_AddRef,
2545 ISVViewObject_Release,
2547 ISVViewObject_GetColorSet,
2548 ISVViewObject_Freeze,
2549 ISVViewObject_Unfreeze,
2550 ISVViewObject_SetAdvise,
2551 ISVViewObject_GetAdvise