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 = lParam1;
459 LPITEMIDLIST pItemIdList2 = 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 = SendMessageW(This->hWndList, LVM_GETITEMCOUNT, 0, 0); /*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==SendMessageW(This->hWndList, LVM_DELETEITEM, nIndex, 0))? 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 = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0);
840 This->apidl = 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(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 = 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 = 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 = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0);
1499 /* get selected item */
1502 /* get selected item */
1503 i = SendMessageW(This->hWndList, LVM_GETNEXTITEM, -1, MAKELPARAM (LVNI_SELECTED, 0));
1505 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1506 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
1510 TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1512 else if(plvKeyDown->wVKey == VK_DELETE)
1517 LPITEMIDLIST* pItems;
1520 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1526 if(!(i = SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0)))
1529 /* allocate memory for the pidl array */
1530 pItems = HeapAlloc(GetProcessHeap(), 0,
1531 sizeof(LPITEMIDLIST) * i);
1533 /* retrieve all selected items */
1536 while(SendMessageW(This->hWndList, LVM_GETSELECTEDCOUNT, 0, 0) > i)
1538 /* get selected item */
1539 item_index = SendMessageW(This->hWndList, LVM_GETNEXTITEM, item_index,
1540 MAKELPARAM (LVNI_SELECTED, 0));
1541 item.iItem = item_index;
1542 item.mask = LVIF_PARAM;
1543 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &item);
1546 pItems[i] = (LPITEMIDLIST)item.lParam;
1551 /* perform the item deletion */
1552 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1554 /* free pidl array memory */
1555 HeapFree(GetProcessHeap(), 0, pItems);
1558 /* Initiate a refresh */
1559 else if(plvKeyDown->wVKey == VK_F5)
1561 IShellView_Refresh((IShellView*)This);
1564 else if(plvKeyDown->wVKey == VK_BACK)
1566 LPSHELLBROWSER lpSb;
1567 if((lpSb = (LPSHELLBROWSER)SendMessageW(This->hWndParent, CWM_GETISHELLBROWSER, 0, 0)))
1569 IShellBrowser_BrowseObject(lpSb, NULL, SBSP_PARENT);
1574 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1579 TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1585 /**********************************************************
1586 * ShellView_OnChange()
1589 static LRESULT ShellView_OnChange(IShellViewImpl * This, const LPCITEMIDLIST * Pidls, LONG wEventId)
1592 TRACE("(%p)(%p,%p,0x%08x)\n", This, Pidls[0], Pidls[1], wEventId);
1597 LV_AddItem(This, Pidls[0]);
1601 LV_DeleteItem(This, Pidls[0]);
1603 case SHCNE_RENAMEFOLDER:
1604 case SHCNE_RENAMEITEM:
1605 LV_RenameItem(This, Pidls[0], Pidls[1]);
1607 case SHCNE_UPDATEITEM:
1612 /**********************************************************
1616 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1618 IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1619 LPCREATESTRUCTW lpcs;
1621 TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1626 lpcs = (LPCREATESTRUCTW)lParam;
1627 pThis = lpcs->lpCreateParams;
1628 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1629 pThis->hWnd = hWnd; /*set the window handle*/
1632 case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1633 case WM_SETFOCUS: return ShellView_OnSetFocus(pThis);
1634 case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis);
1635 case WM_CREATE: return ShellView_OnCreate(pThis);
1636 case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1637 case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1638 case WM_COMMAND: return ShellView_OnCommand(pThis,
1639 GET_WM_COMMAND_ID(wParam, lParam),
1640 GET_WM_COMMAND_CMD(wParam, lParam),
1641 GET_WM_COMMAND_HWND(wParam, lParam));
1642 case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (const LPCITEMIDLIST*)wParam, (LONG)lParam);
1644 case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1647 case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
1650 case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0);
1653 RevokeDragDrop(pThis->hWnd);
1654 SHChangeNotifyDeregister(pThis->hNotify);
1658 if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1659 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1664 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
1666 /**********************************************************
1669 * The INTERFACE of the IShellView object
1672 **********************************************************
1673 * IShellView_QueryInterface
1675 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView2 * iface,REFIID riid, LPVOID *ppvObj)
1677 IShellViewImpl *This = (IShellViewImpl *)iface;
1679 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1683 if(IsEqualIID(riid, &IID_IUnknown))
1687 else if(IsEqualIID(riid, &IID_IShellView))
1691 else if(IsEqualIID(riid, &IID_IShellView2))
1695 else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1697 *ppvObj = &This->lpvtblOleCommandTarget;
1699 else if(IsEqualIID(riid, &IID_IDropTarget))
1701 *ppvObj = &This->lpvtblDropTarget;
1703 else if(IsEqualIID(riid, &IID_IDropSource))
1705 *ppvObj = &This->lpvtblDropSource;
1707 else if(IsEqualIID(riid, &IID_IViewObject))
1709 *ppvObj = &This->lpvtblViewObject;
1714 IUnknown_AddRef( (IUnknown*)*ppvObj );
1715 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1718 TRACE("-- Interface: E_NOINTERFACE\n");
1719 return E_NOINTERFACE;
1722 /**********************************************************
1725 static ULONG WINAPI IShellView_fnAddRef(IShellView2 * iface)
1727 IShellViewImpl *This = (IShellViewImpl *)iface;
1728 ULONG refCount = InterlockedIncrement(&This->ref);
1730 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
1734 /**********************************************************
1735 * IShellView_Release
1737 static ULONG WINAPI IShellView_fnRelease(IShellView2 * iface)
1739 IShellViewImpl *This = (IShellViewImpl *)iface;
1740 ULONG refCount = InterlockedDecrement(&This->ref);
1742 TRACE("(%p)->(count=%i)\n", This, refCount + 1);
1746 TRACE(" destroying IShellView(%p)\n",This);
1748 DestroyWindow(This->hWndList);
1751 IShellFolder_Release(This->pSFParent);
1753 if(This->pSF2Parent)
1754 IShellFolder2_Release(This->pSF2Parent);
1756 SHFree(This->apidl);
1759 IAdviseSink_Release(This->pAdvSink);
1761 HeapFree(GetProcessHeap(),0,This);
1766 /**********************************************************
1767 * ShellView_GetWindow
1769 static HRESULT WINAPI IShellView_fnGetWindow(IShellView2 * iface,HWND * phWnd)
1771 IShellViewImpl *This = (IShellViewImpl *)iface;
1773 TRACE("(%p)\n",This);
1775 *phWnd = This->hWnd;
1780 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView2 * iface,BOOL fEnterMode)
1782 IShellViewImpl *This = (IShellViewImpl *)iface;
1784 FIXME("(%p) stub\n",This);
1789 /**********************************************************
1790 * IShellView_TranslateAccelerator
1793 * use the accel functions
1795 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView2 * iface,LPMSG lpmsg)
1798 IShellViewImpl *This = (IShellViewImpl *)iface;
1800 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1803 if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1805 TRACE("-- key=0x04%lx\n",lpmsg->wParam) ;
1807 return S_FALSE; /* not handled */
1810 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView2 * iface,BOOL fEnable)
1812 IShellViewImpl *This = (IShellViewImpl *)iface;
1814 FIXME("(%p) stub\n",This);
1819 static HRESULT WINAPI IShellView_fnUIActivate(IShellView2 * iface,UINT uState)
1821 IShellViewImpl *This = (IShellViewImpl *)iface;
1824 CHAR szName[MAX_PATH];
1827 int nPartArray[1] = {-1};
1829 TRACE("(%p)->(state=%x) stub\n",This, uState);
1831 /*don't do anything if the state isn't really changing*/
1832 if(This->uState == uState)
1837 /*OnActivate handles the menu merging and internal state*/
1838 ShellView_OnActivate(This, uState);
1840 /*only do This if we are active*/
1841 if(uState != SVUIA_DEACTIVATE)
1845 GetFolderPath is not a method of IShellFolder
1846 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1848 /* set the number of parts */
1849 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1850 (LPARAM)nPartArray, &lResult);
1852 /* set the text for the parts */
1854 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1855 0, (LPARAM)szName, &lResult);
1862 static HRESULT WINAPI IShellView_fnRefresh(IShellView2 * iface)
1864 IShellViewImpl *This = (IShellViewImpl *)iface;
1866 TRACE("(%p)\n",This);
1868 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
1869 ShellView_FillList(This);
1874 static HRESULT WINAPI IShellView_fnCreateViewWindow(IShellView2 *iface, IShellView *lpPrevView,
1875 LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd)
1878 SV2CVW2_PARAMS view_params;
1879 view_params.cbSize = sizeof(view_params);
1880 view_params.psvPrev = lpPrevView;
1881 view_params.pfs = lpfs;
1882 view_params.psbOwner = psb;
1883 view_params.prcView = prcView;
1884 view_params.pvid = NULL;
1885 view_params.hwndView = 0;
1887 TRACE("(%p) Forwarding to CreateViewWindow2\n", iface);
1889 hr = IShellView2_CreateViewWindow2(iface, &view_params);
1890 *phWnd = view_params.hwndView;
1895 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView2 * iface)
1897 IShellViewImpl *This = (IShellViewImpl *)iface;
1899 TRACE("(%p)\n",This);
1901 /*Make absolutely sure all our UI is cleaned up.*/
1902 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1906 DestroyMenu(This->hMenu);
1909 DestroyWindow(This->hWnd);
1910 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1911 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1917 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView2 * iface, LPFOLDERSETTINGS lpfs)
1919 IShellViewImpl *This = (IShellViewImpl *)iface;
1921 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1922 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1924 if (!lpfs) return E_INVALIDARG;
1926 *lpfs = This->FolderSettings;
1930 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView2 * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1932 IShellViewImpl *This = (IShellViewImpl *)iface;
1934 FIXME("(%p) stub\n",This);
1939 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView2 * iface)
1941 IShellViewImpl *This = (IShellViewImpl *)iface;
1943 FIXME("(%p) stub\n",This);
1948 static HRESULT WINAPI IShellView_fnSelectItem(
1949 IShellView2 * iface,
1953 IShellViewImpl *This = (IShellViewImpl *)iface;
1956 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
1958 i = LV_FindItemByPidl(This, pidl);
1964 if(uFlags & SVSI_ENSUREVISIBLE)
1965 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1967 lvItem.mask = LVIF_STATE;
1968 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
1970 lvItem.iSubItem = 0;
1972 while(SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem))
1974 if (lvItem.iItem == i)
1976 if (uFlags & SVSI_SELECT)
1977 lvItem.state |= LVIS_SELECTED;
1979 lvItem.state &= ~LVIS_SELECTED;
1981 if(uFlags & SVSI_FOCUSED)
1982 lvItem.state &= ~LVIS_FOCUSED;
1986 if (uFlags & SVSI_DESELECTOTHERS)
1987 lvItem.state &= ~LVIS_SELECTED;
1989 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
1994 if(uFlags & SVSI_EDIT)
1995 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
2001 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView2 * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
2003 IShellViewImpl *This = (IShellViewImpl *)iface;
2005 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2011 case SVGIO_BACKGROUND:
2012 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2015 case SVGIO_SELECTION:
2016 ShellView_GetSelections(This);
2017 IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2020 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2022 if(!*ppvOut) return E_OUTOFMEMORY;
2027 static HRESULT WINAPI IShellView2_fnGetView(IShellView2* iface, SHELLVIEWID *view_guid, ULONG view_type)
2029 FIXME("(%p)->(view_guid %s, view_type %#x) stub!\n", iface, debugstr_guid(view_guid), view_type);
2033 static HRESULT WINAPI IShellView2_fnCreateViewWindow2(IShellView2* iface, LPSV2CVW2_PARAMS view_params)
2035 IShellViewImpl *This = (IShellViewImpl *)iface;
2039 TRACE("(%p)->(view_params %p)\n", iface, view_params);
2041 if (view_params->cbSize != sizeof(*view_params))
2043 FIXME("Got unexpected cbSize %#x\n", view_params->cbSize);
2047 TRACE("-- psvPrev %p, pfs %p, psbOwner %p, prcView %p\n",
2048 view_params->psvPrev, view_params->pfs, view_params->psbOwner, view_params->prcView);
2049 TRACE("-- vmode %#x, flags %#x, left %d, top %d, right %d, bottom %d\n",
2050 view_params->pfs->ViewMode, view_params->pfs->fFlags, view_params->prcView->left,
2051 view_params->prcView->top, view_params->prcView->right, view_params->prcView->bottom);
2053 /* Set up the member variables */
2054 This->pShellBrowser = view_params->psbOwner;
2055 This->FolderSettings = *view_params->pfs;
2057 if (view_params->pvid)
2059 if (IsEqualGUID(view_params->pvid, &VID_LargeIcons))
2060 This->FolderSettings.ViewMode = FVM_ICON;
2061 else if (IsEqualGUID(view_params->pvid, &VID_SmallIcons))
2062 This->FolderSettings.ViewMode = FVM_SMALLICON;
2063 else if (IsEqualGUID(view_params->pvid, &VID_List))
2064 This->FolderSettings.ViewMode = FVM_LIST;
2065 else if (IsEqualGUID(view_params->pvid, &VID_Details))
2066 This->FolderSettings.ViewMode = FVM_DETAILS;
2067 else if (IsEqualGUID(view_params->pvid, &VID_Thumbnails))
2068 This->FolderSettings.ViewMode = FVM_THUMBNAIL;
2069 else if (IsEqualGUID(view_params->pvid, &VID_Tile))
2070 This->FolderSettings.ViewMode = FVM_TILE;
2071 else if (IsEqualGUID(view_params->pvid, &VID_ThumbStrip))
2072 This->FolderSettings.ViewMode = FVM_THUMBSTRIP;
2074 FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_params->pvid));
2077 /* Get our parent window */
2078 IShellBrowser_AddRef(This->pShellBrowser);
2079 IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
2081 /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
2082 This->pCommDlgBrowser = NULL;
2083 if (SUCCEEDED(IShellBrowser_QueryInterface(This->pShellBrowser, &IID_ICommDlgBrowser, (void **)&This->pCommDlgBrowser)))
2085 TRACE("-- CommDlgBrowser %p\n", This->pCommDlgBrowser);
2088 /* If our window class has not been registered, then do so */
2089 if (!GetClassInfoW(shell32_hInstance, SV_CLASS_NAME, &wc))
2091 ZeroMemory(&wc, sizeof(wc));
2092 wc.style = CS_HREDRAW | CS_VREDRAW;
2093 wc.lpfnWndProc = ShellView_WndProc;
2096 wc.hInstance = shell32_hInstance;
2098 wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
2099 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
2100 wc.lpszMenuName = NULL;
2101 wc.lpszClassName = SV_CLASS_NAME;
2103 if (!RegisterClassW(&wc)) return E_FAIL;
2106 wnd = CreateWindowExW(0, SV_CLASS_NAME, NULL, WS_CHILD | WS_TABSTOP,
2107 view_params->prcView->left, view_params->prcView->top,
2108 view_params->prcView->right - view_params->prcView->left,
2109 view_params->prcView->bottom - view_params->prcView->top,
2110 This->hWndParent, 0, shell32_hInstance, This);
2114 if (!wnd) return E_FAIL;
2116 SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
2119 view_params->hwndView = wnd;
2124 static HRESULT WINAPI IShellView2_fnHandleRename(IShellView2* iface, LPCITEMIDLIST new_pidl)
2126 FIXME("(%p)->(new_pidl %p) stub!\n", iface, new_pidl);
2130 static HRESULT WINAPI IShellView2_fnSelectAndPositionItem(IShellView2* iface, LPCITEMIDLIST item, UINT flags, POINT *point)
2132 FIXME("(%p)->(item %p, flags %#x, point %p) stub!\n", iface, item, flags, point);
2136 static const IShellView2Vtbl svvt =
2138 IShellView_fnQueryInterface,
2139 IShellView_fnAddRef,
2140 IShellView_fnRelease,
2141 IShellView_fnGetWindow,
2142 IShellView_fnContextSensitiveHelp,
2143 IShellView_fnTranslateAccelerator,
2144 IShellView_fnEnableModeless,
2145 IShellView_fnUIActivate,
2146 IShellView_fnRefresh,
2147 IShellView_fnCreateViewWindow,
2148 IShellView_fnDestroyViewWindow,
2149 IShellView_fnGetCurrentInfo,
2150 IShellView_fnAddPropertySheetPages,
2151 IShellView_fnSaveViewState,
2152 IShellView_fnSelectItem,
2153 IShellView_fnGetItemObject,
2154 IShellView2_fnGetView,
2155 IShellView2_fnCreateViewWindow2,
2156 IShellView2_fnHandleRename,
2157 IShellView2_fnSelectAndPositionItem,
2161 /**********************************************************
2162 * ISVOleCmdTarget_QueryInterface (IUnknown)
2164 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2165 IOleCommandTarget * iface,
2169 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2171 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2174 /**********************************************************
2175 * ISVOleCmdTarget_AddRef (IUnknown)
2177 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2178 IOleCommandTarget * iface)
2180 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2182 return IShellFolder_AddRef((IShellFolder*)This);
2185 /**********************************************************
2186 * ISVOleCmdTarget_Release (IUnknown)
2188 static ULONG WINAPI ISVOleCmdTarget_Release(
2189 IOleCommandTarget * iface)
2191 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2193 return IShellFolder_Release((IShellFolder*)This);
2196 /**********************************************************
2197 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2199 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2200 IOleCommandTarget *iface,
2201 const GUID* pguidCmdGroup,
2204 OLECMDTEXT* pCmdText)
2207 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2209 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2210 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2214 for (i = 0; i < cCmds; i++)
2216 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2217 prgCmds[i].cmdf = 0;
2219 return OLECMDERR_E_UNKNOWNGROUP;
2222 /**********************************************************
2223 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2225 * nCmdID is the OLECMDID_* enumeration
2227 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2228 IOleCommandTarget *iface,
2229 const GUID* pguidCmdGroup,
2235 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2237 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2238 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2240 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2242 (nCmdexecopt == 4) && pvaOut)
2244 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2249 return OLECMDERR_E_UNKNOWNGROUP;
2252 static const IOleCommandTargetVtbl ctvt =
2254 ISVOleCmdTarget_QueryInterface,
2255 ISVOleCmdTarget_AddRef,
2256 ISVOleCmdTarget_Release,
2257 ISVOleCmdTarget_QueryStatus,
2258 ISVOleCmdTarget_Exec
2261 /**********************************************************
2262 * ISVDropTarget implementation
2265 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2270 IShellViewImpl *This = impl_from_IDropTarget(iface);
2272 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2274 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2277 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2279 IShellViewImpl *This = impl_from_IDropTarget(iface);
2281 TRACE("(%p)->(count=%u)\n",This,This->ref);
2283 return IShellFolder_AddRef((IShellFolder*)This);
2286 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2288 IShellViewImpl *This = impl_from_IDropTarget(iface);
2290 TRACE("(%p)->(count=%u)\n",This,This->ref);
2292 return IShellFolder_Release((IShellFolder*)This);
2295 /******************************************************************************
2296 * drag_notify_subitem [Internal]
2298 * Figure out the shellfolder object, which is currently under the mouse cursor
2299 * and notify it via the IDropTarget interface.
2302 #define SCROLLAREAWIDTH 20
2304 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2307 LVHITTESTINFO htinfo;
2313 /* Map from global to client coordinates and query the index of the listview-item, which is
2314 * currently under the mouse cursor. */
2317 htinfo.flags = LVHT_ONITEM;
2318 ScreenToClient(This->hWndList, &htinfo.pt);
2319 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2321 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2322 GetClientRect(This->hWndList, &clientRect);
2323 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2324 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2325 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2327 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2328 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2329 if (htinfo.pt.x < SCROLLAREAWIDTH)
2330 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2331 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2332 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2333 if (htinfo.pt.y < SCROLLAREAWIDTH)
2334 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2335 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2336 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2339 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2341 This->ptLastMousePos = htinfo.pt;
2343 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2344 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2345 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2347 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2348 if (This->pCurDropTarget) {
2349 IDropTarget_DragLeave(This->pCurDropTarget);
2350 IDropTarget_Release(This->pCurDropTarget);
2351 This->pCurDropTarget = NULL;
2354 This->iDragOverItem = lResult;
2355 if (lResult == -1) {
2356 /* We are not above one of the listview's subitems. Bind to the parent folder's
2357 * DropTarget interface. */
2358 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2359 (LPVOID*)&This->pCurDropTarget);
2361 /* Query the relative PIDL of the shellfolder object represented by the currently
2362 * dragged over listview-item ... */
2363 lvItem.mask = LVIF_PARAM;
2364 lvItem.iItem = lResult;
2365 lvItem.iSubItem = 0;
2366 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
2368 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2369 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2370 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2373 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2377 /* Notify the item just entered via DragEnter. */
2378 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2381 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2382 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2384 IShellViewImpl *This = impl_from_IDropTarget(iface);
2386 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2387 This->pCurDataObject = pDataObject;
2388 IDataObject_AddRef(pDataObject);
2390 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2393 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2396 IShellViewImpl *This = impl_from_IDropTarget(iface);
2397 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2400 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2401 IShellViewImpl *This = impl_from_IDropTarget(iface);
2403 IDropTarget_DragLeave(This->pCurDropTarget);
2405 IDropTarget_Release(This->pCurDropTarget);
2406 IDataObject_Release(This->pCurDataObject);
2407 This->pCurDataObject = NULL;
2408 This->pCurDropTarget = NULL;
2409 This->iDragOverItem = 0;
2414 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2415 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2417 IShellViewImpl *This = impl_from_IDropTarget(iface);
2419 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2421 IDropTarget_Release(This->pCurDropTarget);
2422 IDataObject_Release(This->pCurDataObject);
2423 This->pCurDataObject = NULL;
2424 This->pCurDropTarget = NULL;
2425 This->iDragOverItem = 0;
2430 static const IDropTargetVtbl dtvt =
2432 ISVDropTarget_QueryInterface,
2433 ISVDropTarget_AddRef,
2434 ISVDropTarget_Release,
2435 ISVDropTarget_DragEnter,
2436 ISVDropTarget_DragOver,
2437 ISVDropTarget_DragLeave,
2441 /**********************************************************
2442 * ISVDropSource implementation
2445 static HRESULT WINAPI ISVDropSource_QueryInterface(
2450 IShellViewImpl *This = impl_from_IDropSource(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 ISVDropSource_AddRef( IDropSource *iface)
2459 IShellViewImpl *This = impl_from_IDropSource(iface);
2461 TRACE("(%p)->(count=%u)\n",This,This->ref);
2463 return IShellFolder_AddRef((IShellFolder*)This);
2466 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2468 IShellViewImpl *This = impl_from_IDropSource(iface);
2470 TRACE("(%p)->(count=%u)\n",This,This->ref);
2472 return IShellFolder_Release((IShellFolder*)This);
2474 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2476 BOOL fEscapePressed,
2479 IShellViewImpl *This = impl_from_IDropSource(iface);
2480 TRACE("(%p)\n",This);
2483 return DRAGDROP_S_CANCEL;
2484 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2485 return DRAGDROP_S_DROP;
2490 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2494 IShellViewImpl *This = impl_from_IDropSource(iface);
2495 TRACE("(%p)\n",This);
2497 return DRAGDROP_S_USEDEFAULTCURSORS;
2500 static const IDropSourceVtbl dsvt =
2502 ISVDropSource_QueryInterface,
2503 ISVDropSource_AddRef,
2504 ISVDropSource_Release,
2505 ISVDropSource_QueryContinueDrag,
2506 ISVDropSource_GiveFeedback
2508 /**********************************************************
2509 * ISVViewObject implementation
2512 static HRESULT WINAPI ISVViewObject_QueryInterface(
2517 IShellViewImpl *This = impl_from_IViewObject(iface);
2519 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2521 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2524 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2526 IShellViewImpl *This = impl_from_IViewObject(iface);
2528 TRACE("(%p)->(count=%u)\n",This,This->ref);
2530 return IShellFolder_AddRef((IShellFolder*)This);
2533 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2535 IShellViewImpl *This = impl_from_IViewObject(iface);
2537 TRACE("(%p)->(count=%u)\n",This,This->ref);
2539 return IShellFolder_Release((IShellFolder*)This);
2542 static HRESULT WINAPI ISVViewObject_Draw(
2547 DVTARGETDEVICE* ptd,
2550 LPCRECTL lprcBounds,
2551 LPCRECTL lprcWBounds,
2552 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2553 ULONG_PTR dwContinue)
2556 IShellViewImpl *This = impl_from_IViewObject(iface);
2558 FIXME("Stub: This=%p\n",This);
2562 static HRESULT WINAPI ISVViewObject_GetColorSet(
2567 DVTARGETDEVICE* ptd,
2568 HDC hicTargetDevice,
2569 LOGPALETTE** ppColorSet)
2572 IShellViewImpl *This = impl_from_IViewObject(iface);
2574 FIXME("Stub: This=%p\n",This);
2578 static HRESULT WINAPI ISVViewObject_Freeze(
2586 IShellViewImpl *This = impl_from_IViewObject(iface);
2588 FIXME("Stub: This=%p\n",This);
2592 static HRESULT WINAPI ISVViewObject_Unfreeze(
2597 IShellViewImpl *This = impl_from_IViewObject(iface);
2599 FIXME("Stub: This=%p\n",This);
2603 static HRESULT WINAPI ISVViewObject_SetAdvise(
2607 IAdviseSink* pAdvSink)
2610 IShellViewImpl *This = impl_from_IViewObject(iface);
2612 FIXME("partial stub: %p %08x %08x %p\n",
2613 This, aspects, advf, pAdvSink);
2615 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2616 This->pAdvSink = pAdvSink;
2617 This->dwAspects = aspects;
2618 This->dwAdvf = advf;
2623 static HRESULT WINAPI ISVViewObject_GetAdvise(
2627 IAdviseSink** ppAdvSink)
2630 IShellViewImpl *This = impl_from_IViewObject(iface);
2632 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2633 This, pAspects, pAdvf, ppAdvSink);
2637 IAdviseSink_AddRef( This->pAdvSink );
2638 *ppAdvSink = This->pAdvSink;
2641 *pAspects = This->dwAspects;
2643 *pAdvf = This->dwAdvf;
2649 static const IViewObjectVtbl vovt =
2651 ISVViewObject_QueryInterface,
2652 ISVViewObject_AddRef,
2653 ISVViewObject_Release,
2655 ISVViewObject_GetColorSet,
2656 ISVViewObject_Freeze,
2657 ISVViewObject_Unfreeze,
2658 ISVViewObject_SetAdvise,
2659 ISVViewObject_GetAdvise