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 */
773 mii.cbSize = sizeof(mii);
774 mii.fMask = MIIM_ID | MIIM_TYPE;
776 mii.fType = MFT_SEPARATOR;
777 InsertMenuItemA(hSubMenu, 0, TRUE, &mii);
779 mii.cbSize = sizeof(mii);
780 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
781 mii.dwTypeData = (LPSTR)"dummy45";
782 mii.fState = MFS_ENABLED;
783 mii.wID = IDM_MYFILEITEM;
784 mii.fType = MFT_STRING;
785 InsertMenuItemA(hSubMenu, 0, TRUE, &mii);
790 /**********************************************************
791 * ShellView_MergeViewMenu()
794 static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu)
796 TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
799 { /*add a separator at the correct position in the menu*/
801 static char view[] = "View";
803 ZeroMemory(&mii, sizeof(mii));
804 mii.cbSize = sizeof(mii);
805 mii.fMask = MIIM_ID | MIIM_TYPE;
807 mii.fType = MFT_SEPARATOR;
808 InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
810 mii.cbSize = sizeof(mii);
811 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
812 mii.fType = MFT_STRING;
813 mii.dwTypeData = view;
814 mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
815 InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
819 /**********************************************************
820 * ShellView_GetSelections()
822 * - fills the this->apidl list with the selected objects
825 * number of selected items
827 static UINT ShellView_GetSelections(IShellViewImpl * This)
834 This->cidl = ListView_GetSelectedCount(This->hWndList);
835 This->apidl = (LPITEMIDLIST*)SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
837 TRACE("selected=%i\n", This->cidl);
841 TRACE("-- Items selected =%u\n", This->cidl);
843 lvItem.mask = LVIF_STATE | LVIF_PARAM;
844 lvItem.stateMask = LVIS_SELECTED;
848 while(ListView_GetItemW(This->hWndList, &lvItem) && (i < This->cidl))
850 if(lvItem.state & LVIS_SELECTED)
852 This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
854 TRACE("-- selected Item found\n");
863 /**********************************************************
864 * ShellView_OpenSelectedItems()
866 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
868 static UINT CF_IDLIST = 0;
870 IDataObject* selection;
874 LPCITEMIDLIST parent_pidl;
875 WCHAR parent_path[MAX_PATH];
876 LPCWSTR parent_dir = NULL;
880 if (0 == ShellView_GetSelections(This))
884 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
885 (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
886 0, (LPVOID *)&selection);
892 CF_IDLIST = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
894 fetc.cfFormat = CF_IDLIST;
896 fetc.dwAspect = DVASPECT_CONTENT;
898 fetc.tymed = TYMED_HGLOBAL;
900 hr = IDataObject_QueryGetData(selection, &fetc);
904 hr = IDataObject_GetData(selection, &fetc, &stgm);
908 pIDList = GlobalLock(stgm.u.hGlobal);
910 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
911 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &parent_pidl, &attribs);
912 if (SUCCEEDED(hr) && (attribs & SFGAO_FILESYSTEM) &&
913 SHGetPathFromIDListW(parent_pidl, parent_path))
915 parent_dir = parent_path;
918 for (i = pIDList->cidl; i > 0; --i)
922 pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
924 attribs = SFGAO_FOLDER;
925 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
927 if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
929 SHELLEXECUTEINFOW shexinfo;
931 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
932 shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */
933 shexinfo.hwnd = NULL;
934 shexinfo.lpVerb = NULL;
935 shexinfo.lpFile = NULL;
936 shexinfo.lpParameters = NULL;
937 shexinfo.lpDirectory = parent_dir;
938 shexinfo.nShow = SW_NORMAL;
939 shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
941 ShellExecuteExW(&shexinfo); /* Discard error/success info */
943 ILFree((LPITEMIDLIST)shexinfo.lpIDList);
947 GlobalUnlock(stgm.u.hGlobal);
948 ReleaseStgMedium(&stgm);
950 IDataObject_Release(selection);
955 /**********************************************************
956 * ShellView_DoContextMenu()
958 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
962 BOOL fExplore = FALSE;
964 LPCONTEXTMENU pContextMenu = NULL;
965 IContextMenu2 *pCM = NULL;
966 CMINVOKECOMMANDINFO cmi;
968 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
970 /* look, what's selected and create a context menu object of it*/
971 if( ShellView_GetSelections(This) )
973 IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
974 (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
978 TRACE("-- pContextMenu\n");
979 hMenu = CreatePopupMenu();
983 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
984 if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
986 TRACE("-- explore mode\n");
990 /* build the flags depending on what we can do with the selected item */
991 wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
993 /* let the ContextMenu merge its items in */
994 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
996 if (This->FolderSettings.fFlags & FWF_DESKTOP)
997 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
1001 TRACE("-- get menu default command\n");
1002 uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
1006 TRACE("-- track popup\n");
1007 uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1012 TRACE("-- uCommand=%u\n", uCommand);
1013 if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
1015 TRACE("-- dlg: OnDefaultCommand\n");
1016 if (OnDefaultCommand(This) != S_OK)
1018 ShellView_OpenSelectedItems(This);
1023 TRACE("-- explore -- invoke command\n");
1024 ZeroMemory(&cmi, sizeof(cmi));
1025 cmi.cbSize = sizeof(cmi);
1026 cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
1027 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1028 IContextMenu_InvokeCommand(pContextMenu, &cmi);
1035 IContextMenu_Release(pContextMenu);
1038 else /* background context menu */
1040 hMenu = CreatePopupMenu();
1042 pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
1043 IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1045 uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1048 TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1050 ZeroMemory(&cmi, sizeof(cmi));
1051 cmi.cbSize = sizeof(cmi);
1052 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1053 cmi.hwnd = This->hWndParent;
1054 IContextMenu2_InvokeCommand(pCM, &cmi);
1056 IContextMenu2_Release(pCM);
1060 /**********************************************************
1061 * ##### message handling #####
1064 /**********************************************************
1065 * ShellView_OnSize()
1067 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1069 TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1071 /*resize the ListView to fit our window*/
1074 MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1079 /**********************************************************
1080 * ShellView_OnDeactivate()
1085 static void ShellView_OnDeactivate(IShellViewImpl * This)
1089 if(This->uState != SVUIA_DEACTIVATE)
1093 IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1094 IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1095 DestroyMenu(This->hMenu);
1099 This->uState = SVUIA_DEACTIVATE;
1103 /**********************************************************
1104 * ShellView_OnActivate()
1106 static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState)
1107 { OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} };
1109 CHAR szText[MAX_PATH];
1111 TRACE("%p uState=%x\n",This,uState);
1113 /*don't do anything if the state isn't really changing */
1114 if(This->uState == uState)
1119 ShellView_OnDeactivate(This);
1121 /*only do This if we are active */
1122 if(uState != SVUIA_DEACTIVATE)
1124 /*merge the menus */
1125 This->hMenu = CreateMenu();
1129 IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1130 TRACE("-- after fnInsertMenusSB\n");
1132 /*build the top level menu get the menu item's text*/
1133 strcpy(szText,"dummy 31");
1135 ZeroMemory(&mii, sizeof(mii));
1136 mii.cbSize = sizeof(mii);
1137 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1138 mii.fType = MFT_STRING;
1139 mii.fState = MFS_ENABLED;
1140 mii.dwTypeData = szText;
1141 mii.hSubMenu = ShellView_BuildFileMenu(This);
1143 /*insert our menu into the menu bar*/
1146 InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1149 /*get the view menu so we can merge with it*/
1150 ZeroMemory(&mii, sizeof(mii));
1151 mii.cbSize = sizeof(mii);
1152 mii.fMask = MIIM_SUBMENU;
1154 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1156 ShellView_MergeViewMenu(This, mii.hSubMenu);
1159 /*add the items that should only be added if we have the focus*/
1160 if(SVUIA_ACTIVATE_FOCUS == uState)
1162 /*get the file menu so we can merge with it */
1163 ZeroMemory(&mii, sizeof(mii));
1164 mii.cbSize = sizeof(mii);
1165 mii.fMask = MIIM_SUBMENU;
1167 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1169 ShellView_MergeFileMenu(This, mii.hSubMenu);
1172 TRACE("-- before fnSetMenuSB\n");
1173 IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1176 This->uState = uState;
1181 /**********************************************************
1182 * ShellView_OnSetFocus()
1185 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1189 /* Tell the browser one of our windows has received the focus. This
1190 should always be done before merging menus (OnActivate merges the
1191 menus) if one of our windows has the focus.*/
1193 IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1194 ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1196 /* Set the focus to the listview */
1197 SetFocus(This->hWndList);
1199 /* Notify the ICommDlgBrowser interface */
1200 OnStateChange(This,CDBOSC_SETFOCUS);
1205 /**********************************************************
1206 * ShellView_OnKillFocus()
1208 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1210 TRACE("(%p) stub\n",This);
1212 ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1213 /* Notify the ICommDlgBrowser */
1214 OnStateChange(This,CDBOSC_KILLFOCUS);
1219 /**********************************************************
1220 * ShellView_OnCommand()
1223 * the CmdID's are the ones from the context menu
1225 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1227 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1231 case FCIDM_SHVIEW_SMALLICON:
1232 This->FolderSettings.ViewMode = FVM_SMALLICON;
1233 SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1237 case FCIDM_SHVIEW_BIGICON:
1238 This->FolderSettings.ViewMode = FVM_ICON;
1239 SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1243 case FCIDM_SHVIEW_LISTVIEW:
1244 This->FolderSettings.ViewMode = FVM_LIST;
1245 SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1249 case FCIDM_SHVIEW_REPORTVIEW:
1250 This->FolderSettings.ViewMode = FVM_DETAILS;
1251 SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1255 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1260 This->ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30);
1261 This->ListViewSortInfo.bIsAscending = TRUE;
1262 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1263 SendMessageA(This->hWndList, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1267 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID);
1272 /**********************************************************
1273 * ShellView_OnNotify()
1276 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1277 { LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1278 NMLVDISPINFOW *lpdi = (NMLVDISPINFOW *)lpnmh;
1281 TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1286 TRACE("-- NM_SETFOCUS %p\n",This);
1287 ShellView_OnSetFocus(This);
1291 TRACE("-- NM_KILLFOCUS %p\n",This);
1292 ShellView_OnDeactivate(This);
1293 /* Notify the ICommDlgBrowser interface */
1294 OnStateChange(This,CDBOSC_KILLFOCUS);
1298 TRACE("-- NM_CUSTOMDRAW %p\n",This);
1299 return CDRF_DODEFAULT;
1301 case NM_RELEASEDCAPTURE:
1302 TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1306 TRACE("-- NM_CLICK %p\n",This);
1310 TRACE("-- NM_RCLICK %p\n",This);
1314 TRACE("-- NM_DBLCLK %p\n",This);
1315 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1319 TRACE("-- NM_DBLCLK %p\n",This);
1320 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1324 TRACE("-- HDN_ENDTRACKW %p\n",This);
1325 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1326 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1329 case LVN_DELETEITEM:
1330 TRACE("-- LVN_DELETEITEM %p\n",This);
1331 SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/
1334 case LVN_DELETEALLITEMS:
1335 TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1338 case LVN_INSERTITEM:
1339 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1342 case LVN_ITEMACTIVATE:
1343 TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1344 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1347 case LVN_COLUMNCLICK:
1348 This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1349 if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1351 This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1355 This->ListViewSortInfo.bIsAscending = TRUE;
1357 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1359 SendMessageW(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1362 case LVN_GETDISPINFOA:
1363 case LVN_GETDISPINFOW:
1364 TRACE("-- LVN_GETDISPINFO %p\n",This);
1365 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1367 if(lpdi->item.mask & LVIF_TEXT) /* text requested */
1369 if (This->pSF2Parent)
1372 IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1373 if (lpnmh->code == LVN_GETDISPINFOA)
1375 /* shouldn't happen */
1376 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1377 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1378 TRACE("-- text=%s\n",lpdiA->item.pszText);
1380 else /* LVN_GETDISPINFOW */
1382 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1383 TRACE("-- text=%s\n",debugstr_w(lpdi->item.pszText));
1391 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1393 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1397 case LVN_ITEMCHANGED:
1398 TRACE("-- LVN_ITEMCHANGED %p\n",This);
1399 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1403 case LVN_BEGINRDRAG:
1404 TRACE("-- LVN_BEGINDRAG\n");
1406 if (ShellView_GetSelections(This))
1409 DWORD dwAttributes = SFGAO_CANLINK;
1410 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1412 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1414 IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource); /* own DropSource interface */
1416 if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1418 if (dwAttributes & SFGAO_CANLINK)
1420 dwEffect |= DROPEFFECT_LINK;
1427 DoDragDrop(pda, pds, dwEffect, &dwEffect);
1429 IDataObject_Release(pda);
1434 case LVN_BEGINLABELEDITW:
1436 DWORD dwAttr = SFGAO_CANRENAME;
1437 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1439 TRACE("-- LVN_BEGINLABELEDITA %p\n",This);
1441 IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1442 if (SFGAO_CANRENAME & dwAttr)
1449 case LVN_ENDLABELEDITW:
1451 TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1452 if (lpdi->item.pszText)
1457 lvItem.iItem = lpdi->item.iItem;
1458 lvItem.iSubItem = 0;
1459 lvItem.mask = LVIF_PARAM;
1460 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
1462 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1463 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidl);
1465 if(SUCCEEDED(hr) && pidl)
1467 lvItem.mask = LVIF_PARAM;
1468 lvItem.lParam = (LPARAM)pidl;
1469 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
1479 msg.hwnd = This->hWnd;
1480 msg.message = WM_KEYDOWN;
1481 msg.wParam = plvKeyDown->wVKey;
1486 LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1488 /* initiate a rename of the selected file or directory */
1489 if(plvKeyDown->wVKey == VK_F2)
1491 /* see how many files are selected */
1492 int i = ListView_GetSelectedCount(This->hWndList);
1494 /* get selected item */
1497 /* get selected item */
1498 i = ListView_GetNextItem(This->hWndList, -1,
1501 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1502 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
1506 TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1508 else if(plvKeyDown->wVKey == VK_DELETE)
1513 LPITEMIDLIST* pItems;
1516 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1522 if(!(i = ListView_GetSelectedCount(This->hWndList)))
1525 /* allocate memory for the pidl array */
1526 pItems = HeapAlloc(GetProcessHeap(), 0,
1527 sizeof(LPITEMIDLIST) * i);
1529 /* retrieve all selected items */
1532 while(ListView_GetSelectedCount(This->hWndList) > i)
1534 /* get selected item */
1535 item_index = ListView_GetNextItem(This->hWndList,
1536 item_index, LVNI_SELECTED);
1537 item.iItem = item_index;
1538 item.mask = LVIF_PARAM;
1539 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &item);
1542 pItems[i] = (LPITEMIDLIST)item.lParam;
1547 /* perform the item deletion */
1548 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1550 /* free pidl array memory */
1551 HeapFree(GetProcessHeap(), 0, pItems);
1554 /* Initiate a refresh */
1555 else if(plvKeyDown->wVKey == VK_F5)
1557 IShellView_Refresh((IShellView*)This);
1560 else if(plvKeyDown->wVKey == VK_BACK)
1562 LPSHELLBROWSER lpSb;
1563 if((lpSb = (LPSHELLBROWSER)SendMessageW(This->hWndParent, CWM_GETISHELLBROWSER, 0, 0)))
1565 IShellBrowser_BrowseObject(lpSb, NULL, SBSP_PARENT);
1570 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1575 TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1581 /**********************************************************
1582 * ShellView_OnChange()
1585 static LRESULT ShellView_OnChange(IShellViewImpl * This, const LPCITEMIDLIST * Pidls, LONG wEventId)
1588 TRACE("(%p)(%p,%p,0x%08x)\n", This, Pidls[0], Pidls[1], wEventId);
1593 LV_AddItem(This, Pidls[0]);
1597 LV_DeleteItem(This, Pidls[0]);
1599 case SHCNE_RENAMEFOLDER:
1600 case SHCNE_RENAMEITEM:
1601 LV_RenameItem(This, Pidls[0], Pidls[1]);
1603 case SHCNE_UPDATEITEM:
1608 /**********************************************************
1612 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1614 IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1615 LPCREATESTRUCTW lpcs;
1617 TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1622 lpcs = (LPCREATESTRUCTW)lParam;
1623 pThis = (IShellViewImpl*)(lpcs->lpCreateParams);
1624 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1625 pThis->hWnd = hWnd; /*set the window handle*/
1628 case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1629 case WM_SETFOCUS: return ShellView_OnSetFocus(pThis);
1630 case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis);
1631 case WM_CREATE: return ShellView_OnCreate(pThis);
1632 case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1633 case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1634 case WM_COMMAND: return ShellView_OnCommand(pThis,
1635 GET_WM_COMMAND_ID(wParam, lParam),
1636 GET_WM_COMMAND_CMD(wParam, lParam),
1637 GET_WM_COMMAND_HWND(wParam, lParam));
1638 case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (const LPCITEMIDLIST*)wParam, (LONG)lParam);
1640 case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1643 case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
1646 case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0);
1649 RevokeDragDrop(pThis->hWnd);
1650 SHChangeNotifyDeregister(pThis->hNotify);
1654 if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1655 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1660 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
1662 /**********************************************************
1665 * The INTERFACE of the IShellView object
1668 **********************************************************
1669 * IShellView_QueryInterface
1671 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj)
1673 IShellViewImpl *This = (IShellViewImpl *)iface;
1675 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1679 if(IsEqualIID(riid, &IID_IUnknown))
1683 else if(IsEqualIID(riid, &IID_IShellView))
1685 *ppvObj = (IShellView*)This;
1687 else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1689 *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget);
1691 else if(IsEqualIID(riid, &IID_IDropTarget))
1693 *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
1695 else if(IsEqualIID(riid, &IID_IDropSource))
1697 *ppvObj = (IDropSource*)&(This->lpvtblDropSource);
1699 else if(IsEqualIID(riid, &IID_IViewObject))
1701 *ppvObj = (IViewObject*)&(This->lpvtblViewObject);
1706 IUnknown_AddRef( (IUnknown*)*ppvObj );
1707 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1710 TRACE("-- Interface: E_NOINTERFACE\n");
1711 return E_NOINTERFACE;
1714 /**********************************************************
1717 static ULONG WINAPI IShellView_fnAddRef(IShellView * iface)
1719 IShellViewImpl *This = (IShellViewImpl *)iface;
1720 ULONG refCount = InterlockedIncrement(&This->ref);
1722 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
1726 /**********************************************************
1727 * IShellView_Release
1729 static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
1731 IShellViewImpl *This = (IShellViewImpl *)iface;
1732 ULONG refCount = InterlockedDecrement(&This->ref);
1734 TRACE("(%p)->(count=%i)\n", This, refCount + 1);
1738 TRACE(" destroying IShellView(%p)\n",This);
1740 DestroyWindow(This->hWndList);
1743 IShellFolder_Release(This->pSFParent);
1745 if(This->pSF2Parent)
1746 IShellFolder2_Release(This->pSF2Parent);
1748 SHFree(This->apidl);
1751 IAdviseSink_Release(This->pAdvSink);
1753 HeapFree(GetProcessHeap(),0,This);
1758 /**********************************************************
1759 * ShellView_GetWindow
1761 static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd)
1763 IShellViewImpl *This = (IShellViewImpl *)iface;
1765 TRACE("(%p)\n",This);
1767 *phWnd = This->hWnd;
1772 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode)
1774 IShellViewImpl *This = (IShellViewImpl *)iface;
1776 FIXME("(%p) stub\n",This);
1781 /**********************************************************
1782 * IShellView_TranslateAccelerator
1785 * use the accel functions
1787 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg)
1790 IShellViewImpl *This = (IShellViewImpl *)iface;
1792 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1795 if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1797 TRACE("-- key=0x04%lx\n",lpmsg->wParam) ;
1799 return S_FALSE; /* not handled */
1802 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable)
1804 IShellViewImpl *This = (IShellViewImpl *)iface;
1806 FIXME("(%p) stub\n",This);
1811 static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState)
1813 IShellViewImpl *This = (IShellViewImpl *)iface;
1816 CHAR szName[MAX_PATH];
1819 int nPartArray[1] = {-1};
1821 TRACE("(%p)->(state=%x) stub\n",This, uState);
1823 /*don't do anything if the state isn't really changing*/
1824 if(This->uState == uState)
1829 /*OnActivate handles the menu merging and internal state*/
1830 ShellView_OnActivate(This, uState);
1832 /*only do This if we are active*/
1833 if(uState != SVUIA_DEACTIVATE)
1837 GetFolderPath is not a method of IShellFolder
1838 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1840 /* set the number of parts */
1841 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1842 (LPARAM)nPartArray, &lResult);
1844 /* set the text for the parts */
1846 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1847 0, (LPARAM)szName, &lResult);
1854 static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface)
1856 IShellViewImpl *This = (IShellViewImpl *)iface;
1858 TRACE("(%p)\n",This);
1860 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
1861 ShellView_FillList(This);
1866 static HRESULT WINAPI IShellView_fnCreateViewWindow(
1868 IShellView *lpPrevView,
1869 LPCFOLDERSETTINGS lpfs,
1870 IShellBrowser * psb,
1874 IShellViewImpl *This = (IShellViewImpl *)iface;
1880 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd);
1881 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);
1883 /*set up the member variables*/
1884 This->pShellBrowser = psb;
1885 This->FolderSettings = *lpfs;
1887 /*get our parent window*/
1888 IShellBrowser_AddRef(This->pShellBrowser);
1889 IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
1891 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1892 This->pCommDlgBrowser=NULL;
1893 if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser,
1894 (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser)))
1896 TRACE("-- CommDlgBrowser\n");
1899 /*if our window class has not been registered, then do so*/
1900 if(!GetClassInfoW(shell32_hInstance, SV_CLASS_NAME, &wc))
1902 ZeroMemory(&wc, sizeof(wc));
1903 wc.style = CS_HREDRAW | CS_VREDRAW;
1904 wc.lpfnWndProc = ShellView_WndProc;
1907 wc.hInstance = shell32_hInstance;
1909 wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
1910 wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
1911 wc.lpszMenuName = NULL;
1912 wc.lpszClassName = SV_CLASS_NAME;
1914 if(!RegisterClassW(&wc))
1918 *phWnd = CreateWindowExW(0,
1921 WS_CHILD | WS_TABSTOP,
1924 prcView->right - prcView->left,
1925 prcView->bottom - prcView->top,
1933 if(!*phWnd) return E_FAIL;
1935 SetWindowPos(*phWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
1936 UpdateWindow(*phWnd);
1941 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
1943 IShellViewImpl *This = (IShellViewImpl *)iface;
1945 TRACE("(%p)\n",This);
1947 /*Make absolutely sure all our UI is cleaned up.*/
1948 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1952 DestroyMenu(This->hMenu);
1955 DestroyWindow(This->hWnd);
1956 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1957 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1963 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs)
1965 IShellViewImpl *This = (IShellViewImpl *)iface;
1967 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1968 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1970 if (!lpfs) return E_INVALIDARG;
1972 *lpfs = This->FolderSettings;
1976 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1978 IShellViewImpl *This = (IShellViewImpl *)iface;
1980 FIXME("(%p) stub\n",This);
1985 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface)
1987 IShellViewImpl *This = (IShellViewImpl *)iface;
1989 FIXME("(%p) stub\n",This);
1994 static HRESULT WINAPI IShellView_fnSelectItem(
1999 IShellViewImpl *This = (IShellViewImpl *)iface;
2002 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
2004 i = LV_FindItemByPidl(This, pidl);
2010 if(uFlags & SVSI_ENSUREVISIBLE)
2011 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
2013 lvItem.mask = LVIF_STATE;
2014 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
2016 lvItem.iSubItem = 0;
2018 while(SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem))
2020 if (lvItem.iItem == i)
2022 if (uFlags & SVSI_SELECT)
2023 lvItem.state |= LVIS_SELECTED;
2025 lvItem.state &= ~LVIS_SELECTED;
2027 if(uFlags & SVSI_FOCUSED)
2028 lvItem.state &= ~LVIS_FOCUSED;
2032 if (uFlags & SVSI_DESELECTOTHERS)
2033 lvItem.state &= ~LVIS_SELECTED;
2035 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
2040 if(uFlags & SVSI_EDIT)
2041 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
2047 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
2049 IShellViewImpl *This = (IShellViewImpl *)iface;
2051 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2057 case SVGIO_BACKGROUND:
2058 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2061 case SVGIO_SELECTION:
2062 ShellView_GetSelections(This);
2063 IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2066 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2068 if(!*ppvOut) return E_OUTOFMEMORY;
2073 static const IShellViewVtbl svvt =
2075 IShellView_fnQueryInterface,
2076 IShellView_fnAddRef,
2077 IShellView_fnRelease,
2078 IShellView_fnGetWindow,
2079 IShellView_fnContextSensitiveHelp,
2080 IShellView_fnTranslateAccelerator,
2081 IShellView_fnEnableModeless,
2082 IShellView_fnUIActivate,
2083 IShellView_fnRefresh,
2084 IShellView_fnCreateViewWindow,
2085 IShellView_fnDestroyViewWindow,
2086 IShellView_fnGetCurrentInfo,
2087 IShellView_fnAddPropertySheetPages,
2088 IShellView_fnSaveViewState,
2089 IShellView_fnSelectItem,
2090 IShellView_fnGetItemObject
2094 /**********************************************************
2095 * ISVOleCmdTarget_QueryInterface (IUnknown)
2097 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2098 IOleCommandTarget * iface,
2102 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2104 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2107 /**********************************************************
2108 * ISVOleCmdTarget_AddRef (IUnknown)
2110 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2111 IOleCommandTarget * iface)
2113 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2115 return IShellFolder_AddRef((IShellFolder*)This);
2118 /**********************************************************
2119 * ISVOleCmdTarget_Release (IUnknown)
2121 static ULONG WINAPI ISVOleCmdTarget_Release(
2122 IOleCommandTarget * iface)
2124 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2126 return IShellFolder_Release((IShellFolder*)This);
2129 /**********************************************************
2130 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2132 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2133 IOleCommandTarget *iface,
2134 const GUID* pguidCmdGroup,
2137 OLECMDTEXT* pCmdText)
2140 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2142 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2143 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2147 for (i = 0; i < cCmds; i++)
2149 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2150 prgCmds[i].cmdf = 0;
2152 return OLECMDERR_E_UNKNOWNGROUP;
2155 /**********************************************************
2156 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2158 * nCmdID is the OLECMDID_* enumeration
2160 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2161 IOleCommandTarget *iface,
2162 const GUID* pguidCmdGroup,
2168 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2170 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2171 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2173 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2175 (nCmdexecopt == 4) && pvaOut)
2177 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2182 return OLECMDERR_E_UNKNOWNGROUP;
2185 static const IOleCommandTargetVtbl ctvt =
2187 ISVOleCmdTarget_QueryInterface,
2188 ISVOleCmdTarget_AddRef,
2189 ISVOleCmdTarget_Release,
2190 ISVOleCmdTarget_QueryStatus,
2191 ISVOleCmdTarget_Exec
2194 /**********************************************************
2195 * ISVDropTarget implementation
2198 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2203 IShellViewImpl *This = impl_from_IDropTarget(iface);
2205 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2207 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2210 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2212 IShellViewImpl *This = impl_from_IDropTarget(iface);
2214 TRACE("(%p)->(count=%u)\n",This,This->ref);
2216 return IShellFolder_AddRef((IShellFolder*)This);
2219 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2221 IShellViewImpl *This = impl_from_IDropTarget(iface);
2223 TRACE("(%p)->(count=%u)\n",This,This->ref);
2225 return IShellFolder_Release((IShellFolder*)This);
2228 /******************************************************************************
2229 * drag_notify_subitem [Internal]
2231 * Figure out the shellfolder object, which is currently under the mouse cursor
2232 * and notify it via the IDropTarget interface.
2235 #define SCROLLAREAWIDTH 20
2237 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2240 LVHITTESTINFO htinfo;
2246 /* Map from global to client coordinates and query the index of the listview-item, which is
2247 * currently under the mouse cursor. */
2250 htinfo.flags = LVHT_ONITEM;
2251 ScreenToClient(This->hWndList, &htinfo.pt);
2252 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2254 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2255 GetClientRect(This->hWndList, &clientRect);
2256 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2257 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2258 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2260 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2261 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2262 if (htinfo.pt.x < SCROLLAREAWIDTH)
2263 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2264 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2265 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2266 if (htinfo.pt.y < SCROLLAREAWIDTH)
2267 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2268 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2269 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2272 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2274 This->ptLastMousePos = htinfo.pt;
2276 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2277 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2278 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2280 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2281 if (This->pCurDropTarget) {
2282 IDropTarget_DragLeave(This->pCurDropTarget);
2283 IDropTarget_Release(This->pCurDropTarget);
2284 This->pCurDropTarget = NULL;
2287 This->iDragOverItem = lResult;
2288 if (lResult == -1) {
2289 /* We are not above one of the listview's subitems. Bind to the parent folder's
2290 * DropTarget interface. */
2291 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2292 (LPVOID*)&This->pCurDropTarget);
2294 /* Query the relative PIDL of the shellfolder object represented by the currently
2295 * dragged over listview-item ... */
2296 lvItem.mask = LVIF_PARAM;
2297 lvItem.iItem = lResult;
2298 lvItem.iSubItem = 0;
2299 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
2301 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2302 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2303 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2306 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2310 /* Notify the item just entered via DragEnter. */
2311 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2314 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2315 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2317 IShellViewImpl *This = impl_from_IDropTarget(iface);
2319 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2320 This->pCurDataObject = pDataObject;
2321 IDataObject_AddRef(pDataObject);
2323 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2326 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2329 IShellViewImpl *This = impl_from_IDropTarget(iface);
2330 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2333 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2334 IShellViewImpl *This = impl_from_IDropTarget(iface);
2336 IDropTarget_DragLeave(This->pCurDropTarget);
2338 IDropTarget_Release(This->pCurDropTarget);
2339 IDataObject_Release(This->pCurDataObject);
2340 This->pCurDataObject = NULL;
2341 This->pCurDropTarget = NULL;
2342 This->iDragOverItem = 0;
2347 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2348 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2350 IShellViewImpl *This = impl_from_IDropTarget(iface);
2352 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2354 IDropTarget_Release(This->pCurDropTarget);
2355 IDataObject_Release(This->pCurDataObject);
2356 This->pCurDataObject = NULL;
2357 This->pCurDropTarget = NULL;
2358 This->iDragOverItem = 0;
2363 static const IDropTargetVtbl dtvt =
2365 ISVDropTarget_QueryInterface,
2366 ISVDropTarget_AddRef,
2367 ISVDropTarget_Release,
2368 ISVDropTarget_DragEnter,
2369 ISVDropTarget_DragOver,
2370 ISVDropTarget_DragLeave,
2374 /**********************************************************
2375 * ISVDropSource implementation
2378 static HRESULT WINAPI ISVDropSource_QueryInterface(
2383 IShellViewImpl *This = impl_from_IDropSource(iface);
2385 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2387 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2390 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2392 IShellViewImpl *This = impl_from_IDropSource(iface);
2394 TRACE("(%p)->(count=%u)\n",This,This->ref);
2396 return IShellFolder_AddRef((IShellFolder*)This);
2399 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2401 IShellViewImpl *This = impl_from_IDropSource(iface);
2403 TRACE("(%p)->(count=%u)\n",This,This->ref);
2405 return IShellFolder_Release((IShellFolder*)This);
2407 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2409 BOOL fEscapePressed,
2412 IShellViewImpl *This = impl_from_IDropSource(iface);
2413 TRACE("(%p)\n",This);
2416 return DRAGDROP_S_CANCEL;
2417 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2418 return DRAGDROP_S_DROP;
2423 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2427 IShellViewImpl *This = impl_from_IDropSource(iface);
2428 TRACE("(%p)\n",This);
2430 return DRAGDROP_S_USEDEFAULTCURSORS;
2433 static const IDropSourceVtbl dsvt =
2435 ISVDropSource_QueryInterface,
2436 ISVDropSource_AddRef,
2437 ISVDropSource_Release,
2438 ISVDropSource_QueryContinueDrag,
2439 ISVDropSource_GiveFeedback
2441 /**********************************************************
2442 * ISVViewObject implementation
2445 static HRESULT WINAPI ISVViewObject_QueryInterface(
2450 IShellViewImpl *This = impl_from_IViewObject(iface);
2452 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2454 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2457 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2459 IShellViewImpl *This = impl_from_IViewObject(iface);
2461 TRACE("(%p)->(count=%u)\n",This,This->ref);
2463 return IShellFolder_AddRef((IShellFolder*)This);
2466 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2468 IShellViewImpl *This = impl_from_IViewObject(iface);
2470 TRACE("(%p)->(count=%u)\n",This,This->ref);
2472 return IShellFolder_Release((IShellFolder*)This);
2475 static HRESULT WINAPI ISVViewObject_Draw(
2480 DVTARGETDEVICE* ptd,
2483 LPCRECTL lprcBounds,
2484 LPCRECTL lprcWBounds,
2485 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2486 ULONG_PTR dwContinue)
2489 IShellViewImpl *This = impl_from_IViewObject(iface);
2491 FIXME("Stub: This=%p\n",This);
2495 static HRESULT WINAPI ISVViewObject_GetColorSet(
2500 DVTARGETDEVICE* ptd,
2501 HDC hicTargetDevice,
2502 LOGPALETTE** ppColorSet)
2505 IShellViewImpl *This = impl_from_IViewObject(iface);
2507 FIXME("Stub: This=%p\n",This);
2511 static HRESULT WINAPI ISVViewObject_Freeze(
2519 IShellViewImpl *This = impl_from_IViewObject(iface);
2521 FIXME("Stub: This=%p\n",This);
2525 static HRESULT WINAPI ISVViewObject_Unfreeze(
2530 IShellViewImpl *This = impl_from_IViewObject(iface);
2532 FIXME("Stub: This=%p\n",This);
2536 static HRESULT WINAPI ISVViewObject_SetAdvise(
2540 IAdviseSink* pAdvSink)
2543 IShellViewImpl *This = impl_from_IViewObject(iface);
2545 FIXME("partial stub: %p %08x %08x %p\n",
2546 This, aspects, advf, pAdvSink);
2548 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2549 This->pAdvSink = pAdvSink;
2550 This->dwAspects = aspects;
2551 This->dwAdvf = advf;
2556 static HRESULT WINAPI ISVViewObject_GetAdvise(
2560 IAdviseSink** ppAdvSink)
2563 IShellViewImpl *This = impl_from_IViewObject(iface);
2565 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2566 This, pAspects, pAdvf, ppAdvSink);
2570 IAdviseSink_AddRef( This->pAdvSink );
2571 *ppAdvSink = This->pAdvSink;
2574 *pAspects = This->dwAspects;
2576 *pAdvf = This->dwAdvf;
2582 static const IViewObjectVtbl vovt =
2584 ISVViewObject_QueryInterface,
2585 ISVViewObject_AddRef,
2586 ISVViewObject_Release,
2588 ISVViewObject_GetColorSet,
2589 ISVViewObject_Freeze,
2590 ISVViewObject_Unfreeze,
2591 ISVViewObject_SetAdvise,
2592 ISVViewObject_GetAdvise