4 * Copyright 1998,1999 <juergen.schmied@debitel.net>
6 * This is the view visualizing the data provided by the shellfolder.
7 * No direct access to data from pidls should be done from here.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * FIXME: The order by part of the background context menu should be
24 * built according to the columns shown.
26 * FIXME: Load/Save the view state from/into the stream provided by
29 * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
31 * FIXME: ShellView_FillList: consider sort orders
33 * FIXME: implement the drag and drop in the old (msg-based) way
35 * FIXME: when the ShellView_WndProc gets a WM_NCDESTROY should we do a
40 #include "wine/port.h"
47 #define NONAMELESSUNION
48 #define NONAMELESSSTRUCT
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 IShellView2Vtbl* 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 IShellView2Vtbl 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;
321 FIXME("ViewMode %d not implemented\n", This->FolderSettings.ViewMode);
327 if (This->FolderSettings.fFlags & FWF_AUTOARRANGE) dwStyle |= LVS_AUTOARRANGE;
328 if (This->FolderSettings.fFlags & FWF_DESKTOP)
329 This->FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
330 if (This->FolderSettings.fFlags & FWF_SINGLESEL) dwStyle |= LVS_SINGLESEL;
331 if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE)
332 dwExStyle &= ~WS_EX_CLIENTEDGE;
334 This->hWndList=CreateWindowExW( dwExStyle,
347 This->ListViewSortInfo.bIsAscending = TRUE;
348 This->ListViewSortInfo.nHeaderID = -1;
349 This->ListViewSortInfo.nLastHeaderID = -1;
351 if (This->FolderSettings.fFlags & FWF_DESKTOP) {
353 * FIXME: look at the registry value
354 * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
355 * and activate drop shadows if necessary
358 SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, CLR_NONE);
360 SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, GetSysColor(COLOR_DESKTOP));
362 SendMessageW(This->hWndList, LVM_SETTEXTCOLOR, 0, RGB(255,255,255));
365 /* UpdateShellSettings(); */
369 /**********************************************************
370 * ShellView_InitList()
372 * - adds all needed columns to the shellview
374 static BOOL ShellView_InitList(IShellViewImpl * This)
383 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
385 lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
386 lvColumn.pszText = szTemp;
388 if (This->pSF2Parent)
392 if (FAILED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd)))
394 lvColumn.fmt = sd.fmt;
395 lvColumn.cx = sd.cxChar*8; /* chars->pixel */
396 StrRetToStrNW( szTemp, 50, &sd.str, NULL);
397 SendMessageW(This->hWndList, LVM_INSERTCOLUMNW, i, (LPARAM) &lvColumn);
405 SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ShellSmallIconList);
406 SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)ShellBigIconList);
410 /**********************************************************
411 * ShellView_CompareItems()
414 * internal, CALLBACK for DSA_Sort
416 static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
419 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
421 if(!lpData) return 0;
423 ret = (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2));
424 TRACE("ret=%i\n",ret);
428 /*************************************************************************
429 * ShellView_ListViewCompareItems
431 * Compare Function for the Listview (FileOpen Dialog)
434 * lParam1 [I] the first ItemIdList to compare with
435 * lParam2 [I] the second ItemIdList to compare with
436 * lpData [I] The column ID for the header Ctrl to process
439 * A negative value if the first item should precede the second,
440 * a positive value if the first item should follow the second,
441 * or zero if the two items are equivalent
444 * FIXME: function does what ShellView_CompareItems is supposed to do.
445 * unify it and figure out how to use the undocumented first parameter
446 * of IShellFolder_CompareIDs to do the job this function does and
447 * move this code to IShellFolder.
448 * make LISTVIEW_SORT_INFO obsolete
449 * the way this function works is only usable if we had only
450 * filesystemfolders (25/10/99 jsch)
452 static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
456 char strName1[MAX_PATH], strName2[MAX_PATH];
457 BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
458 LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1;
459 LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2;
460 LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData;
463 bIsFolder1 = _ILIsFolder(pItemIdList1);
464 bIsFolder2 = _ILIsFolder(pItemIdList2);
465 bIsBothFolder = bIsFolder1 && bIsFolder2;
467 /* When sorting between a File and a Folder, the Folder gets sorted first */
468 if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
470 nDiff = bIsFolder1 ? -1 : 1;
474 /* Sort by Time: Folders or Files can be sorted */
476 if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
478 _ILGetFileDateTime(pItemIdList1, &fd1);
479 _ILGetFileDateTime(pItemIdList2, &fd2);
480 nDiff = CompareFileTime(&fd2, &fd1);
482 /* Sort by Attribute: Folder or Files can be sorted */
483 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
485 _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH);
486 _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH);
487 nDiff = lstrcmpiA(strName1, strName2);
489 /* Sort by FileName: Folder or Files can be sorted */
490 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
493 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
494 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
495 nDiff = lstrcmpiA(strName1, strName2);
497 /* Sort by File Size, Only valid for Files */
498 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
500 nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0));
502 /* Sort by File Type, Only valid for Files */
503 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
506 _ILGetFileType(pItemIdList1, strName1, MAX_PATH);
507 _ILGetFileType(pItemIdList2, strName2, MAX_PATH);
508 nDiff = lstrcmpiA(strName1, strName2);
511 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
515 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
516 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
517 nDiff = lstrcmpiA(strName1, strName2);
520 if(!pSortInfo->bIsAscending)
529 /**********************************************************
530 * LV_FindItemByPidl()
532 static int LV_FindItemByPidl(
533 IShellViewImpl * This,
538 lvItem.mask = LVIF_PARAM;
539 for(lvItem.iItem = 0;
540 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
543 LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam;
544 HRESULT hr = IShellFolder_CompareIDs(This->pSFParent, 0, pidl, currentpidl);
545 if(SUCCEEDED(hr) && !HRESULT_CODE(hr))
553 /**********************************************************
556 static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
560 TRACE("(%p)(pidl=%p)\n", This, pidl);
562 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/
563 lvItem.iItem = ListView_GetItemCount(This->hWndList); /*add the item to the end of the list*/
565 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/
566 lvItem.pszText = LPSTR_TEXTCALLBACKW; /*get text on a callback basis*/
567 lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/
568 return (-1==ListView_InsertItemW(This->hWndList, &lvItem))? FALSE: TRUE;
571 /**********************************************************
574 static BOOLEAN LV_DeleteItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
578 TRACE("(%p)(pidl=%p)\n", This, pidl);
580 nIndex = LV_FindItemByPidl(This, ILFindLastID(pidl));
581 return (-1==ListView_DeleteItem(This->hWndList, nIndex))? FALSE: TRUE;
584 /**********************************************************
587 static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew )
592 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew);
594 nItem = LV_FindItemByPidl(This, ILFindLastID(pidlOld));
597 lvItem.mask = LVIF_PARAM; /* only the pidl */
598 lvItem.iItem = nItem;
599 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
601 SHFree((LPITEMIDLIST)lvItem.lParam);
602 lvItem.mask = LVIF_PARAM;
603 lvItem.iItem = nItem;
604 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */
605 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
606 SendMessageW(This->hWndList, LVM_UPDATE, nItem, 0);
607 return TRUE; /* FIXME: better handling */
611 /**********************************************************
612 * ShellView_FillList()
614 * - gets the objectlist from the shellfolder
616 * - fills the list into the view
619 static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg )
621 LPITEMIDLIST pidl = ptr;
622 IShellViewImpl *This = arg;
623 /* in a commdlg This works as a filemask*/
624 if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl);
629 static HRESULT ShellView_FillList(IShellViewImpl * This)
631 LPENUMIDLIST pEnumIDList;
639 /* get the itemlist from the shfolder*/
640 hRes = IShellFolder_EnumObjects(This->pSFParent,This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
648 /* create a pointer array */
649 hdpa = DPA_Create(16);
652 return(E_OUTOFMEMORY);
655 /* copy the items into the array*/
656 while((S_OK == IEnumIDList_Next(pEnumIDList,1, &pidl, &dwFetched)) && dwFetched)
658 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
665 DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent);
667 /*turn the listview's redrawing off*/
668 SendMessageA(This->hWndList, WM_SETREDRAW, FALSE, 0);
670 DPA_DestroyCallback( hdpa, fill_list, This );
672 /*turn the listview's redrawing back on and force it to draw*/
673 SendMessageA(This->hWndList, WM_SETREDRAW, TRUE, 0);
675 IEnumIDList_Release(pEnumIDList); /* destroy the list*/
680 /**********************************************************
681 * ShellView_OnCreate()
683 static LRESULT ShellView_OnCreate(IShellViewImpl * This)
686 SHChangeNotifyEntry ntreg;
687 IPersistFolder2 * ppf2 = NULL;
691 if(ShellView_CreateList(This))
693 if(ShellView_InitList(This))
695 ShellView_FillList(This);
699 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown*)&This->lpVtbl, &IID_IDropTarget, (LPVOID*)&pdt)))
701 RegisterDragDrop(This->hWnd, pdt);
702 IDropTarget_Release(pdt);
705 /* register for receiving notifications */
706 IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
709 IPersistFolder2_GetCurFolder(ppf2, (LPITEMIDLIST*)&ntreg.pidl);
710 ntreg.fRecursive = TRUE;
711 This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
712 SHFree((LPITEMIDLIST)ntreg.pidl);
713 IPersistFolder2_Release(ppf2);
716 This->hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel");
721 /**********************************************************
722 * #### Handling of the menus ####
725 /**********************************************************
726 * ShellView_BuildFileMenu()
728 static HMENU ShellView_BuildFileMenu(IShellViewImpl * This)
729 { WCHAR szText[MAX_PATH];
734 TRACE("(%p)\n",This);
736 hSubMenu = CreatePopupMenu();
738 { /*get the number of items in our global array*/
739 for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
741 /*add the menu items*/
742 for(i = 0; i < nTools; i++)
744 LoadStringW(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
746 ZeroMemory(&mii, sizeof(mii));
747 mii.cbSize = sizeof(mii);
748 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
750 if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
752 mii.fType = MFT_STRING;
753 mii.fState = MFS_ENABLED;
754 mii.dwTypeData = szText;
755 mii.wID = Tools[i].idCommand;
759 mii.fType = MFT_SEPARATOR;
761 /* tack This item onto the end of the menu */
762 InsertMenuItemW(hSubMenu, (UINT)-1, TRUE, &mii);
765 TRACE("-- return (menu=%p)\n",hSubMenu);
768 /**********************************************************
769 * ShellView_MergeFileMenu()
771 static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu)
772 { TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu);
775 { /*insert This item at the beginning of the menu */
778 mii.cbSize = sizeof(mii);
779 mii.fMask = MIIM_ID | MIIM_TYPE;
781 mii.fType = MFT_SEPARATOR;
782 InsertMenuItemA(hSubMenu, 0, TRUE, &mii);
784 mii.cbSize = sizeof(mii);
785 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
786 mii.dwTypeData = (LPSTR)"dummy45";
787 mii.fState = MFS_ENABLED;
788 mii.wID = IDM_MYFILEITEM;
789 mii.fType = MFT_STRING;
790 InsertMenuItemA(hSubMenu, 0, TRUE, &mii);
795 /**********************************************************
796 * ShellView_MergeViewMenu()
799 static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu)
801 TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
804 { /*add a separator at the correct position in the menu*/
806 static char view[] = "View";
808 ZeroMemory(&mii, sizeof(mii));
809 mii.cbSize = sizeof(mii);
810 mii.fMask = MIIM_ID | MIIM_TYPE;
812 mii.fType = MFT_SEPARATOR;
813 InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
815 mii.cbSize = sizeof(mii);
816 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
817 mii.fType = MFT_STRING;
818 mii.dwTypeData = view;
819 mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
820 InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
824 /**********************************************************
825 * ShellView_GetSelections()
827 * - fills the this->apidl list with the selected objects
830 * number of selected items
832 static UINT ShellView_GetSelections(IShellViewImpl * This)
839 This->cidl = ListView_GetSelectedCount(This->hWndList);
840 This->apidl = (LPITEMIDLIST*)SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
842 TRACE("selected=%i\n", This->cidl);
846 TRACE("-- Items selected =%u\n", This->cidl);
848 lvItem.mask = LVIF_STATE | LVIF_PARAM;
849 lvItem.stateMask = LVIS_SELECTED;
853 while(ListView_GetItemW(This->hWndList, &lvItem) && (i < This->cidl))
855 if(lvItem.state & LVIS_SELECTED)
857 This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
859 TRACE("-- selected Item found\n");
868 /**********************************************************
869 * ShellView_OpenSelectedItems()
871 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
873 static UINT CF_IDLIST = 0;
875 IDataObject* selection;
879 LPCITEMIDLIST parent_pidl;
880 WCHAR parent_path[MAX_PATH];
881 LPCWSTR parent_dir = NULL;
885 if (0 == ShellView_GetSelections(This))
889 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
890 (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
891 0, (LPVOID *)&selection);
897 CF_IDLIST = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
899 fetc.cfFormat = CF_IDLIST;
901 fetc.dwAspect = DVASPECT_CONTENT;
903 fetc.tymed = TYMED_HGLOBAL;
905 hr = IDataObject_QueryGetData(selection, &fetc);
909 hr = IDataObject_GetData(selection, &fetc, &stgm);
913 pIDList = GlobalLock(stgm.u.hGlobal);
915 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
916 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &parent_pidl, &attribs);
917 if (SUCCEEDED(hr) && (attribs & SFGAO_FILESYSTEM) &&
918 SHGetPathFromIDListW(parent_pidl, parent_path))
920 parent_dir = parent_path;
923 for (i = pIDList->cidl; i > 0; --i)
927 pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
929 attribs = SFGAO_FOLDER;
930 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
932 if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
934 SHELLEXECUTEINFOW shexinfo;
936 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
937 shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */
938 shexinfo.hwnd = NULL;
939 shexinfo.lpVerb = NULL;
940 shexinfo.lpFile = NULL;
941 shexinfo.lpParameters = NULL;
942 shexinfo.lpDirectory = parent_dir;
943 shexinfo.nShow = SW_NORMAL;
944 shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
946 ShellExecuteExW(&shexinfo); /* Discard error/success info */
948 ILFree((LPITEMIDLIST)shexinfo.lpIDList);
952 GlobalUnlock(stgm.u.hGlobal);
953 ReleaseStgMedium(&stgm);
955 IDataObject_Release(selection);
960 /**********************************************************
961 * ShellView_DoContextMenu()
963 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
967 BOOL fExplore = FALSE;
969 LPCONTEXTMENU pContextMenu = NULL;
970 IContextMenu2 *pCM = NULL;
971 CMINVOKECOMMANDINFO cmi;
973 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
975 /* look, what's selected and create a context menu object of it*/
976 if( ShellView_GetSelections(This) )
978 IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
979 (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
983 TRACE("-- pContextMenu\n");
984 hMenu = CreatePopupMenu();
988 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
989 if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
991 TRACE("-- explore mode\n");
995 /* build the flags depending on what we can do with the selected item */
996 wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
998 /* let the ContextMenu merge its items in */
999 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
1001 if (This->FolderSettings.fFlags & FWF_DESKTOP)
1002 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
1006 TRACE("-- get menu default command\n");
1007 uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
1011 TRACE("-- track popup\n");
1012 uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1017 TRACE("-- uCommand=%u\n", uCommand);
1018 if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
1020 TRACE("-- dlg: OnDefaultCommand\n");
1021 if (OnDefaultCommand(This) != S_OK)
1023 ShellView_OpenSelectedItems(This);
1028 TRACE("-- explore -- invoke command\n");
1029 ZeroMemory(&cmi, sizeof(cmi));
1030 cmi.cbSize = sizeof(cmi);
1031 cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
1032 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1033 IContextMenu_InvokeCommand(pContextMenu, &cmi);
1040 IContextMenu_Release(pContextMenu);
1043 else /* background context menu */
1045 hMenu = CreatePopupMenu();
1047 pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
1048 IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1050 uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1053 TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1055 ZeroMemory(&cmi, sizeof(cmi));
1056 cmi.cbSize = sizeof(cmi);
1057 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1058 cmi.hwnd = This->hWndParent;
1059 IContextMenu2_InvokeCommand(pCM, &cmi);
1061 IContextMenu2_Release(pCM);
1065 /**********************************************************
1066 * ##### message handling #####
1069 /**********************************************************
1070 * ShellView_OnSize()
1072 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1074 TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1076 /*resize the ListView to fit our window*/
1079 MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1084 /**********************************************************
1085 * ShellView_OnDeactivate()
1090 static void ShellView_OnDeactivate(IShellViewImpl * This)
1094 if(This->uState != SVUIA_DEACTIVATE)
1098 IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1099 IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1100 DestroyMenu(This->hMenu);
1104 This->uState = SVUIA_DEACTIVATE;
1108 /**********************************************************
1109 * ShellView_OnActivate()
1111 static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState)
1112 { OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} };
1114 CHAR szText[MAX_PATH];
1116 TRACE("%p uState=%x\n",This,uState);
1118 /*don't do anything if the state isn't really changing */
1119 if(This->uState == uState)
1124 ShellView_OnDeactivate(This);
1126 /*only do This if we are active */
1127 if(uState != SVUIA_DEACTIVATE)
1129 /*merge the menus */
1130 This->hMenu = CreateMenu();
1134 IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1135 TRACE("-- after fnInsertMenusSB\n");
1137 /*build the top level menu get the menu item's text*/
1138 strcpy(szText,"dummy 31");
1140 ZeroMemory(&mii, sizeof(mii));
1141 mii.cbSize = sizeof(mii);
1142 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1143 mii.fType = MFT_STRING;
1144 mii.fState = MFS_ENABLED;
1145 mii.dwTypeData = szText;
1146 mii.hSubMenu = ShellView_BuildFileMenu(This);
1148 /*insert our menu into the menu bar*/
1151 InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1154 /*get the view menu so we can merge with it*/
1155 ZeroMemory(&mii, sizeof(mii));
1156 mii.cbSize = sizeof(mii);
1157 mii.fMask = MIIM_SUBMENU;
1159 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1161 ShellView_MergeViewMenu(This, mii.hSubMenu);
1164 /*add the items that should only be added if we have the focus*/
1165 if(SVUIA_ACTIVATE_FOCUS == uState)
1167 /*get the file menu so we can merge with it */
1168 ZeroMemory(&mii, sizeof(mii));
1169 mii.cbSize = sizeof(mii);
1170 mii.fMask = MIIM_SUBMENU;
1172 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1174 ShellView_MergeFileMenu(This, mii.hSubMenu);
1177 TRACE("-- before fnSetMenuSB\n");
1178 IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1181 This->uState = uState;
1186 /**********************************************************
1187 * ShellView_OnSetFocus()
1190 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1194 /* Tell the browser one of our windows has received the focus. This
1195 should always be done before merging menus (OnActivate merges the
1196 menus) if one of our windows has the focus.*/
1198 IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1199 ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1201 /* Set the focus to the listview */
1202 SetFocus(This->hWndList);
1204 /* Notify the ICommDlgBrowser interface */
1205 OnStateChange(This,CDBOSC_SETFOCUS);
1210 /**********************************************************
1211 * ShellView_OnKillFocus()
1213 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1215 TRACE("(%p) stub\n",This);
1217 ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1218 /* Notify the ICommDlgBrowser */
1219 OnStateChange(This,CDBOSC_KILLFOCUS);
1224 /**********************************************************
1225 * ShellView_OnCommand()
1228 * the CmdID's are the ones from the context menu
1230 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1232 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1236 case FCIDM_SHVIEW_SMALLICON:
1237 This->FolderSettings.ViewMode = FVM_SMALLICON;
1238 SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1242 case FCIDM_SHVIEW_BIGICON:
1243 This->FolderSettings.ViewMode = FVM_ICON;
1244 SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1248 case FCIDM_SHVIEW_LISTVIEW:
1249 This->FolderSettings.ViewMode = FVM_LIST;
1250 SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1254 case FCIDM_SHVIEW_REPORTVIEW:
1255 This->FolderSettings.ViewMode = FVM_DETAILS;
1256 SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1260 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1265 This->ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30);
1266 This->ListViewSortInfo.bIsAscending = TRUE;
1267 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1268 SendMessageA(This->hWndList, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1272 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID);
1277 /**********************************************************
1278 * ShellView_OnNotify()
1281 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1282 { LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1283 NMLVDISPINFOW *lpdi = (NMLVDISPINFOW *)lpnmh;
1286 TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1291 TRACE("-- NM_SETFOCUS %p\n",This);
1292 ShellView_OnSetFocus(This);
1296 TRACE("-- NM_KILLFOCUS %p\n",This);
1297 ShellView_OnDeactivate(This);
1298 /* Notify the ICommDlgBrowser interface */
1299 OnStateChange(This,CDBOSC_KILLFOCUS);
1303 TRACE("-- NM_CUSTOMDRAW %p\n",This);
1304 return CDRF_DODEFAULT;
1306 case NM_RELEASEDCAPTURE:
1307 TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1311 TRACE("-- NM_CLICK %p\n",This);
1315 TRACE("-- NM_RCLICK %p\n",This);
1319 TRACE("-- NM_DBLCLK %p\n",This);
1320 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1324 TRACE("-- NM_DBLCLK %p\n",This);
1325 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1329 TRACE("-- HDN_ENDTRACKW %p\n",This);
1330 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1331 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1334 case LVN_DELETEITEM:
1335 TRACE("-- LVN_DELETEITEM %p\n",This);
1336 SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/
1339 case LVN_DELETEALLITEMS:
1340 TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1343 case LVN_INSERTITEM:
1344 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1347 case LVN_ITEMACTIVATE:
1348 TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1349 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1352 case LVN_COLUMNCLICK:
1353 This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1354 if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1356 This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1360 This->ListViewSortInfo.bIsAscending = TRUE;
1362 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1364 SendMessageW(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1367 case LVN_GETDISPINFOA:
1368 case LVN_GETDISPINFOW:
1369 TRACE("-- LVN_GETDISPINFO %p\n",This);
1370 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1372 if(lpdi->item.mask & LVIF_TEXT) /* text requested */
1374 if (This->pSF2Parent)
1377 IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1378 if (lpnmh->code == LVN_GETDISPINFOA)
1380 /* shouldn't happen */
1381 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1382 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1383 TRACE("-- text=%s\n",lpdiA->item.pszText);
1385 else /* LVN_GETDISPINFOW */
1387 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1388 TRACE("-- text=%s\n",debugstr_w(lpdi->item.pszText));
1396 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1398 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1402 case LVN_ITEMCHANGED:
1403 TRACE("-- LVN_ITEMCHANGED %p\n",This);
1404 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1408 case LVN_BEGINRDRAG:
1409 TRACE("-- LVN_BEGINDRAG\n");
1411 if (ShellView_GetSelections(This))
1414 DWORD dwAttributes = SFGAO_CANLINK;
1415 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1417 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1419 IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource); /* own DropSource interface */
1421 if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1423 if (dwAttributes & SFGAO_CANLINK)
1425 dwEffect |= DROPEFFECT_LINK;
1432 DoDragDrop(pda, pds, dwEffect, &dwEffect);
1434 IDataObject_Release(pda);
1439 case LVN_BEGINLABELEDITW:
1441 DWORD dwAttr = SFGAO_CANRENAME;
1442 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1444 TRACE("-- LVN_BEGINLABELEDITA %p\n",This);
1446 IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1447 if (SFGAO_CANRENAME & dwAttr)
1454 case LVN_ENDLABELEDITW:
1456 TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1457 if (lpdi->item.pszText)
1462 lvItem.iItem = lpdi->item.iItem;
1463 lvItem.iSubItem = 0;
1464 lvItem.mask = LVIF_PARAM;
1465 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
1467 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1468 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidl);
1470 if(SUCCEEDED(hr) && pidl)
1472 lvItem.mask = LVIF_PARAM;
1473 lvItem.lParam = (LPARAM)pidl;
1474 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
1484 msg.hwnd = This->hWnd;
1485 msg.message = WM_KEYDOWN;
1486 msg.wParam = plvKeyDown->wVKey;
1491 LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1493 /* initiate a rename of the selected file or directory */
1494 if(plvKeyDown->wVKey == VK_F2)
1496 /* see how many files are selected */
1497 int i = ListView_GetSelectedCount(This->hWndList);
1499 /* get selected item */
1502 /* get selected item */
1503 i = ListView_GetNextItem(This->hWndList, -1,
1506 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1507 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
1511 TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1513 else if(plvKeyDown->wVKey == VK_DELETE)
1518 LPITEMIDLIST* pItems;
1521 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1527 if(!(i = ListView_GetSelectedCount(This->hWndList)))
1530 /* allocate memory for the pidl array */
1531 pItems = HeapAlloc(GetProcessHeap(), 0,
1532 sizeof(LPITEMIDLIST) * i);
1534 /* retrieve all selected items */
1537 while(ListView_GetSelectedCount(This->hWndList) > i)
1539 /* get selected item */
1540 item_index = ListView_GetNextItem(This->hWndList,
1541 item_index, LVNI_SELECTED);
1542 item.iItem = item_index;
1543 item.mask = LVIF_PARAM;
1544 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &item);
1547 pItems[i] = (LPITEMIDLIST)item.lParam;
1552 /* perform the item deletion */
1553 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1555 /* free pidl array memory */
1556 HeapFree(GetProcessHeap(), 0, pItems);
1559 /* Initiate a refresh */
1560 else if(plvKeyDown->wVKey == VK_F5)
1562 IShellView_Refresh((IShellView*)This);
1565 else if(plvKeyDown->wVKey == VK_BACK)
1567 LPSHELLBROWSER lpSb;
1568 if((lpSb = (LPSHELLBROWSER)SendMessageW(This->hWndParent, CWM_GETISHELLBROWSER, 0, 0)))
1570 IShellBrowser_BrowseObject(lpSb, NULL, SBSP_PARENT);
1575 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1580 TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1586 /**********************************************************
1587 * ShellView_OnChange()
1590 static LRESULT ShellView_OnChange(IShellViewImpl * This, const LPCITEMIDLIST * Pidls, LONG wEventId)
1593 TRACE("(%p)(%p,%p,0x%08x)\n", This, Pidls[0], Pidls[1], wEventId);
1598 LV_AddItem(This, Pidls[0]);
1602 LV_DeleteItem(This, Pidls[0]);
1604 case SHCNE_RENAMEFOLDER:
1605 case SHCNE_RENAMEITEM:
1606 LV_RenameItem(This, Pidls[0], Pidls[1]);
1608 case SHCNE_UPDATEITEM:
1613 /**********************************************************
1617 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1619 IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1620 LPCREATESTRUCTW lpcs;
1622 TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1627 lpcs = (LPCREATESTRUCTW)lParam;
1628 pThis = (IShellViewImpl*)(lpcs->lpCreateParams);
1629 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1630 pThis->hWnd = hWnd; /*set the window handle*/
1633 case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1634 case WM_SETFOCUS: return ShellView_OnSetFocus(pThis);
1635 case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis);
1636 case WM_CREATE: return ShellView_OnCreate(pThis);
1637 case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1638 case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1639 case WM_COMMAND: return ShellView_OnCommand(pThis,
1640 GET_WM_COMMAND_ID(wParam, lParam),
1641 GET_WM_COMMAND_CMD(wParam, lParam),
1642 GET_WM_COMMAND_HWND(wParam, lParam));
1643 case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (const LPCITEMIDLIST*)wParam, (LONG)lParam);
1645 case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1648 case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
1651 case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0);
1654 RevokeDragDrop(pThis->hWnd);
1655 SHChangeNotifyDeregister(pThis->hNotify);
1659 if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1660 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1665 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
1667 /**********************************************************
1670 * The INTERFACE of the IShellView object
1673 **********************************************************
1674 * IShellView_QueryInterface
1676 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView2 * iface,REFIID riid, LPVOID *ppvObj)
1678 IShellViewImpl *This = (IShellViewImpl *)iface;
1680 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1684 if(IsEqualIID(riid, &IID_IUnknown))
1688 else if(IsEqualIID(riid, &IID_IShellView))
1690 *ppvObj = (IShellView*)This;
1692 else if(IsEqualIID(riid, &IID_IShellView2))
1694 *ppvObj = (IShellView2*)This;
1696 else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1698 *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget);
1700 else if(IsEqualIID(riid, &IID_IDropTarget))
1702 *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
1704 else if(IsEqualIID(riid, &IID_IDropSource))
1706 *ppvObj = (IDropSource*)&(This->lpvtblDropSource);
1708 else if(IsEqualIID(riid, &IID_IViewObject))
1710 *ppvObj = (IViewObject*)&(This->lpvtblViewObject);
1715 IUnknown_AddRef( (IUnknown*)*ppvObj );
1716 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1719 TRACE("-- Interface: E_NOINTERFACE\n");
1720 return E_NOINTERFACE;
1723 /**********************************************************
1726 static ULONG WINAPI IShellView_fnAddRef(IShellView2 * iface)
1728 IShellViewImpl *This = (IShellViewImpl *)iface;
1729 ULONG refCount = InterlockedIncrement(&This->ref);
1731 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
1735 /**********************************************************
1736 * IShellView_Release
1738 static ULONG WINAPI IShellView_fnRelease(IShellView2 * iface)
1740 IShellViewImpl *This = (IShellViewImpl *)iface;
1741 ULONG refCount = InterlockedDecrement(&This->ref);
1743 TRACE("(%p)->(count=%i)\n", This, refCount + 1);
1747 TRACE(" destroying IShellView(%p)\n",This);
1749 DestroyWindow(This->hWndList);
1752 IShellFolder_Release(This->pSFParent);
1754 if(This->pSF2Parent)
1755 IShellFolder2_Release(This->pSF2Parent);
1757 SHFree(This->apidl);
1760 IAdviseSink_Release(This->pAdvSink);
1762 HeapFree(GetProcessHeap(),0,This);
1767 /**********************************************************
1768 * ShellView_GetWindow
1770 static HRESULT WINAPI IShellView_fnGetWindow(IShellView2 * iface,HWND * phWnd)
1772 IShellViewImpl *This = (IShellViewImpl *)iface;
1774 TRACE("(%p)\n",This);
1776 *phWnd = This->hWnd;
1781 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView2 * iface,BOOL fEnterMode)
1783 IShellViewImpl *This = (IShellViewImpl *)iface;
1785 FIXME("(%p) stub\n",This);
1790 /**********************************************************
1791 * IShellView_TranslateAccelerator
1794 * use the accel functions
1796 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView2 * iface,LPMSG lpmsg)
1799 IShellViewImpl *This = (IShellViewImpl *)iface;
1801 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1804 if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1806 TRACE("-- key=0x04%lx\n",lpmsg->wParam) ;
1808 return S_FALSE; /* not handled */
1811 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView2 * iface,BOOL fEnable)
1813 IShellViewImpl *This = (IShellViewImpl *)iface;
1815 FIXME("(%p) stub\n",This);
1820 static HRESULT WINAPI IShellView_fnUIActivate(IShellView2 * iface,UINT uState)
1822 IShellViewImpl *This = (IShellViewImpl *)iface;
1825 CHAR szName[MAX_PATH];
1828 int nPartArray[1] = {-1};
1830 TRACE("(%p)->(state=%x) stub\n",This, uState);
1832 /*don't do anything if the state isn't really changing*/
1833 if(This->uState == uState)
1838 /*OnActivate handles the menu merging and internal state*/
1839 ShellView_OnActivate(This, uState);
1841 /*only do This if we are active*/
1842 if(uState != SVUIA_DEACTIVATE)
1846 GetFolderPath is not a method of IShellFolder
1847 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1849 /* set the number of parts */
1850 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1851 (LPARAM)nPartArray, &lResult);
1853 /* set the text for the parts */
1855 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1856 0, (LPARAM)szName, &lResult);
1863 static HRESULT WINAPI IShellView_fnRefresh(IShellView2 * iface)
1865 IShellViewImpl *This = (IShellViewImpl *)iface;
1867 TRACE("(%p)\n",This);
1869 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
1870 ShellView_FillList(This);
1875 static HRESULT WINAPI IShellView_fnCreateViewWindow(IShellView2 *iface, IShellView *lpPrevView,
1876 LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd)
1879 SV2CVW2_PARAMS view_params;
1880 view_params.cbSize = sizeof(view_params);
1881 view_params.psvPrev = lpPrevView;
1882 view_params.pfs = lpfs;
1883 view_params.psbOwner = psb;
1884 view_params.prcView = prcView;
1885 view_params.pvid = NULL;
1886 view_params.hwndView = 0;
1888 TRACE("(%p) Forwarding to CreateViewWindow2\n", iface);
1890 hr = IShellView2_CreateViewWindow2(iface, &view_params);
1891 *phWnd = view_params.hwndView;
1896 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView2 * iface)
1898 IShellViewImpl *This = (IShellViewImpl *)iface;
1900 TRACE("(%p)\n",This);
1902 /*Make absolutely sure all our UI is cleaned up.*/
1903 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1907 DestroyMenu(This->hMenu);
1910 DestroyWindow(This->hWnd);
1911 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1912 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1918 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView2 * iface, LPFOLDERSETTINGS lpfs)
1920 IShellViewImpl *This = (IShellViewImpl *)iface;
1922 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1923 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1925 if (!lpfs) return E_INVALIDARG;
1927 *lpfs = This->FolderSettings;
1931 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView2 * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1933 IShellViewImpl *This = (IShellViewImpl *)iface;
1935 FIXME("(%p) stub\n",This);
1940 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView2 * iface)
1942 IShellViewImpl *This = (IShellViewImpl *)iface;
1944 FIXME("(%p) stub\n",This);
1949 static HRESULT WINAPI IShellView_fnSelectItem(
1950 IShellView2 * iface,
1954 IShellViewImpl *This = (IShellViewImpl *)iface;
1957 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
1959 i = LV_FindItemByPidl(This, pidl);
1965 if(uFlags & SVSI_ENSUREVISIBLE)
1966 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1968 lvItem.mask = LVIF_STATE;
1969 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
1971 lvItem.iSubItem = 0;
1973 while(SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem))
1975 if (lvItem.iItem == i)
1977 if (uFlags & SVSI_SELECT)
1978 lvItem.state |= LVIS_SELECTED;
1980 lvItem.state &= ~LVIS_SELECTED;
1982 if(uFlags & SVSI_FOCUSED)
1983 lvItem.state &= ~LVIS_FOCUSED;
1987 if (uFlags & SVSI_DESELECTOTHERS)
1988 lvItem.state &= ~LVIS_SELECTED;
1990 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
1995 if(uFlags & SVSI_EDIT)
1996 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
2002 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView2 * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
2004 IShellViewImpl *This = (IShellViewImpl *)iface;
2006 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2012 case SVGIO_BACKGROUND:
2013 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2016 case SVGIO_SELECTION:
2017 ShellView_GetSelections(This);
2018 IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2021 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2023 if(!*ppvOut) return E_OUTOFMEMORY;
2028 static HRESULT WINAPI IShellView2_fnGetView(IShellView2* iface, SHELLVIEWID *view_guid, ULONG view_type)
2030 FIXME("(%p)->(view_guid %s, view_type %#x) stub!\n", iface, debugstr_guid(view_guid), view_type);
2034 static HRESULT WINAPI IShellView2_fnCreateViewWindow2(IShellView2* iface, LPSV2CVW2_PARAMS view_params)
2036 IShellViewImpl *This = (IShellViewImpl *)iface;
2040 TRACE("(%p)->(view_params %p)\n", iface, view_params);
2042 if (view_params->cbSize != sizeof(*view_params))
2044 FIXME("Got unexpected cbSize %#x\n", view_params->cbSize);
2048 TRACE("-- psvPrev %p, pfs %p, psbOwner %p, prcView %p\n",
2049 view_params->psvPrev, view_params->pfs, view_params->psbOwner, view_params->prcView);
2050 TRACE("-- vmode %#x, flags %#x, left %d, top %d, right %d, bottom %d\n",
2051 view_params->pfs->ViewMode, view_params->pfs->fFlags, view_params->prcView->left,
2052 view_params->prcView->top, view_params->prcView->right, view_params->prcView->bottom);
2054 /* Set up the member variables */
2055 This->pShellBrowser = view_params->psbOwner;
2056 This->FolderSettings = *view_params->pfs;
2058 if (view_params->pvid)
2060 if (IsEqualGUID(view_params->pvid, &VID_LargeIcons))
2061 This->FolderSettings.ViewMode = FVM_ICON;
2062 else if (IsEqualGUID(view_params->pvid, &VID_SmallIcons))
2063 This->FolderSettings.ViewMode = FVM_SMALLICON;
2064 else if (IsEqualGUID(view_params->pvid, &VID_List))
2065 This->FolderSettings.ViewMode = FVM_LIST;
2066 else if (IsEqualGUID(view_params->pvid, &VID_Details))
2067 This->FolderSettings.ViewMode = FVM_DETAILS;
2068 else if (IsEqualGUID(view_params->pvid, &VID_Thumbnails))
2069 This->FolderSettings.ViewMode = FVM_THUMBNAIL;
2070 else if (IsEqualGUID(view_params->pvid, &VID_Tile))
2071 This->FolderSettings.ViewMode = FVM_TILE;
2072 else if (IsEqualGUID(view_params->pvid, &VID_ThumbStrip))
2073 This->FolderSettings.ViewMode = FVM_THUMBSTRIP;
2075 FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_params->pvid));
2078 /* Get our parent window */
2079 IShellBrowser_AddRef(This->pShellBrowser);
2080 IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
2082 /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
2083 This->pCommDlgBrowser = NULL;
2084 if (SUCCEEDED(IShellBrowser_QueryInterface(This->pShellBrowser, &IID_ICommDlgBrowser, (void **)&This->pCommDlgBrowser)))
2086 TRACE("-- CommDlgBrowser %p\n", This->pCommDlgBrowser);
2089 /* If our window class has not been registered, then do so */
2090 if (!GetClassInfoW(shell32_hInstance, SV_CLASS_NAME, &wc))
2092 ZeroMemory(&wc, sizeof(wc));
2093 wc.style = CS_HREDRAW | CS_VREDRAW;
2094 wc.lpfnWndProc = ShellView_WndProc;
2097 wc.hInstance = shell32_hInstance;
2099 wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
2100 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2101 wc.lpszMenuName = NULL;
2102 wc.lpszClassName = SV_CLASS_NAME;
2104 if (!RegisterClassW(&wc)) return E_FAIL;
2107 wnd = CreateWindowExW(0,
2110 WS_CHILD | WS_TABSTOP,
2111 view_params->prcView->left,
2112 view_params->prcView->top,
2113 view_params->prcView->right - view_params->prcView->left,
2114 view_params->prcView->bottom - view_params->prcView->top,
2122 if (!wnd) return E_FAIL;
2124 SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
2127 view_params->hwndView = wnd;
2132 static HRESULT WINAPI IShellView2_fnHandleRename(IShellView2* iface, LPCITEMIDLIST new_pidl)
2134 FIXME("(%p)->(new_pidl %p) stub!\n", iface, new_pidl);
2138 static HRESULT WINAPI IShellView2_fnSelectAndPositionItem(IShellView2* iface, LPCITEMIDLIST item, UINT flags, POINT *point)
2140 FIXME("(%p)->(item %p, flags %#x, point %p) stub!\n", iface, item, flags, point);
2144 static const IShellView2Vtbl svvt =
2146 IShellView_fnQueryInterface,
2147 IShellView_fnAddRef,
2148 IShellView_fnRelease,
2149 IShellView_fnGetWindow,
2150 IShellView_fnContextSensitiveHelp,
2151 IShellView_fnTranslateAccelerator,
2152 IShellView_fnEnableModeless,
2153 IShellView_fnUIActivate,
2154 IShellView_fnRefresh,
2155 IShellView_fnCreateViewWindow,
2156 IShellView_fnDestroyViewWindow,
2157 IShellView_fnGetCurrentInfo,
2158 IShellView_fnAddPropertySheetPages,
2159 IShellView_fnSaveViewState,
2160 IShellView_fnSelectItem,
2161 IShellView_fnGetItemObject,
2162 IShellView2_fnGetView,
2163 IShellView2_fnCreateViewWindow2,
2164 IShellView2_fnHandleRename,
2165 IShellView2_fnSelectAndPositionItem,
2169 /**********************************************************
2170 * ISVOleCmdTarget_QueryInterface (IUnknown)
2172 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2173 IOleCommandTarget * iface,
2177 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2179 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2182 /**********************************************************
2183 * ISVOleCmdTarget_AddRef (IUnknown)
2185 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2186 IOleCommandTarget * iface)
2188 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2190 return IShellFolder_AddRef((IShellFolder*)This);
2193 /**********************************************************
2194 * ISVOleCmdTarget_Release (IUnknown)
2196 static ULONG WINAPI ISVOleCmdTarget_Release(
2197 IOleCommandTarget * iface)
2199 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2201 return IShellFolder_Release((IShellFolder*)This);
2204 /**********************************************************
2205 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2207 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2208 IOleCommandTarget *iface,
2209 const GUID* pguidCmdGroup,
2212 OLECMDTEXT* pCmdText)
2215 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2217 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2218 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2222 for (i = 0; i < cCmds; i++)
2224 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2225 prgCmds[i].cmdf = 0;
2227 return OLECMDERR_E_UNKNOWNGROUP;
2230 /**********************************************************
2231 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2233 * nCmdID is the OLECMDID_* enumeration
2235 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2236 IOleCommandTarget *iface,
2237 const GUID* pguidCmdGroup,
2243 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2245 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2246 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2248 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2250 (nCmdexecopt == 4) && pvaOut)
2252 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2257 return OLECMDERR_E_UNKNOWNGROUP;
2260 static const IOleCommandTargetVtbl ctvt =
2262 ISVOleCmdTarget_QueryInterface,
2263 ISVOleCmdTarget_AddRef,
2264 ISVOleCmdTarget_Release,
2265 ISVOleCmdTarget_QueryStatus,
2266 ISVOleCmdTarget_Exec
2269 /**********************************************************
2270 * ISVDropTarget implementation
2273 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2278 IShellViewImpl *This = impl_from_IDropTarget(iface);
2280 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2282 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2285 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2287 IShellViewImpl *This = impl_from_IDropTarget(iface);
2289 TRACE("(%p)->(count=%u)\n",This,This->ref);
2291 return IShellFolder_AddRef((IShellFolder*)This);
2294 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2296 IShellViewImpl *This = impl_from_IDropTarget(iface);
2298 TRACE("(%p)->(count=%u)\n",This,This->ref);
2300 return IShellFolder_Release((IShellFolder*)This);
2303 /******************************************************************************
2304 * drag_notify_subitem [Internal]
2306 * Figure out the shellfolder object, which is currently under the mouse cursor
2307 * and notify it via the IDropTarget interface.
2310 #define SCROLLAREAWIDTH 20
2312 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2315 LVHITTESTINFO htinfo;
2321 /* Map from global to client coordinates and query the index of the listview-item, which is
2322 * currently under the mouse cursor. */
2325 htinfo.flags = LVHT_ONITEM;
2326 ScreenToClient(This->hWndList, &htinfo.pt);
2327 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2329 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2330 GetClientRect(This->hWndList, &clientRect);
2331 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2332 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2333 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2335 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2336 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2337 if (htinfo.pt.x < SCROLLAREAWIDTH)
2338 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2339 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2340 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2341 if (htinfo.pt.y < SCROLLAREAWIDTH)
2342 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2343 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2344 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2347 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2349 This->ptLastMousePos = htinfo.pt;
2351 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2352 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2353 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2355 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2356 if (This->pCurDropTarget) {
2357 IDropTarget_DragLeave(This->pCurDropTarget);
2358 IDropTarget_Release(This->pCurDropTarget);
2359 This->pCurDropTarget = NULL;
2362 This->iDragOverItem = lResult;
2363 if (lResult == -1) {
2364 /* We are not above one of the listview's subitems. Bind to the parent folder's
2365 * DropTarget interface. */
2366 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2367 (LPVOID*)&This->pCurDropTarget);
2369 /* Query the relative PIDL of the shellfolder object represented by the currently
2370 * dragged over listview-item ... */
2371 lvItem.mask = LVIF_PARAM;
2372 lvItem.iItem = lResult;
2373 lvItem.iSubItem = 0;
2374 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
2376 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2377 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2378 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2381 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2385 /* Notify the item just entered via DragEnter. */
2386 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2389 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2390 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2392 IShellViewImpl *This = impl_from_IDropTarget(iface);
2394 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2395 This->pCurDataObject = pDataObject;
2396 IDataObject_AddRef(pDataObject);
2398 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2401 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2404 IShellViewImpl *This = impl_from_IDropTarget(iface);
2405 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2408 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2409 IShellViewImpl *This = impl_from_IDropTarget(iface);
2411 IDropTarget_DragLeave(This->pCurDropTarget);
2413 IDropTarget_Release(This->pCurDropTarget);
2414 IDataObject_Release(This->pCurDataObject);
2415 This->pCurDataObject = NULL;
2416 This->pCurDropTarget = NULL;
2417 This->iDragOverItem = 0;
2422 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2423 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2425 IShellViewImpl *This = impl_from_IDropTarget(iface);
2427 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2429 IDropTarget_Release(This->pCurDropTarget);
2430 IDataObject_Release(This->pCurDataObject);
2431 This->pCurDataObject = NULL;
2432 This->pCurDropTarget = NULL;
2433 This->iDragOverItem = 0;
2438 static const IDropTargetVtbl dtvt =
2440 ISVDropTarget_QueryInterface,
2441 ISVDropTarget_AddRef,
2442 ISVDropTarget_Release,
2443 ISVDropTarget_DragEnter,
2444 ISVDropTarget_DragOver,
2445 ISVDropTarget_DragLeave,
2449 /**********************************************************
2450 * ISVDropSource implementation
2453 static HRESULT WINAPI ISVDropSource_QueryInterface(
2458 IShellViewImpl *This = impl_from_IDropSource(iface);
2460 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2462 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2465 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2467 IShellViewImpl *This = impl_from_IDropSource(iface);
2469 TRACE("(%p)->(count=%u)\n",This,This->ref);
2471 return IShellFolder_AddRef((IShellFolder*)This);
2474 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2476 IShellViewImpl *This = impl_from_IDropSource(iface);
2478 TRACE("(%p)->(count=%u)\n",This,This->ref);
2480 return IShellFolder_Release((IShellFolder*)This);
2482 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2484 BOOL fEscapePressed,
2487 IShellViewImpl *This = impl_from_IDropSource(iface);
2488 TRACE("(%p)\n",This);
2491 return DRAGDROP_S_CANCEL;
2492 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2493 return DRAGDROP_S_DROP;
2498 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2502 IShellViewImpl *This = impl_from_IDropSource(iface);
2503 TRACE("(%p)\n",This);
2505 return DRAGDROP_S_USEDEFAULTCURSORS;
2508 static const IDropSourceVtbl dsvt =
2510 ISVDropSource_QueryInterface,
2511 ISVDropSource_AddRef,
2512 ISVDropSource_Release,
2513 ISVDropSource_QueryContinueDrag,
2514 ISVDropSource_GiveFeedback
2516 /**********************************************************
2517 * ISVViewObject implementation
2520 static HRESULT WINAPI ISVViewObject_QueryInterface(
2525 IShellViewImpl *This = impl_from_IViewObject(iface);
2527 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2529 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2532 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2534 IShellViewImpl *This = impl_from_IViewObject(iface);
2536 TRACE("(%p)->(count=%u)\n",This,This->ref);
2538 return IShellFolder_AddRef((IShellFolder*)This);
2541 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2543 IShellViewImpl *This = impl_from_IViewObject(iface);
2545 TRACE("(%p)->(count=%u)\n",This,This->ref);
2547 return IShellFolder_Release((IShellFolder*)This);
2550 static HRESULT WINAPI ISVViewObject_Draw(
2555 DVTARGETDEVICE* ptd,
2558 LPCRECTL lprcBounds,
2559 LPCRECTL lprcWBounds,
2560 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2561 ULONG_PTR dwContinue)
2564 IShellViewImpl *This = impl_from_IViewObject(iface);
2566 FIXME("Stub: This=%p\n",This);
2570 static HRESULT WINAPI ISVViewObject_GetColorSet(
2575 DVTARGETDEVICE* ptd,
2576 HDC hicTargetDevice,
2577 LOGPALETTE** ppColorSet)
2580 IShellViewImpl *This = impl_from_IViewObject(iface);
2582 FIXME("Stub: This=%p\n",This);
2586 static HRESULT WINAPI ISVViewObject_Freeze(
2594 IShellViewImpl *This = impl_from_IViewObject(iface);
2596 FIXME("Stub: This=%p\n",This);
2600 static HRESULT WINAPI ISVViewObject_Unfreeze(
2605 IShellViewImpl *This = impl_from_IViewObject(iface);
2607 FIXME("Stub: This=%p\n",This);
2611 static HRESULT WINAPI ISVViewObject_SetAdvise(
2615 IAdviseSink* pAdvSink)
2618 IShellViewImpl *This = impl_from_IViewObject(iface);
2620 FIXME("partial stub: %p %08x %08x %p\n",
2621 This, aspects, advf, pAdvSink);
2623 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2624 This->pAdvSink = pAdvSink;
2625 This->dwAspects = aspects;
2626 This->dwAdvf = advf;
2631 static HRESULT WINAPI ISVViewObject_GetAdvise(
2635 IAdviseSink** ppAdvSink)
2638 IShellViewImpl *This = impl_from_IViewObject(iface);
2640 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2641 This, pAspects, pAdvf, ppAdvSink);
2645 IAdviseSink_AddRef( This->pAdvSink );
2646 *ppAdvSink = This->pAdvSink;
2649 *pAspects = This->dwAspects;
2651 *pAdvf = This->dwAdvf;
2657 static const IViewObjectVtbl vovt =
2659 ISVViewObject_QueryInterface,
2660 ISVViewObject_AddRef,
2661 ISVViewObject_Release,
2663 ISVViewObject_GetColorSet,
2664 ISVViewObject_Freeze,
2665 ISVViewObject_Unfreeze,
2666 ISVViewObject_SetAdvise,
2667 ISVViewObject_GetAdvise