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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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);
71 static const WCHAR SV_CLASS_NAME[] = {'S','H','E','L','L','D','L','L','_','D','e','f','V','i','e','w',0};
77 }LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;
81 const IShellViewVtbl* lpVtbl;
83 const IOleCommandTargetVtbl* lpvtblOleCommandTarget;
84 const IDropTargetVtbl* lpvtblDropTarget;
85 const IDropSourceVtbl* lpvtblDropSource;
86 const IViewObjectVtbl* lpvtblViewObject;
87 IShellFolder* pSFParent;
88 IShellFolder2* pSF2Parent;
89 IShellBrowser* pShellBrowser;
90 ICommDlgBrowser* pCommDlgBrowser;
91 HWND hWnd; /* SHELLDLL_DefView */
92 HWND hWndList; /* ListView control */
94 FOLDERSETTINGS FolderSettings;
99 LISTVIEW_SORT_INFO ListViewSortInfo;
100 ULONG hNotify; /* change notification handle */
104 IAdviseSink *pAdvSink;
105 IDropTarget* pCurDropTarget; /* The sub-item, which is currently dragged over */
106 IDataObject* pCurDataObject; /* The dragged data-object */
107 LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */
108 UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
109 POINT ptLastMousePos; /* Mouse position at last DragOver call */
112 static const IShellViewVtbl svvt;
113 static const IOleCommandTargetVtbl ctvt;
114 static const IDropTargetVtbl dtvt;
115 static const IDropSourceVtbl dsvt;
116 static const IViewObjectVtbl vovt;
119 static inline IShellViewImpl *impl_from_IOleCommandTarget( IOleCommandTarget *iface )
121 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblOleCommandTarget));
124 static inline IShellViewImpl *impl_from_IDropTarget( IDropTarget *iface )
126 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropTarget));
129 static inline IShellViewImpl *impl_from_IDropSource( IDropSource *iface )
131 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropSource));
134 static inline IShellViewImpl *impl_from_IViewObject( IViewObject *iface )
136 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblViewObject));
139 /* ListView Header ID's */
140 #define LISTVIEW_COLUMN_NAME 0
141 #define LISTVIEW_COLUMN_SIZE 1
142 #define LISTVIEW_COLUMN_TYPE 2
143 #define LISTVIEW_COLUMN_TIME 3
144 #define LISTVIEW_COLUMN_ATTRIB 4
147 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
148 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
149 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
151 #define ID_LISTVIEW 1
153 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
156 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
157 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
158 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
161 Items merged into the toolbar and the filemenu
170 } MYTOOLINFO, *LPMYTOOLINFO;
172 static const MYTOOLINFO Tools[] =
174 { FCIDM_SHVIEW_BIGICON, 0, 0, IDS_VIEW_LARGE, TBSTATE_ENABLED, BTNS_BUTTON },
175 { FCIDM_SHVIEW_SMALLICON, 0, 0, IDS_VIEW_SMALL, TBSTATE_ENABLED, BTNS_BUTTON },
176 { FCIDM_SHVIEW_LISTVIEW, 0, 0, IDS_VIEW_LIST, TBSTATE_ENABLED, BTNS_BUTTON },
177 { FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON },
181 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
183 /**********************************************************
184 * IShellView_Constructor
186 IShellView * IShellView_Constructor( IShellFolder * pFolder)
187 { IShellViewImpl * sv;
188 sv=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellViewImpl));
191 sv->lpvtblOleCommandTarget=&ctvt;
192 sv->lpvtblDropTarget=&dtvt;
193 sv->lpvtblDropSource=&dsvt;
194 sv->lpvtblViewObject=&vovt;
196 sv->pSFParent = pFolder;
197 if(pFolder) IShellFolder_AddRef(pFolder);
198 IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent);
200 sv->pCurDropTarget = NULL;
201 sv->pCurDataObject = NULL;
202 sv->iDragOverItem = 0;
203 sv->cScrollDelay = 0;
204 sv->ptLastMousePos.x = 0;
205 sv->ptLastMousePos.y = 0;
207 TRACE("(%p)->(%p)\n",sv, pFolder);
208 return (IShellView *) sv;
211 /**********************************************************
213 * ##### helperfunctions for communication with ICommDlgBrowser #####
215 static BOOL IsInCommDlg(IShellViewImpl * This)
216 { return(This->pCommDlgBrowser != NULL);
219 static HRESULT IncludeObject(IShellViewImpl * This, LPCITEMIDLIST pidl)
223 if ( IsInCommDlg(This) )
225 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
226 ret = ICommDlgBrowser_IncludeObject(This->pCommDlgBrowser, (IShellView*)This, pidl);
227 TRACE("--0x%08x\n", ret);
232 static HRESULT OnDefaultCommand(IShellViewImpl * This)
234 HRESULT ret = S_FALSE;
236 if (IsInCommDlg(This))
238 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
239 ret = ICommDlgBrowser_OnDefaultCommand(This->pCommDlgBrowser, (IShellView*)This);
240 TRACE("-- returns %08x\n", ret);
245 static HRESULT OnStateChange(IShellViewImpl * This, UINT uFlags)
247 HRESULT ret = S_FALSE;
249 if (IsInCommDlg(This))
251 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
252 ret = ICommDlgBrowser_OnStateChange(This->pCommDlgBrowser, (IShellView*)This, uFlags);
257 /**********************************************************
258 * set the toolbar of the filedialog buttons
260 * - activates the buttons from the shellbrowser according to
263 static void CheckToolbar(IShellViewImpl * This)
269 if (IsInCommDlg(This))
271 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
272 FCIDM_TB_SMALLICON, (This->FolderSettings.ViewMode==FVM_LIST)? TRUE : FALSE, &result);
273 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
274 FCIDM_TB_REPORTVIEW, (This->FolderSettings.ViewMode==FVM_DETAILS)? TRUE : FALSE, &result);
275 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
276 FCIDM_TB_SMALLICON, TRUE, &result);
277 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
278 FCIDM_TB_REPORTVIEW, TRUE, &result);
282 /**********************************************************
284 * ##### helperfunctions for initializing the view #####
286 /**********************************************************
287 * change the style of the listview control
289 static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove)
293 TRACE("(%p)\n", This);
295 tmpstyle = GetWindowLongW(This->hWndList, GWL_STYLE);
296 SetWindowLongW(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
299 /**********************************************************
300 * ShellView_CreateList()
302 * - creates the list view window
304 static BOOL ShellView_CreateList (IShellViewImpl * This)
305 { DWORD dwStyle, dwExStyle;
309 dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
310 LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT | LVS_AUTOARRANGE;
311 dwExStyle = WS_EX_CLIENTEDGE;
313 switch (This->FolderSettings.ViewMode)
315 case FVM_ICON: dwStyle |= LVS_ICON; break;
316 case FVM_DETAILS: dwStyle |= LVS_REPORT; break;
317 case FVM_SMALLICON: dwStyle |= LVS_SMALLICON; break;
318 case FVM_LIST: dwStyle |= LVS_LIST; break;
319 default: dwStyle |= LVS_LIST; break;
322 if (This->FolderSettings.fFlags & FWF_AUTOARRANGE) dwStyle |= LVS_AUTOARRANGE;
323 if (This->FolderSettings.fFlags & FWF_DESKTOP)
324 This->FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
325 if (This->FolderSettings.fFlags & FWF_SINGLESEL) dwStyle |= LVS_SINGLESEL;
326 if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE)
327 dwExStyle &= ~WS_EX_CLIENTEDGE;
329 This->hWndList=CreateWindowExW( dwExStyle,
342 This->ListViewSortInfo.bIsAscending = TRUE;
343 This->ListViewSortInfo.nHeaderID = -1;
344 This->ListViewSortInfo.nLastHeaderID = -1;
346 if (This->FolderSettings.fFlags & FWF_DESKTOP) {
348 * FIXME: look at the registry value
349 * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
350 * and activate drop shadows if necessary
353 SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, CLR_NONE);
355 SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, GetSysColor(COLOR_DESKTOP));
357 SendMessageW(This->hWndList, LVM_SETTEXTCOLOR, 0, RGB(255,255,255));
360 /* UpdateShellSettings(); */
364 /**********************************************************
365 * ShellView_InitList()
367 * - adds all needed columns to the shellview
369 static BOOL ShellView_InitList(IShellViewImpl * This)
378 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
380 lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
381 lvColumn.pszText = szTemp;
383 if (This->pSF2Parent)
387 if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd)))
389 lvColumn.fmt = sd.fmt;
390 lvColumn.cx = sd.cxChar*8; /* chars->pixel */
391 StrRetToStrNW( szTemp, 50, &sd.str, NULL);
392 SendMessageW(This->hWndList, LVM_INSERTCOLUMNW, i, (LPARAM) &lvColumn);
400 SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ShellSmallIconList);
401 SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)ShellBigIconList);
405 /**********************************************************
406 * ShellView_CompareItems()
409 * internal, CALLBACK for DSA_Sort
411 static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
414 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
416 if(!lpData) return 0;
418 ret = (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2));
419 TRACE("ret=%i\n",ret);
423 /*************************************************************************
424 * ShellView_ListViewCompareItems
426 * Compare Function for the Listview (FileOpen Dialog)
429 * lParam1 [I] the first ItemIdList to compare with
430 * lParam2 [I] the second ItemIdList to compare with
431 * lpData [I] The column ID for the header Ctrl to process
434 * A negative value if the first item should precede the second,
435 * a positive value if the first item should follow the second,
436 * or zero if the two items are equivalent
439 * FIXME: function does what ShellView_CompareItems is supposed to do.
440 * unify it and figure out how to use the undocumented first parameter
441 * of IShellFolder_CompareIDs to do the job this function does and
442 * move this code to IShellFolder.
443 * make LISTVIEW_SORT_INFO obsolete
444 * the way this function works is only usable if we had only
445 * filesystemfolders (25/10/99 jsch)
447 static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
451 char strName1[MAX_PATH], strName2[MAX_PATH];
452 BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
453 LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1;
454 LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2;
455 LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData;
458 bIsFolder1 = _ILIsFolder(pItemIdList1);
459 bIsFolder2 = _ILIsFolder(pItemIdList2);
460 bIsBothFolder = bIsFolder1 && bIsFolder2;
462 /* When sorting between a File and a Folder, the Folder gets sorted first */
463 if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
465 nDiff = bIsFolder1 ? -1 : 1;
469 /* Sort by Time: Folders or Files can be sorted */
471 if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
473 _ILGetFileDateTime(pItemIdList1, &fd1);
474 _ILGetFileDateTime(pItemIdList2, &fd2);
475 nDiff = CompareFileTime(&fd2, &fd1);
477 /* Sort by Attribute: Folder or Files can be sorted */
478 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
480 _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH);
481 _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH);
482 nDiff = lstrcmpiA(strName1, strName2);
484 /* Sort by FileName: Folder or Files can be sorted */
485 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
488 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
489 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
490 nDiff = lstrcmpiA(strName1, strName2);
492 /* Sort by File Size, Only valid for Files */
493 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
495 nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0));
497 /* Sort by File Type, Only valid for Files */
498 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
501 _ILGetFileType(pItemIdList1, strName1, MAX_PATH);
502 _ILGetFileType(pItemIdList2, strName2, MAX_PATH);
503 nDiff = lstrcmpiA(strName1, strName2);
506 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
510 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
511 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
512 nDiff = lstrcmpiA(strName1, strName2);
515 if(!pSortInfo->bIsAscending)
524 /**********************************************************
525 * LV_FindItemByPidl()
527 static int LV_FindItemByPidl(
528 IShellViewImpl * This,
533 lvItem.mask = LVIF_PARAM;
534 for(lvItem.iItem = 0;
535 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
538 LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam;
539 HRESULT hr = IShellFolder_CompareIDs(This->pSFParent, 0, pidl, currentpidl);
540 if(SUCCEEDED(hr) && !HRESULT_CODE(hr))
548 /**********************************************************
551 static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
555 TRACE("(%p)(pidl=%p)\n", This, pidl);
557 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/
558 lvItem.iItem = ListView_GetItemCount(This->hWndList); /*add the item to the end of the list*/
560 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/
561 lvItem.pszText = LPSTR_TEXTCALLBACKW; /*get text on a callback basis*/
562 lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/
563 return (-1==ListView_InsertItemW(This->hWndList, &lvItem))? FALSE: TRUE;
566 /**********************************************************
569 static BOOLEAN LV_DeleteItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
573 TRACE("(%p)(pidl=%p)\n", This, pidl);
575 nIndex = LV_FindItemByPidl(This, ILFindLastID(pidl));
576 return (-1==ListView_DeleteItem(This->hWndList, nIndex))? FALSE: TRUE;
579 /**********************************************************
582 static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew )
587 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew);
589 nItem = LV_FindItemByPidl(This, ILFindLastID(pidlOld));
592 lvItem.mask = LVIF_PARAM; /* only the pidl */
593 lvItem.iItem = nItem;
594 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
596 SHFree((LPITEMIDLIST)lvItem.lParam);
597 lvItem.mask = LVIF_PARAM;
598 lvItem.iItem = nItem;
599 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */
600 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
601 SendMessageW(This->hWndList, LVM_UPDATE, nItem, 0);
602 return TRUE; /* FIXME: better handling */
606 /**********************************************************
607 * ShellView_FillList()
609 * - gets the objectlist from the shellfolder
611 * - fills the list into the view
614 static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg )
616 LPITEMIDLIST pidl = ptr;
617 IShellViewImpl *This = arg;
618 /* in a commdlg This works as a filemask*/
619 if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl);
624 static HRESULT ShellView_FillList(IShellViewImpl * This)
626 LPENUMIDLIST pEnumIDList;
634 /* get the itemlist from the shfolder*/
635 hRes = IShellFolder_EnumObjects(This->pSFParent,This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
643 /* create a pointer array */
644 hdpa = DPA_Create(16);
647 return(E_OUTOFMEMORY);
650 /* copy the items into the array*/
651 while((S_OK == IEnumIDList_Next(pEnumIDList,1, &pidl, &dwFetched)) && dwFetched)
653 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
660 DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent);
662 /*turn the listview's redrawing off*/
663 SendMessageA(This->hWndList, WM_SETREDRAW, FALSE, 0);
665 DPA_DestroyCallback( hdpa, fill_list, This );
667 /*turn the listview's redrawing back on and force it to draw*/
668 SendMessageA(This->hWndList, WM_SETREDRAW, TRUE, 0);
670 IEnumIDList_Release(pEnumIDList); /* destroy the list*/
675 /**********************************************************
676 * ShellView_OnCreate()
678 static LRESULT ShellView_OnCreate(IShellViewImpl * This)
681 SHChangeNotifyEntry ntreg;
682 IPersistFolder2 * ppf2 = NULL;
686 if(ShellView_CreateList(This))
688 if(ShellView_InitList(This))
690 ShellView_FillList(This);
694 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown*)&This->lpVtbl, &IID_IDropTarget, (LPVOID*)&pdt)))
696 RegisterDragDrop(This->hWnd, pdt);
697 IDropTarget_Release(pdt);
700 /* register for receiving notifications */
701 IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
704 IPersistFolder2_GetCurFolder(ppf2, (LPITEMIDLIST*)&ntreg.pidl);
705 ntreg.fRecursive = TRUE;
706 This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
707 SHFree((LPITEMIDLIST)ntreg.pidl);
708 IPersistFolder2_Release(ppf2);
711 This->hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel");
716 /**********************************************************
717 * #### Handling of the menus ####
720 /**********************************************************
721 * ShellView_BuildFileMenu()
723 static HMENU ShellView_BuildFileMenu(IShellViewImpl * This)
724 { WCHAR szText[MAX_PATH];
729 TRACE("(%p)\n",This);
731 hSubMenu = CreatePopupMenu();
733 { /*get the number of items in our global array*/
734 for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
736 /*add the menu items*/
737 for(i = 0; i < nTools; i++)
739 LoadStringW(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
741 ZeroMemory(&mii, sizeof(mii));
742 mii.cbSize = sizeof(mii);
743 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
745 if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
747 mii.fType = MFT_STRING;
748 mii.fState = MFS_ENABLED;
749 mii.dwTypeData = szText;
750 mii.wID = Tools[i].idCommand;
754 mii.fType = MFT_SEPARATOR;
756 /* tack This item onto the end of the menu */
757 InsertMenuItemW(hSubMenu, (UINT)-1, TRUE, &mii);
760 TRACE("-- return (menu=%p)\n",hSubMenu);
763 /**********************************************************
764 * ShellView_MergeFileMenu()
766 static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu)
767 { TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu);
770 { /*insert This item at the beginning of the menu */
771 _InsertMenuItem(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
772 _InsertMenuItem(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, "dummy45", MFS_ENABLED);
778 /**********************************************************
779 * ShellView_MergeViewMenu()
782 static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu)
784 TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
787 { /*add a separator at the correct position in the menu*/
789 static char view[] = "View";
791 _InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
793 ZeroMemory(&mii, sizeof(mii));
794 mii.cbSize = sizeof(mii);
795 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
796 mii.fType = MFT_STRING;
797 mii.dwTypeData = view;
798 mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
799 InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
803 /**********************************************************
804 * ShellView_GetSelections()
806 * - fills the this->apidl list with the selected objects
809 * number of selected items
811 static UINT ShellView_GetSelections(IShellViewImpl * This)
818 This->cidl = ListView_GetSelectedCount(This->hWndList);
819 This->apidl = (LPITEMIDLIST*)SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
821 TRACE("selected=%i\n", This->cidl);
825 TRACE("-- Items selected =%u\n", This->cidl);
827 lvItem.mask = LVIF_STATE | LVIF_PARAM;
828 lvItem.stateMask = LVIS_SELECTED;
832 while(ListView_GetItemW(This->hWndList, &lvItem) && (i < This->cidl))
834 if(lvItem.state & LVIS_SELECTED)
836 This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
838 TRACE("-- selected Item found\n");
847 /**********************************************************
848 * ShellView_OpenSelectedItems()
850 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
852 static UINT CF_IDLIST = 0;
854 IDataObject* selection;
858 LPCITEMIDLIST parent_pidl;
859 WCHAR parent_path[MAX_PATH];
860 LPCWSTR parent_dir = NULL;
864 if (0 == ShellView_GetSelections(This))
868 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
869 (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
870 0, (LPVOID *)&selection);
876 CF_IDLIST = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
878 fetc.cfFormat = CF_IDLIST;
880 fetc.dwAspect = DVASPECT_CONTENT;
882 fetc.tymed = TYMED_HGLOBAL;
884 hr = IDataObject_QueryGetData(selection, &fetc);
888 hr = IDataObject_GetData(selection, &fetc, &stgm);
892 pIDList = GlobalLock(stgm.u.hGlobal);
894 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
895 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &parent_pidl, &attribs);
896 if (SUCCEEDED(hr) && (attribs & SFGAO_FILESYSTEM) &&
897 SHGetPathFromIDListW(parent_pidl, parent_path))
899 parent_dir = parent_path;
902 for (i = pIDList->cidl; i > 0; --i)
906 pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
908 attribs = SFGAO_FOLDER;
909 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
911 if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
913 SHELLEXECUTEINFOW shexinfo;
915 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
916 shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */
917 shexinfo.hwnd = NULL;
918 shexinfo.lpVerb = NULL;
919 shexinfo.lpFile = NULL;
920 shexinfo.lpParameters = NULL;
921 shexinfo.lpDirectory = parent_dir;
922 shexinfo.nShow = SW_NORMAL;
923 shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
925 ShellExecuteExW(&shexinfo); /* Discard error/success info */
927 ILFree((LPITEMIDLIST)shexinfo.lpIDList);
931 GlobalUnlock(stgm.u.hGlobal);
932 ReleaseStgMedium(&stgm);
934 IDataObject_Release(selection);
939 /**********************************************************
940 * ShellView_DoContextMenu()
942 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
946 BOOL fExplore = FALSE;
948 LPCONTEXTMENU pContextMenu = NULL;
949 IContextMenu2 *pCM = NULL;
950 CMINVOKECOMMANDINFO cmi;
952 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
954 /* look, what's selected and create a context menu object of it*/
955 if( ShellView_GetSelections(This) )
957 IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
958 (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
962 TRACE("-- pContextMenu\n");
963 hMenu = CreatePopupMenu();
967 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
968 if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
970 TRACE("-- explore mode\n");
974 /* build the flags depending on what we can do with the selected item */
975 wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
977 /* let the ContextMenu merge its items in */
978 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
980 if (This->FolderSettings.fFlags & FWF_DESKTOP)
981 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
985 TRACE("-- get menu default command\n");
986 uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
990 TRACE("-- track popup\n");
991 uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
996 TRACE("-- uCommand=%u\n", uCommand);
997 if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
999 TRACE("-- dlg: OnDefaultCommand\n");
1000 if (OnDefaultCommand(This) != S_OK)
1002 ShellView_OpenSelectedItems(This);
1007 TRACE("-- explore -- invoke command\n");
1008 ZeroMemory(&cmi, sizeof(cmi));
1009 cmi.cbSize = sizeof(cmi);
1010 cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
1011 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1012 IContextMenu_InvokeCommand(pContextMenu, &cmi);
1019 IContextMenu_Release(pContextMenu);
1022 else /* background context menu */
1024 hMenu = CreatePopupMenu();
1026 pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
1027 IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1029 uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1032 TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1034 ZeroMemory(&cmi, sizeof(cmi));
1035 cmi.cbSize = sizeof(cmi);
1036 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1037 cmi.hwnd = This->hWndParent;
1038 IContextMenu2_InvokeCommand(pCM, &cmi);
1040 IContextMenu2_Release(pCM);
1044 /**********************************************************
1045 * ##### message handling #####
1048 /**********************************************************
1049 * ShellView_OnSize()
1051 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1053 TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1055 /*resize the ListView to fit our window*/
1058 MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1063 /**********************************************************
1064 * ShellView_OnDeactivate()
1069 static void ShellView_OnDeactivate(IShellViewImpl * This)
1073 if(This->uState != SVUIA_DEACTIVATE)
1077 IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1078 IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1079 DestroyMenu(This->hMenu);
1083 This->uState = SVUIA_DEACTIVATE;
1087 /**********************************************************
1088 * ShellView_OnActivate()
1090 static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState)
1091 { OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} };
1093 CHAR szText[MAX_PATH];
1095 TRACE("%p uState=%x\n",This,uState);
1097 /*don't do anything if the state isn't really changing */
1098 if(This->uState == uState)
1103 ShellView_OnDeactivate(This);
1105 /*only do This if we are active */
1106 if(uState != SVUIA_DEACTIVATE)
1108 /*merge the menus */
1109 This->hMenu = CreateMenu();
1113 IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1114 TRACE("-- after fnInsertMenusSB\n");
1116 /*build the top level menu get the menu item's text*/
1117 strcpy(szText,"dummy 31");
1119 ZeroMemory(&mii, sizeof(mii));
1120 mii.cbSize = sizeof(mii);
1121 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1122 mii.fType = MFT_STRING;
1123 mii.fState = MFS_ENABLED;
1124 mii.dwTypeData = szText;
1125 mii.hSubMenu = ShellView_BuildFileMenu(This);
1127 /*insert our menu into the menu bar*/
1130 InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1133 /*get the view menu so we can merge with it*/
1134 ZeroMemory(&mii, sizeof(mii));
1135 mii.cbSize = sizeof(mii);
1136 mii.fMask = MIIM_SUBMENU;
1138 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1140 ShellView_MergeViewMenu(This, mii.hSubMenu);
1143 /*add the items that should only be added if we have the focus*/
1144 if(SVUIA_ACTIVATE_FOCUS == uState)
1146 /*get the file menu so we can merge with it */
1147 ZeroMemory(&mii, sizeof(mii));
1148 mii.cbSize = sizeof(mii);
1149 mii.fMask = MIIM_SUBMENU;
1151 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1153 ShellView_MergeFileMenu(This, mii.hSubMenu);
1156 TRACE("-- before fnSetMenuSB\n");
1157 IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1160 This->uState = uState;
1165 /**********************************************************
1166 * ShellView_OnSetFocus()
1169 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1173 /* Tell the browser one of our windows has received the focus. This
1174 should always be done before merging menus (OnActivate merges the
1175 menus) if one of our windows has the focus.*/
1177 IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1178 ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1180 /* Set the focus to the listview */
1181 SetFocus(This->hWndList);
1183 /* Notify the ICommDlgBrowser interface */
1184 OnStateChange(This,CDBOSC_SETFOCUS);
1189 /**********************************************************
1190 * ShellView_OnKillFocus()
1192 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1194 TRACE("(%p) stub\n",This);
1196 ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1197 /* Notify the ICommDlgBrowser */
1198 OnStateChange(This,CDBOSC_KILLFOCUS);
1203 /**********************************************************
1204 * ShellView_OnCommand()
1207 * the CmdID's are the ones from the context menu
1209 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1211 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1215 case FCIDM_SHVIEW_SMALLICON:
1216 This->FolderSettings.ViewMode = FVM_SMALLICON;
1217 SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1221 case FCIDM_SHVIEW_BIGICON:
1222 This->FolderSettings.ViewMode = FVM_ICON;
1223 SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1227 case FCIDM_SHVIEW_LISTVIEW:
1228 This->FolderSettings.ViewMode = FVM_LIST;
1229 SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1233 case FCIDM_SHVIEW_REPORTVIEW:
1234 This->FolderSettings.ViewMode = FVM_DETAILS;
1235 SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1239 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1244 This->ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30);
1245 This->ListViewSortInfo.bIsAscending = TRUE;
1246 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1247 SendMessageA(This->hWndList, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1251 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID);
1256 /**********************************************************
1257 * ShellView_OnNotify()
1260 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1261 { LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1262 NMLVDISPINFOW *lpdi = (NMLVDISPINFOW *)lpnmh;
1265 TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1270 TRACE("-- NM_SETFOCUS %p\n",This);
1271 ShellView_OnSetFocus(This);
1275 TRACE("-- NM_KILLFOCUS %p\n",This);
1276 ShellView_OnDeactivate(This);
1277 /* Notify the ICommDlgBrowser interface */
1278 OnStateChange(This,CDBOSC_KILLFOCUS);
1282 TRACE("-- NM_CUSTOMDRAW %p\n",This);
1283 return CDRF_DODEFAULT;
1285 case NM_RELEASEDCAPTURE:
1286 TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1290 TRACE("-- NM_CLICK %p\n",This);
1294 TRACE("-- NM_RCLICK %p\n",This);
1298 TRACE("-- NM_DBLCLK %p\n",This);
1299 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1303 TRACE("-- NM_DBLCLK %p\n",This);
1304 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1308 TRACE("-- HDN_ENDTRACKW %p\n",This);
1309 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1310 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1313 case LVN_DELETEITEM:
1314 TRACE("-- LVN_DELETEITEM %p\n",This);
1315 SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/
1318 case LVN_DELETEALLITEMS:
1319 TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1322 case LVN_INSERTITEM:
1323 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1326 case LVN_ITEMACTIVATE:
1327 TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1328 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1331 case LVN_COLUMNCLICK:
1332 This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1333 if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1335 This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1339 This->ListViewSortInfo.bIsAscending = TRUE;
1341 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1343 SendMessageW(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1346 case LVN_GETDISPINFOA:
1347 case LVN_GETDISPINFOW:
1348 TRACE("-- LVN_GETDISPINFO %p\n",This);
1349 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1351 if(lpdi->item.mask & LVIF_TEXT) /* text requested */
1353 if (This->pSF2Parent)
1356 IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1357 if (lpnmh->code == LVN_GETDISPINFOA)
1359 /* shouldn't happen */
1360 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1361 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1362 TRACE("-- text=%s\n",lpdiA->item.pszText);
1364 else /* LVN_GETDISPINFOW */
1366 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1367 TRACE("-- text=%s\n",debugstr_w(lpdi->item.pszText));
1375 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1377 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1381 case LVN_ITEMCHANGED:
1382 TRACE("-- LVN_ITEMCHANGED %p\n",This);
1383 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1387 case LVN_BEGINRDRAG:
1388 TRACE("-- LVN_BEGINDRAG\n");
1390 if (ShellView_GetSelections(This))
1393 DWORD dwAttributes = SFGAO_CANLINK;
1394 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1396 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1398 IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource); /* own DropSource interface */
1400 if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1402 if (dwAttributes & SFGAO_CANLINK)
1404 dwEffect |= DROPEFFECT_LINK;
1411 DoDragDrop(pda, pds, dwEffect, &dwEffect);
1413 IDataObject_Release(pda);
1418 case LVN_BEGINLABELEDITW:
1420 DWORD dwAttr = SFGAO_CANRENAME;
1421 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1423 TRACE("-- LVN_BEGINLABELEDITA %p\n",This);
1425 IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1426 if (SFGAO_CANRENAME & dwAttr)
1433 case LVN_ENDLABELEDITW:
1435 TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1436 if (lpdi->item.pszText)
1441 lvItem.iItem = lpdi->item.iItem;
1442 lvItem.iSubItem = 0;
1443 lvItem.mask = LVIF_PARAM;
1444 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
1446 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1447 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidl);
1449 if(SUCCEEDED(hr) && pidl)
1451 lvItem.mask = LVIF_PARAM;
1452 lvItem.lParam = (LPARAM)pidl;
1453 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
1463 msg.hwnd = This->hWnd;
1464 msg.message = WM_KEYDOWN;
1465 msg.wParam = plvKeyDown->wVKey;
1470 LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1472 /* initiate a rename of the selected file or directory */
1473 if(plvKeyDown->wVKey == VK_F2)
1475 /* see how many files are selected */
1476 int i = ListView_GetSelectedCount(This->hWndList);
1478 /* get selected item */
1481 /* get selected item */
1482 i = ListView_GetNextItem(This->hWndList, -1,
1485 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1486 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
1490 TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1492 else if(plvKeyDown->wVKey == VK_DELETE)
1497 LPITEMIDLIST* pItems;
1500 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1506 if(!(i = ListView_GetSelectedCount(This->hWndList)))
1509 /* allocate memory for the pidl array */
1510 pItems = HeapAlloc(GetProcessHeap(), 0,
1511 sizeof(LPITEMIDLIST) * i);
1513 /* retrieve all selected items */
1516 while(ListView_GetSelectedCount(This->hWndList) > i)
1518 /* get selected item */
1519 item_index = ListView_GetNextItem(This->hWndList,
1520 item_index, LVNI_SELECTED);
1521 item.iItem = item_index;
1522 item.mask = LVIF_PARAM;
1523 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &item);
1526 pItems[i] = (LPITEMIDLIST)item.lParam;
1531 /* perform the item deletion */
1532 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1534 /* free pidl array memory */
1535 HeapFree(GetProcessHeap(), 0, pItems);
1538 /* Initiate a refresh */
1539 else if(plvKeyDown->wVKey == VK_F5)
1541 IShellView_Refresh((IShellView*)This);
1545 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1550 TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1556 /**********************************************************
1557 * ShellView_OnChange()
1560 static LRESULT ShellView_OnChange(IShellViewImpl * This, LPITEMIDLIST * Pidls, LONG wEventId)
1563 TRACE("(%p)(%p,%p,0x%08x)\n", This, Pidls[0], Pidls[1], wEventId);
1568 LV_AddItem(This, Pidls[0]);
1572 LV_DeleteItem(This, Pidls[0]);
1574 case SHCNE_RENAMEFOLDER:
1575 case SHCNE_RENAMEITEM:
1576 LV_RenameItem(This, Pidls[0], Pidls[1]);
1578 case SHCNE_UPDATEITEM:
1583 /**********************************************************
1587 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1589 IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1590 LPCREATESTRUCTW lpcs;
1592 TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1597 lpcs = (LPCREATESTRUCTW)lParam;
1598 pThis = (IShellViewImpl*)(lpcs->lpCreateParams);
1599 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1600 pThis->hWnd = hWnd; /*set the window handle*/
1603 case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1604 case WM_SETFOCUS: return ShellView_OnSetFocus(pThis);
1605 case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis);
1606 case WM_CREATE: return ShellView_OnCreate(pThis);
1607 case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1608 case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1609 case WM_COMMAND: return ShellView_OnCommand(pThis,
1610 GET_WM_COMMAND_ID(wParam, lParam),
1611 GET_WM_COMMAND_CMD(wParam, lParam),
1612 GET_WM_COMMAND_HWND(wParam, lParam));
1613 case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (LPITEMIDLIST*)wParam, (LONG)lParam);
1615 case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1618 case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
1621 case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0);
1624 RevokeDragDrop(pThis->hWnd);
1625 SHChangeNotifyDeregister(pThis->hNotify);
1629 if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1630 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1635 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
1637 /**********************************************************
1640 * The INTERFACE of the IShellView object
1643 **********************************************************
1644 * IShellView_QueryInterface
1646 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj)
1648 IShellViewImpl *This = (IShellViewImpl *)iface;
1650 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1654 if(IsEqualIID(riid, &IID_IUnknown))
1658 else if(IsEqualIID(riid, &IID_IShellView))
1660 *ppvObj = (IShellView*)This;
1662 else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1664 *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget);
1666 else if(IsEqualIID(riid, &IID_IDropTarget))
1668 *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
1670 else if(IsEqualIID(riid, &IID_IDropSource))
1672 *ppvObj = (IDropSource*)&(This->lpvtblDropSource);
1674 else if(IsEqualIID(riid, &IID_IViewObject))
1676 *ppvObj = (IViewObject*)&(This->lpvtblViewObject);
1681 IUnknown_AddRef( (IUnknown*)*ppvObj );
1682 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1685 TRACE("-- Interface: E_NOINTERFACE\n");
1686 return E_NOINTERFACE;
1689 /**********************************************************
1692 static ULONG WINAPI IShellView_fnAddRef(IShellView * iface)
1694 IShellViewImpl *This = (IShellViewImpl *)iface;
1695 ULONG refCount = InterlockedIncrement(&This->ref);
1697 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
1701 /**********************************************************
1702 * IShellView_Release
1704 static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
1706 IShellViewImpl *This = (IShellViewImpl *)iface;
1707 ULONG refCount = InterlockedDecrement(&This->ref);
1709 TRACE("(%p)->(count=%i)\n", This, refCount + 1);
1713 TRACE(" destroying IShellView(%p)\n",This);
1715 DestroyWindow(This->hWndList);
1718 IShellFolder_Release(This->pSFParent);
1720 if(This->pSF2Parent)
1721 IShellFolder2_Release(This->pSF2Parent);
1723 SHFree(This->apidl);
1726 IAdviseSink_Release(This->pAdvSink);
1728 HeapFree(GetProcessHeap(),0,This);
1733 /**********************************************************
1734 * ShellView_GetWindow
1736 static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd)
1738 IShellViewImpl *This = (IShellViewImpl *)iface;
1740 TRACE("(%p)\n",This);
1742 *phWnd = This->hWnd;
1747 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode)
1749 IShellViewImpl *This = (IShellViewImpl *)iface;
1751 FIXME("(%p) stub\n",This);
1756 /**********************************************************
1757 * IShellView_TranslateAccelerator
1760 * use the accel functions
1762 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg)
1765 IShellViewImpl *This = (IShellViewImpl *)iface;
1767 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1770 if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1772 TRACE("-- key=0x04%lx\n",lpmsg->wParam) ;
1774 return S_FALSE; /* not handled */
1777 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable)
1779 IShellViewImpl *This = (IShellViewImpl *)iface;
1781 FIXME("(%p) stub\n",This);
1786 static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState)
1788 IShellViewImpl *This = (IShellViewImpl *)iface;
1791 CHAR szName[MAX_PATH];
1794 int nPartArray[1] = {-1};
1796 TRACE("(%p)->(state=%x) stub\n",This, uState);
1798 /*don't do anything if the state isn't really changing*/
1799 if(This->uState == uState)
1804 /*OnActivate handles the menu merging and internal state*/
1805 ShellView_OnActivate(This, uState);
1807 /*only do This if we are active*/
1808 if(uState != SVUIA_DEACTIVATE)
1812 GetFolderPath is not a method of IShellFolder
1813 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1815 /* set the number of parts */
1816 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1817 (LPARAM)nPartArray, &lResult);
1819 /* set the text for the parts */
1821 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1822 0, (LPARAM)szName, &lResult);
1829 static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface)
1831 IShellViewImpl *This = (IShellViewImpl *)iface;
1833 TRACE("(%p)\n",This);
1835 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
1836 ShellView_FillList(This);
1841 static HRESULT WINAPI IShellView_fnCreateViewWindow(
1843 IShellView *lpPrevView,
1844 LPCFOLDERSETTINGS lpfs,
1845 IShellBrowser * psb,
1849 IShellViewImpl *This = (IShellViewImpl *)iface;
1855 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd);
1856 TRACE("-- vmode=%x flags=%x left=%i top=%i right=%i bottom=%i\n",lpfs->ViewMode, lpfs->fFlags ,prcView->left,prcView->top, prcView->right, prcView->bottom);
1858 /*set up the member variables*/
1859 This->pShellBrowser = psb;
1860 This->FolderSettings = *lpfs;
1862 /*get our parent window*/
1863 IShellBrowser_AddRef(This->pShellBrowser);
1864 IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
1866 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1867 This->pCommDlgBrowser=NULL;
1868 if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser,
1869 (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser)))
1871 TRACE("-- CommDlgBrowser\n");
1874 /*if our window class has not been registered, then do so*/
1875 if(!GetClassInfoW(shell32_hInstance, SV_CLASS_NAME, &wc))
1877 ZeroMemory(&wc, sizeof(wc));
1878 wc.style = CS_HREDRAW | CS_VREDRAW;
1879 wc.lpfnWndProc = ShellView_WndProc;
1882 wc.hInstance = shell32_hInstance;
1884 wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
1885 wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
1886 wc.lpszMenuName = NULL;
1887 wc.lpszClassName = SV_CLASS_NAME;
1889 if(!RegisterClassW(&wc))
1893 *phWnd = CreateWindowExW(0,
1896 WS_CHILD | WS_TABSTOP,
1899 prcView->right - prcView->left,
1900 prcView->bottom - prcView->top,
1908 if(!*phWnd) return E_FAIL;
1910 SetWindowPos(*phWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
1911 UpdateWindow(*phWnd);
1916 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
1918 IShellViewImpl *This = (IShellViewImpl *)iface;
1920 TRACE("(%p)\n",This);
1922 /*Make absolutely sure all our UI is cleaned up.*/
1923 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1927 DestroyMenu(This->hMenu);
1930 DestroyWindow(This->hWnd);
1931 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1932 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1938 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs)
1940 IShellViewImpl *This = (IShellViewImpl *)iface;
1942 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1943 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1945 if (!lpfs) return E_INVALIDARG;
1947 *lpfs = This->FolderSettings;
1951 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1953 IShellViewImpl *This = (IShellViewImpl *)iface;
1955 FIXME("(%p) stub\n",This);
1960 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface)
1962 IShellViewImpl *This = (IShellViewImpl *)iface;
1964 FIXME("(%p) stub\n",This);
1969 static HRESULT WINAPI IShellView_fnSelectItem(
1974 IShellViewImpl *This = (IShellViewImpl *)iface;
1977 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
1979 i = LV_FindItemByPidl(This, pidl);
1985 if(uFlags & SVSI_ENSUREVISIBLE)
1986 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1988 lvItem.mask = LVIF_STATE;
1989 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
1991 lvItem.iSubItem = 0;
1993 while(SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem))
1995 if (lvItem.iItem == i)
1997 if (uFlags & SVSI_SELECT)
1998 lvItem.state |= LVIS_SELECTED;
2000 lvItem.state &= ~LVIS_SELECTED;
2002 if(uFlags & SVSI_FOCUSED)
2003 lvItem.state &= ~LVIS_FOCUSED;
2007 if (uFlags & SVSI_DESELECTOTHERS)
2008 lvItem.state &= ~LVIS_SELECTED;
2010 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
2015 if(uFlags & SVSI_EDIT)
2016 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
2022 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
2024 IShellViewImpl *This = (IShellViewImpl *)iface;
2026 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2032 case SVGIO_BACKGROUND:
2033 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2036 case SVGIO_SELECTION:
2037 ShellView_GetSelections(This);
2038 IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2041 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2043 if(!*ppvOut) return E_OUTOFMEMORY;
2048 static const IShellViewVtbl svvt =
2050 IShellView_fnQueryInterface,
2051 IShellView_fnAddRef,
2052 IShellView_fnRelease,
2053 IShellView_fnGetWindow,
2054 IShellView_fnContextSensitiveHelp,
2055 IShellView_fnTranslateAccelerator,
2056 IShellView_fnEnableModeless,
2057 IShellView_fnUIActivate,
2058 IShellView_fnRefresh,
2059 IShellView_fnCreateViewWindow,
2060 IShellView_fnDestroyViewWindow,
2061 IShellView_fnGetCurrentInfo,
2062 IShellView_fnAddPropertySheetPages,
2063 IShellView_fnSaveViewState,
2064 IShellView_fnSelectItem,
2065 IShellView_fnGetItemObject
2069 /**********************************************************
2070 * ISVOleCmdTarget_QueryInterface (IUnknown)
2072 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2073 IOleCommandTarget * iface,
2077 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2079 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2082 /**********************************************************
2083 * ISVOleCmdTarget_AddRef (IUnknown)
2085 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2086 IOleCommandTarget * iface)
2088 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2090 return IShellFolder_AddRef((IShellFolder*)This);
2093 /**********************************************************
2094 * ISVOleCmdTarget_Release (IUnknown)
2096 static ULONG WINAPI ISVOleCmdTarget_Release(
2097 IOleCommandTarget * iface)
2099 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2101 return IShellFolder_Release((IShellFolder*)This);
2104 /**********************************************************
2105 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2107 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2108 IOleCommandTarget *iface,
2109 const GUID* pguidCmdGroup,
2112 OLECMDTEXT* pCmdText)
2115 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2117 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2118 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2122 for (i = 0; i < cCmds; i++)
2124 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2125 prgCmds[i].cmdf = 0;
2127 return OLECMDERR_E_UNKNOWNGROUP;
2130 /**********************************************************
2131 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2133 * nCmdID is the OLECMDID_* enumeration
2135 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2136 IOleCommandTarget *iface,
2137 const GUID* pguidCmdGroup,
2143 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2145 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2146 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2148 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2150 (nCmdexecopt == 4) && pvaOut)
2152 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2157 return OLECMDERR_E_UNKNOWNGROUP;
2160 static const IOleCommandTargetVtbl ctvt =
2162 ISVOleCmdTarget_QueryInterface,
2163 ISVOleCmdTarget_AddRef,
2164 ISVOleCmdTarget_Release,
2165 ISVOleCmdTarget_QueryStatus,
2166 ISVOleCmdTarget_Exec
2169 /**********************************************************
2170 * ISVDropTarget implementation
2173 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2178 IShellViewImpl *This = impl_from_IDropTarget(iface);
2180 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2182 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2185 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2187 IShellViewImpl *This = impl_from_IDropTarget(iface);
2189 TRACE("(%p)->(count=%u)\n",This,This->ref);
2191 return IShellFolder_AddRef((IShellFolder*)This);
2194 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2196 IShellViewImpl *This = impl_from_IDropTarget(iface);
2198 TRACE("(%p)->(count=%u)\n",This,This->ref);
2200 return IShellFolder_Release((IShellFolder*)This);
2203 /******************************************************************************
2204 * drag_notify_subitem [Internal]
2206 * Figure out the shellfolder object, which is currently under the mouse cursor
2207 * and notify it via the IDropTarget interface.
2210 #define SCROLLAREAWIDTH 20
2212 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2215 LVHITTESTINFO htinfo;
2221 /* Map from global to client coordinates and query the index of the listview-item, which is
2222 * currently under the mouse cursor. */
2225 htinfo.flags = LVHT_ONITEM;
2226 ScreenToClient(This->hWndList, &htinfo.pt);
2227 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2229 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2230 GetClientRect(This->hWndList, &clientRect);
2231 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2232 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2233 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2235 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2236 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2237 if (htinfo.pt.x < SCROLLAREAWIDTH)
2238 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2239 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2240 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2241 if (htinfo.pt.y < SCROLLAREAWIDTH)
2242 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2243 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2244 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2247 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2249 This->ptLastMousePos = htinfo.pt;
2251 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2252 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2253 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2255 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2256 if (This->pCurDropTarget) {
2257 IDropTarget_DragLeave(This->pCurDropTarget);
2258 IDropTarget_Release(This->pCurDropTarget);
2259 This->pCurDropTarget = NULL;
2262 This->iDragOverItem = lResult;
2263 if (lResult == -1) {
2264 /* We are not above one of the listview's subitems. Bind to the parent folder's
2265 * DropTarget interface. */
2266 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2267 (LPVOID*)&This->pCurDropTarget);
2269 /* Query the relative PIDL of the shellfolder object represented by the currently
2270 * dragged over listview-item ... */
2271 lvItem.mask = LVIF_PARAM;
2272 lvItem.iItem = lResult;
2273 lvItem.iSubItem = 0;
2274 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
2276 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2277 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2278 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2281 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2285 /* Notify the item just entered via DragEnter. */
2286 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2289 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2290 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2292 IShellViewImpl *This = impl_from_IDropTarget(iface);
2294 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2295 This->pCurDataObject = pDataObject;
2296 IDataObject_AddRef(pDataObject);
2298 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2301 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2304 IShellViewImpl *This = impl_from_IDropTarget(iface);
2305 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2308 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2309 IShellViewImpl *This = impl_from_IDropTarget(iface);
2311 IDropTarget_DragLeave(This->pCurDropTarget);
2313 IDropTarget_Release(This->pCurDropTarget);
2314 IDataObject_Release(This->pCurDataObject);
2315 This->pCurDataObject = NULL;
2316 This->pCurDropTarget = NULL;
2317 This->iDragOverItem = 0;
2322 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2323 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2325 IShellViewImpl *This = impl_from_IDropTarget(iface);
2327 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2329 IDropTarget_Release(This->pCurDropTarget);
2330 IDataObject_Release(This->pCurDataObject);
2331 This->pCurDataObject = NULL;
2332 This->pCurDropTarget = NULL;
2333 This->iDragOverItem = 0;
2338 static const IDropTargetVtbl dtvt =
2340 ISVDropTarget_QueryInterface,
2341 ISVDropTarget_AddRef,
2342 ISVDropTarget_Release,
2343 ISVDropTarget_DragEnter,
2344 ISVDropTarget_DragOver,
2345 ISVDropTarget_DragLeave,
2349 /**********************************************************
2350 * ISVDropSource implementation
2353 static HRESULT WINAPI ISVDropSource_QueryInterface(
2358 IShellViewImpl *This = impl_from_IDropSource(iface);
2360 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2362 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2365 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2367 IShellViewImpl *This = impl_from_IDropSource(iface);
2369 TRACE("(%p)->(count=%u)\n",This,This->ref);
2371 return IShellFolder_AddRef((IShellFolder*)This);
2374 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2376 IShellViewImpl *This = impl_from_IDropSource(iface);
2378 TRACE("(%p)->(count=%u)\n",This,This->ref);
2380 return IShellFolder_Release((IShellFolder*)This);
2382 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2384 BOOL fEscapePressed,
2387 IShellViewImpl *This = impl_from_IDropSource(iface);
2388 TRACE("(%p)\n",This);
2391 return DRAGDROP_S_CANCEL;
2392 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2393 return DRAGDROP_S_DROP;
2398 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2402 IShellViewImpl *This = impl_from_IDropSource(iface);
2403 TRACE("(%p)\n",This);
2405 return DRAGDROP_S_USEDEFAULTCURSORS;
2408 static const IDropSourceVtbl dsvt =
2410 ISVDropSource_QueryInterface,
2411 ISVDropSource_AddRef,
2412 ISVDropSource_Release,
2413 ISVDropSource_QueryContinueDrag,
2414 ISVDropSource_GiveFeedback
2416 /**********************************************************
2417 * ISVViewObject implementation
2420 static HRESULT WINAPI ISVViewObject_QueryInterface(
2425 IShellViewImpl *This = impl_from_IViewObject(iface);
2427 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2429 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2432 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2434 IShellViewImpl *This = impl_from_IViewObject(iface);
2436 TRACE("(%p)->(count=%u)\n",This,This->ref);
2438 return IShellFolder_AddRef((IShellFolder*)This);
2441 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2443 IShellViewImpl *This = impl_from_IViewObject(iface);
2445 TRACE("(%p)->(count=%u)\n",This,This->ref);
2447 return IShellFolder_Release((IShellFolder*)This);
2450 static HRESULT WINAPI ISVViewObject_Draw(
2455 DVTARGETDEVICE* ptd,
2458 LPCRECTL lprcBounds,
2459 LPCRECTL lprcWBounds,
2460 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2461 ULONG_PTR dwContinue)
2464 IShellViewImpl *This = impl_from_IViewObject(iface);
2466 FIXME("Stub: This=%p\n",This);
2470 static HRESULT WINAPI ISVViewObject_GetColorSet(
2475 DVTARGETDEVICE* ptd,
2476 HDC hicTargetDevice,
2477 LOGPALETTE** ppColorSet)
2480 IShellViewImpl *This = impl_from_IViewObject(iface);
2482 FIXME("Stub: This=%p\n",This);
2486 static HRESULT WINAPI ISVViewObject_Freeze(
2494 IShellViewImpl *This = impl_from_IViewObject(iface);
2496 FIXME("Stub: This=%p\n",This);
2500 static HRESULT WINAPI ISVViewObject_Unfreeze(
2505 IShellViewImpl *This = impl_from_IViewObject(iface);
2507 FIXME("Stub: This=%p\n",This);
2511 static HRESULT WINAPI ISVViewObject_SetAdvise(
2515 IAdviseSink* pAdvSink)
2518 IShellViewImpl *This = impl_from_IViewObject(iface);
2520 FIXME("partial stub: %p %08x %08x %p\n",
2521 This, aspects, advf, pAdvSink);
2523 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2524 This->pAdvSink = pAdvSink;
2525 This->dwAspects = aspects;
2526 This->dwAdvf = advf;
2531 static HRESULT WINAPI ISVViewObject_GetAdvise(
2535 IAdviseSink** ppAdvSink)
2538 IShellViewImpl *This = impl_from_IViewObject(iface);
2540 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2541 This, pAspects, pAdvf, ppAdvSink);
2545 IAdviseSink_AddRef( This->pAdvSink );
2546 *ppAdvSink = This->pAdvSink;
2549 *pAspects = This->dwAspects;
2551 *pAdvf = This->dwAdvf;
2557 static const IViewObjectVtbl vovt =
2559 ISVViewObject_QueryInterface,
2560 ISVViewObject_AddRef,
2561 ISVViewObject_Release,
2563 ISVViewObject_GetColorSet,
2564 ISVViewObject_Freeze,
2565 ISVViewObject_Unfreeze,
2566 ISVViewObject_SetAdvise,
2567 ISVViewObject_GetAdvise