dsound Add uninitialized check.
[wine/wine64.git] / dlls / shell32 / shlview.c
bloba887c6efdac951659ac59b395844594317113913
1 /*
2 * ShellView
4 * Copyright 1998,1999 <juergen.schmied@debitel.net>
6 * This is the view visualizing the data provied by the shellfolder.
7 * No direct access to data from pidls should be done from here.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * FIXME: The order by part of the background context menu should be
24 * buily according to the columns shown.
26 * FIXME: Load/Save the view state from/into the stream provied by
27 * the ShellBrowser
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
36 * Release() ???
39 #include "config.h"
40 #include "wine/port.h"
42 #include <stdarg.h>
43 #include <stdlib.h>
44 #include <string.h>
46 #define COBJMACROS
47 #define NONAMELESSUNION
48 #define NONAMELESSSTRUCT
50 #include "windef.h"
51 #include "winerror.h"
52 #include "winbase.h"
53 #include "winnls.h"
54 #include "objbase.h"
55 #include "servprov.h"
56 #include "shlguid.h"
57 #include "wingdi.h"
58 #include "winuser.h"
59 #include "shlobj.h"
60 #include "undocshell.h"
61 #include "shresdef.h"
62 #include "wine/debug.h"
64 #include "docobj.h"
65 #include "pidl.h"
66 #include "shell32_main.h"
67 #include "shellfolder.h"
69 WINE_DEFAULT_DEBUG_CHANNEL(shell);
71 typedef struct
72 { BOOL bIsAscending;
73 INT nHeaderID;
74 INT nLastHeaderID;
75 }LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;
77 typedef struct
79 const IShellViewVtbl* lpVtbl;
80 LONG ref;
81 const IOleCommandTargetVtbl* lpvtblOleCommandTarget;
82 const IDropTargetVtbl* lpvtblDropTarget;
83 const IDropSourceVtbl* lpvtblDropSource;
84 const IViewObjectVtbl* lpvtblViewObject;
85 IShellFolder* pSFParent;
86 IShellFolder2* pSF2Parent;
87 IShellBrowser* pShellBrowser;
88 ICommDlgBrowser* pCommDlgBrowser;
89 HWND hWnd; /* SHELLDLL_DefView */
90 HWND hWndList; /* ListView control */
91 HWND hWndParent;
92 FOLDERSETTINGS FolderSettings;
93 HMENU hMenu;
94 UINT uState;
95 UINT cidl;
96 LPITEMIDLIST *apidl;
97 LISTVIEW_SORT_INFO ListViewSortInfo;
98 ULONG hNotify; /* change notification handle */
99 HANDLE hAccel;
100 DWORD dwAspects;
101 DWORD dwAdvf;
102 IAdviseSink *pAdvSink;
103 IDropTarget* pCurDropTarget; /* The sub-item, which is currently dragged over */
104 IDataObject* pCurDataObject; /* The dragged data-object */
105 LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */
106 UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
107 POINT ptLastMousePos; /* Mouse position at last DragOver call */
108 } IShellViewImpl;
110 static const IShellViewVtbl svvt;
111 static const IOleCommandTargetVtbl ctvt;
112 static const IDropTargetVtbl dtvt;
113 static const IDropSourceVtbl dsvt;
114 static const IViewObjectVtbl vovt;
117 static inline IShellViewImpl *impl_from_IOleCommandTarget( IOleCommandTarget *iface )
119 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblOleCommandTarget));
122 static inline IShellViewImpl *impl_from_IDropTarget( IDropTarget *iface )
124 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropTarget));
127 static inline IShellViewImpl *impl_from_IDropSource( IDropSource *iface )
129 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropSource));
132 static inline IShellViewImpl *impl_from_IViewObject( IViewObject *iface )
134 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblViewObject));
137 /* ListView Header ID's */
138 #define LISTVIEW_COLUMN_NAME 0
139 #define LISTVIEW_COLUMN_SIZE 1
140 #define LISTVIEW_COLUMN_TYPE 2
141 #define LISTVIEW_COLUMN_TIME 3
142 #define LISTVIEW_COLUMN_ATTRIB 4
144 /*menu items */
145 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
146 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
147 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
149 #define ID_LISTVIEW 2000
151 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
153 /*windowsx.h */
154 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
155 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
156 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
159 Items merged into the toolbar and and the filemenu
161 typedef struct
162 { int idCommand;
163 int iImage;
164 int idButtonString;
165 int idMenuString;
166 BYTE bState;
167 BYTE bStyle;
168 } MYTOOLINFO, *LPMYTOOLINFO;
170 MYTOOLINFO Tools[] =
172 { FCIDM_SHVIEW_BIGICON, 0, 0, IDS_VIEW_LARGE, TBSTATE_ENABLED, BTNS_BUTTON },
173 { FCIDM_SHVIEW_SMALLICON, 0, 0, IDS_VIEW_SMALL, TBSTATE_ENABLED, BTNS_BUTTON },
174 { FCIDM_SHVIEW_LISTVIEW, 0, 0, IDS_VIEW_LIST, TBSTATE_ENABLED, BTNS_BUTTON },
175 { FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON },
176 { -1, 0, 0, 0, 0, 0}
179 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
181 /**********************************************************
182 * IShellView_Constructor
184 IShellView * IShellView_Constructor( IShellFolder * pFolder)
185 { IShellViewImpl * sv;
186 sv=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellViewImpl));
187 sv->ref=1;
188 sv->lpVtbl=&svvt;
189 sv->lpvtblOleCommandTarget=&ctvt;
190 sv->lpvtblDropTarget=&dtvt;
191 sv->lpvtblDropSource=&dsvt;
192 sv->lpvtblViewObject=&vovt;
194 sv->pSFParent = pFolder;
195 if(pFolder) IShellFolder_AddRef(pFolder);
196 IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent);
198 sv->pCurDropTarget = NULL;
199 sv->pCurDataObject = NULL;
200 sv->iDragOverItem = 0;
201 sv->cScrollDelay = 0;
202 sv->ptLastMousePos.x = 0;
203 sv->ptLastMousePos.y = 0;
205 TRACE("(%p)->(%p)\n",sv, pFolder);
206 return (IShellView *) sv;
209 /**********************************************************
211 * ##### helperfunctions for communication with ICommDlgBrowser #####
213 static BOOL IsInCommDlg(IShellViewImpl * This)
214 { return(This->pCommDlgBrowser != NULL);
217 static HRESULT IncludeObject(IShellViewImpl * This, LPCITEMIDLIST pidl)
219 HRESULT ret = S_OK;
221 if ( IsInCommDlg(This) )
223 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
224 ret = ICommDlgBrowser_IncludeObject(This->pCommDlgBrowser, (IShellView*)This, pidl);
225 TRACE("--0x%08lx\n", ret);
227 return ret;
230 static HRESULT OnDefaultCommand(IShellViewImpl * This)
232 HRESULT ret = S_FALSE;
234 if (IsInCommDlg(This))
236 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
237 ret = ICommDlgBrowser_OnDefaultCommand(This->pCommDlgBrowser, (IShellView*)This);
238 TRACE("-- returns %08lx\n", ret);
240 return ret;
243 static HRESULT OnStateChange(IShellViewImpl * This, UINT uFlags)
245 HRESULT ret = S_FALSE;
247 if (IsInCommDlg(This))
249 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
250 ret = ICommDlgBrowser_OnStateChange(This->pCommDlgBrowser, (IShellView*)This, uFlags);
251 TRACE("--\n");
253 return ret;
255 /**********************************************************
256 * set the toolbar of the filedialog buttons
258 * - activates the buttons from the shellbrowser according to
259 * the view state
261 static void CheckToolbar(IShellViewImpl * This)
263 LRESULT result;
265 TRACE("\n");
267 if (IsInCommDlg(This))
269 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
270 FCIDM_TB_SMALLICON, (This->FolderSettings.ViewMode==FVM_LIST)? TRUE : FALSE, &result);
271 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
272 FCIDM_TB_REPORTVIEW, (This->FolderSettings.ViewMode==FVM_DETAILS)? TRUE : FALSE, &result);
273 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
274 FCIDM_TB_SMALLICON, TRUE, &result);
275 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
276 FCIDM_TB_REPORTVIEW, TRUE, &result);
280 /**********************************************************
282 * ##### helperfunctions for initializing the view #####
284 /**********************************************************
285 * change the style of the listview control
287 static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove)
289 DWORD tmpstyle;
291 TRACE("(%p)\n", This);
293 tmpstyle = GetWindowLongA(This->hWndList, GWL_STYLE);
294 SetWindowLongA(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
297 /**********************************************************
298 * ShellView_CreateList()
300 * - creates the list view window
302 static BOOL ShellView_CreateList (IShellViewImpl * This)
303 { DWORD dwStyle, dwExStyle;
305 TRACE("%p\n",This);
307 dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
308 LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT | LVS_AUTOARRANGE;
309 dwExStyle = WS_EX_CLIENTEDGE;
311 switch (This->FolderSettings.ViewMode)
313 case FVM_ICON: dwStyle |= LVS_ICON; break;
314 case FVM_DETAILS: dwStyle |= LVS_REPORT; break;
315 case FVM_SMALLICON: dwStyle |= LVS_SMALLICON; break;
316 case FVM_LIST: dwStyle |= LVS_LIST; break;
317 default: dwStyle |= LVS_LIST; break;
320 if (This->FolderSettings.fFlags & FWF_AUTOARRANGE) dwStyle |= LVS_AUTOARRANGE;
321 if (This->FolderSettings.fFlags & FWF_DESKTOP)
322 This->FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
323 if (This->FolderSettings.fFlags & FWF_SINGLESEL) dwStyle |= LVS_SINGLESEL;
324 if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE)
325 dwExStyle &= ~WS_EX_CLIENTEDGE;
327 This->hWndList=CreateWindowExA( dwExStyle,
328 WC_LISTVIEWA,
329 NULL,
330 dwStyle,
331 0,0,0,0,
332 This->hWnd,
333 (HMENU)ID_LISTVIEW,
334 shell32_hInstance,
335 NULL);
337 if(!This->hWndList)
338 return FALSE;
340 This->ListViewSortInfo.bIsAscending = TRUE;
341 This->ListViewSortInfo.nHeaderID = -1;
342 This->ListViewSortInfo.nLastHeaderID = -1;
344 if (This->FolderSettings.fFlags & FWF_DESKTOP) {
345 if (0) /* FIXME: look into registry vale HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow and activate drop shadows */
346 ListView_SetTextBkColor(This->hWndList, CLR_NONE);
347 else
348 ListView_SetTextBkColor(This->hWndList, GetSysColor(COLOR_DESKTOP));
350 ListView_SetTextColor(This->hWndList, RGB(255,255,255));
353 /* UpdateShellSettings(); */
354 return TRUE;
357 /**********************************************************
358 * ShellView_InitList()
360 * - adds all needed columns to the shellview
362 static BOOL ShellView_InitList(IShellViewImpl * This)
364 LVCOLUMNA lvColumn;
365 SHELLDETAILS sd;
366 int i;
367 char szTemp[50];
369 TRACE("%p\n",This);
371 ListView_DeleteAllItems(This->hWndList);
373 lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
374 lvColumn.pszText = szTemp;
376 if (This->pSF2Parent)
378 for (i=0; 1; i++)
380 if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd)))
381 break;
382 lvColumn.fmt = sd.fmt;
383 lvColumn.cx = sd.cxChar*8; /* chars->pixel */
384 StrRetToStrNA( szTemp, 50, &sd.str, NULL);
385 ListView_InsertColumnA(This->hWndList, i, &lvColumn);
388 else
390 FIXME("no SF2\n");
393 ListView_SetImageList(This->hWndList, ShellSmallIconList, LVSIL_SMALL);
394 ListView_SetImageList(This->hWndList, ShellBigIconList, LVSIL_NORMAL);
396 return TRUE;
398 /**********************************************************
399 * ShellView_CompareItems()
401 * NOTES
402 * internal, CALLBACK for DSA_Sort
404 static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
406 int ret;
407 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
409 if(!lpData) return 0;
411 ret = (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2));
412 TRACE("ret=%i\n",ret);
413 return ret;
416 /*************************************************************************
417 * ShellView_ListViewCompareItems
419 * Compare Function for the Listview (FileOpen Dialog)
421 * PARAMS
422 * lParam1 [I] the first ItemIdList to compare with
423 * lParam2 [I] the second ItemIdList to compare with
424 * lpData [I] The column ID for the header Ctrl to process
426 * RETURNS
427 * A negative value if the first item should precede the second,
428 * a positive value if the first item should follow the second,
429 * or zero if the two items are equivalent
431 * NOTES
432 * FIXME: function does what ShellView_CompareItems is supposed to do.
433 * unify it and figure out how to use the undocumented first parameter
434 * of IShellFolder_CompareIDs to do the job this function does and
435 * move this code to IShellFolder.
436 * make LISTVIEW_SORT_INFO obsolete
437 * the way this function works is only usable if we had only
438 * filesystemfolders (25/10/99 jsch)
440 static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
442 INT nDiff=0;
443 FILETIME fd1, fd2;
444 char strName1[MAX_PATH], strName2[MAX_PATH];
445 BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
446 LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1;
447 LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2;
448 LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData;
451 bIsFolder1 = _ILIsFolder(pItemIdList1);
452 bIsFolder2 = _ILIsFolder(pItemIdList2);
453 bIsBothFolder = bIsFolder1 && bIsFolder2;
455 /* When sorting between a File and a Folder, the Folder gets sorted first */
456 if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
458 nDiff = bIsFolder1 ? -1 : 1;
460 else
462 /* Sort by Time: Folders or Files can be sorted */
464 if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
466 _ILGetFileDateTime(pItemIdList1, &fd1);
467 _ILGetFileDateTime(pItemIdList2, &fd2);
468 nDiff = CompareFileTime(&fd2, &fd1);
470 /* Sort by Attribute: Folder or Files can be sorted */
471 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
473 _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH);
474 _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH);
475 nDiff = lstrcmpiA(strName1, strName2);
477 /* Sort by FileName: Folder or Files can be sorted */
478 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
480 /* Sort by Text */
481 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
482 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
483 nDiff = lstrcmpiA(strName1, strName2);
485 /* Sort by File Size, Only valid for Files */
486 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
488 nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0));
490 /* Sort by File Type, Only valid for Files */
491 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
493 /* Sort by Type */
494 _ILGetFileType(pItemIdList1, strName1, MAX_PATH);
495 _ILGetFileType(pItemIdList2, strName2, MAX_PATH);
496 nDiff = lstrcmpiA(strName1, strName2);
499 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
501 if(nDiff == 0)
503 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
504 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
505 nDiff = lstrcmpiA(strName1, strName2);
508 if(!pSortInfo->bIsAscending)
510 nDiff = -nDiff;
513 return nDiff;
517 /**********************************************************
518 * LV_FindItemByPidl()
520 static int LV_FindItemByPidl(
521 IShellViewImpl * This,
522 LPCITEMIDLIST pidl)
524 LVITEMA lvItem;
525 ZeroMemory(&lvItem, sizeof(LVITEMA));
526 lvItem.mask = LVIF_PARAM;
527 for(lvItem.iItem = 0; ListView_GetItemA(This->hWndList, &lvItem); lvItem.iItem++)
529 LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam;
530 HRESULT hr = IShellFolder_CompareIDs(This->pSFParent, 0, pidl, currentpidl);
531 if(SUCCEEDED(hr) && !HRESULT_CODE(hr))
533 return lvItem.iItem;
536 return -1;
539 /**********************************************************
540 * LV_AddItem()
542 static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
544 LVITEMA lvItem;
546 TRACE("(%p)(pidl=%p)\n", This, pidl);
548 ZeroMemory(&lvItem, sizeof(lvItem)); /* create the listview item*/
549 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/
550 lvItem.iItem = ListView_GetItemCount(This->hWndList); /*add the item to the end of the list*/
551 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/
552 lvItem.pszText = LPSTR_TEXTCALLBACKA; /*get text on a callback basis*/
553 lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/
554 return (-1==ListView_InsertItemA(This->hWndList, &lvItem))? FALSE: TRUE;
557 /**********************************************************
558 * LV_DeleteItem()
560 static BOOLEAN LV_DeleteItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
562 int nIndex;
564 TRACE("(%p)(pidl=%p)\n", This, pidl);
566 nIndex = LV_FindItemByPidl(This, ILFindLastID(pidl));
567 return (-1==ListView_DeleteItem(This->hWndList, nIndex))? FALSE: TRUE;
570 /**********************************************************
571 * LV_RenameItem()
573 static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew )
575 int nItem;
576 LVITEMA lvItem;
578 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew);
580 nItem = LV_FindItemByPidl(This, ILFindLastID(pidlOld));
581 if ( -1 != nItem )
583 ZeroMemory(&lvItem, sizeof(lvItem)); /* create the listview item*/
584 lvItem.mask = LVIF_PARAM; /* only the pidl */
585 lvItem.iItem = nItem;
586 ListView_GetItemA(This->hWndList, &lvItem);
588 SHFree((LPITEMIDLIST)lvItem.lParam);
589 lvItem.mask = LVIF_PARAM;
590 lvItem.iItem = nItem;
591 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */
592 ListView_SetItemA(This->hWndList, &lvItem);
593 ListView_Update(This->hWndList, nItem);
594 return TRUE; /* FIXME: better handling */
596 return FALSE;
598 /**********************************************************
599 * ShellView_FillList()
601 * - gets the objectlist from the shellfolder
602 * - sorts the list
603 * - fills the list into the view
606 static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg )
608 LPITEMIDLIST pidl = ptr;
609 IShellViewImpl *This = arg;
610 /* in a commdlg This works as a filemask*/
611 if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl);
612 SHFree(pidl);
613 return TRUE;
616 static HRESULT ShellView_FillList(IShellViewImpl * This)
618 LPENUMIDLIST pEnumIDList;
619 LPITEMIDLIST pidl;
620 DWORD dwFetched;
621 HRESULT hRes;
622 HDPA hdpa;
624 TRACE("%p\n",This);
626 /* get the itemlist from the shfolder*/
627 hRes = IShellFolder_EnumObjects(This->pSFParent,This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
628 if (hRes != S_OK)
630 if (hRes==S_FALSE)
631 return(NOERROR);
632 return(hRes);
635 /* create a pointer array */
636 hdpa = DPA_Create(16);
637 if (!hdpa)
639 return(E_OUTOFMEMORY);
642 /* copy the items into the array*/
643 while((S_OK == IEnumIDList_Next(pEnumIDList,1, &pidl, &dwFetched)) && dwFetched)
645 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
647 SHFree(pidl);
651 /* sort the array */
652 DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent);
654 /*turn the listview's redrawing off*/
655 SendMessageA(This->hWndList, WM_SETREDRAW, FALSE, 0);
657 DPA_DestroyCallback( hdpa, fill_list, This );
659 /*turn the listview's redrawing back on and force it to draw*/
660 SendMessageA(This->hWndList, WM_SETREDRAW, TRUE, 0);
662 IEnumIDList_Release(pEnumIDList); /* destroy the list*/
664 return S_OK;
667 /**********************************************************
668 * ShellView_OnCreate()
670 static LRESULT ShellView_OnCreate(IShellViewImpl * This)
672 IDropTarget* pdt;
673 SHChangeNotifyEntry ntreg;
674 IPersistFolder2 * ppf2 = NULL;
676 TRACE("%p\n",This);
678 if(ShellView_CreateList(This))
680 if(ShellView_InitList(This))
682 ShellView_FillList(This);
686 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown*)&This->lpVtbl, &IID_IDropTarget, (LPVOID*)&pdt)))
688 RegisterDragDrop(This->hWnd, pdt);
689 IDropTarget_Release(pdt);
692 /* register for receiving notifications */
693 IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
694 if (ppf2)
696 IPersistFolder2_GetCurFolder(ppf2, (LPITEMIDLIST*)&ntreg.pidl);
697 ntreg.fRecursive = TRUE;
698 This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
699 SHFree((LPITEMIDLIST)ntreg.pidl);
700 IPersistFolder2_Release(ppf2);
703 This->hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel");
705 return S_OK;
708 /**********************************************************
709 * #### Handling of the menus ####
712 /**********************************************************
713 * ShellView_BuildFileMenu()
715 static HMENU ShellView_BuildFileMenu(IShellViewImpl * This)
716 { CHAR szText[MAX_PATH];
717 MENUITEMINFOA mii;
718 int nTools,i;
719 HMENU hSubMenu;
721 TRACE("(%p)\n",This);
723 hSubMenu = CreatePopupMenu();
724 if(hSubMenu)
725 { /*get the number of items in our global array*/
726 for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
728 /*add the menu items*/
729 for(i = 0; i < nTools; i++)
731 LoadStringA(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
733 ZeroMemory(&mii, sizeof(mii));
734 mii.cbSize = sizeof(mii);
735 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
737 if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
739 mii.fType = MFT_STRING;
740 mii.fState = MFS_ENABLED;
741 mii.dwTypeData = szText;
742 mii.wID = Tools[i].idCommand;
744 else
746 mii.fType = MFT_SEPARATOR;
748 /* tack This item onto the end of the menu */
749 InsertMenuItemA(hSubMenu, (UINT)-1, TRUE, &mii);
752 TRACE("-- return (menu=%p)\n",hSubMenu);
753 return hSubMenu;
755 /**********************************************************
756 * ShellView_MergeFileMenu()
758 static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu)
759 { TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu);
761 if(hSubMenu)
762 { /*insert This item at the beginning of the menu */
763 _InsertMenuItem(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
764 _InsertMenuItem(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, "dummy45", MFS_ENABLED);
767 TRACE("--\n");
770 /**********************************************************
771 * ShellView_MergeViewMenu()
774 static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu)
775 { MENUITEMINFOA mii;
777 TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
779 if(hSubMenu)
780 { /*add a separator at the correct position in the menu*/
781 _InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
783 ZeroMemory(&mii, sizeof(mii));
784 mii.cbSize = sizeof(mii);
785 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
786 mii.fType = MFT_STRING;
787 mii.dwTypeData = "View";
788 mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
789 InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
793 /**********************************************************
794 * ShellView_GetSelections()
796 * - fills the this->apidl list with the selected objects
798 * RETURNS
799 * number of selected items
801 static UINT ShellView_GetSelections(IShellViewImpl * This)
803 LVITEMA lvItem;
804 UINT i = 0;
806 if (This->apidl)
808 SHFree(This->apidl);
811 This->cidl = ListView_GetSelectedCount(This->hWndList);
812 This->apidl = (LPITEMIDLIST*)SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
814 TRACE("selected=%i\n", This->cidl);
816 if(This->apidl)
818 TRACE("-- Items selected =%u\n", This->cidl);
820 ZeroMemory(&lvItem, sizeof(lvItem));
821 lvItem.mask = LVIF_STATE | LVIF_PARAM;
822 lvItem.stateMask = LVIS_SELECTED;
824 while(ListView_GetItemA(This->hWndList, &lvItem) && (i < This->cidl))
826 if(lvItem.state & LVIS_SELECTED)
828 This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
829 i++;
830 TRACE("-- selected Item found\n");
832 lvItem.iItem++;
835 return This->cidl;
839 /**********************************************************
840 * ShellView_OpenSelectedItems()
842 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
844 static UINT CF_IDLIST = 0;
845 HRESULT hr;
846 IDataObject* selection;
847 FORMATETC fetc;
848 STGMEDIUM stgm;
849 LPIDA pIDList;
850 LPCITEMIDLIST parent_pidl;
851 int i;
853 if (0 == ShellView_GetSelections(This))
855 return S_OK;
857 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
858 (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
859 0, (LPVOID *)&selection);
860 if (FAILED(hr))
861 return hr;
863 if (0 == CF_IDLIST)
865 CF_IDLIST = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
867 fetc.cfFormat = CF_IDLIST;
868 fetc.ptd = NULL;
869 fetc.dwAspect = DVASPECT_CONTENT;
870 fetc.lindex = -1;
871 fetc.tymed = TYMED_HGLOBAL;
873 hr = IDataObject_QueryGetData(selection, &fetc);
874 if (FAILED(hr))
875 return hr;
877 hr = IDataObject_GetData(selection, &fetc, &stgm);
878 if (FAILED(hr))
879 return hr;
881 pIDList = GlobalLock(stgm.u.hGlobal);
883 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
884 for (i = pIDList->cidl; i > 0; --i)
886 LPCITEMIDLIST pidl;
887 SFGAOF attribs;
889 pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
891 attribs = SFGAO_FOLDER;
892 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
894 if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
896 SHELLEXECUTEINFOA shexinfo;
898 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOA);
899 shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */
900 shexinfo.hwnd = NULL;
901 shexinfo.lpVerb = NULL;
902 shexinfo.lpFile = NULL;
903 shexinfo.lpParameters = NULL;
904 shexinfo.lpDirectory = NULL;
905 shexinfo.nShow = SW_NORMAL;
906 shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
908 ShellExecuteExA(&shexinfo); /* Discard error/success info */
910 ILFree((LPITEMIDLIST)shexinfo.lpIDList);
914 GlobalUnlock(stgm.u.hGlobal);
915 ReleaseStgMedium(&stgm);
917 IDataObject_Release(selection);
919 return S_OK;
922 /**********************************************************
923 * ShellView_DoContextMenu()
925 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
926 { UINT uCommand;
927 DWORD wFlags;
928 HMENU hMenu;
929 BOOL fExplore = FALSE;
930 HWND hwndTree = 0;
931 LPCONTEXTMENU pContextMenu = NULL;
932 IContextMenu2 *pCM = NULL;
933 CMINVOKECOMMANDINFO cmi;
935 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
937 /* look, what's selected and create a context menu object of it*/
938 if( ShellView_GetSelections(This) )
940 IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
941 (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
943 if(pContextMenu)
945 TRACE("-- pContextMenu\n");
946 hMenu = CreatePopupMenu();
948 if( hMenu )
950 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
951 if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
953 TRACE("-- explore mode\n");
954 fExplore = TRUE;
957 /* build the flags depending on what we can do with the selected item */
958 wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
960 /* let the ContextMenu merge its items in */
961 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
963 if (This->FolderSettings.fFlags & FWF_DESKTOP)
964 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
966 if( bDefault )
968 TRACE("-- get menu default command\n");
969 uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
971 else
973 TRACE("-- track popup\n");
974 uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
977 if(uCommand > 0)
979 TRACE("-- uCommand=%u\n", uCommand);
980 if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
982 TRACE("-- dlg: OnDefaultCommand\n");
983 if (OnDefaultCommand(This) != S_OK)
985 ShellView_OpenSelectedItems(This);
988 else
990 TRACE("-- explore -- invoke command\n");
991 ZeroMemory(&cmi, sizeof(cmi));
992 cmi.cbSize = sizeof(cmi);
993 cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
994 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
995 IContextMenu_InvokeCommand(pContextMenu, &cmi);
998 DestroyMenu(hMenu);
1001 if (pContextMenu)
1002 IContextMenu_Release(pContextMenu);
1005 else /* background context menu */
1007 hMenu = CreatePopupMenu();
1009 pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
1010 IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1012 uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1013 DestroyMenu(hMenu);
1015 TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1017 ZeroMemory(&cmi, sizeof(cmi));
1018 cmi.cbSize = sizeof(cmi);
1019 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1020 cmi.hwnd = This->hWndParent;
1021 IContextMenu2_InvokeCommand(pCM, &cmi);
1023 IContextMenu2_Release(pCM);
1027 /**********************************************************
1028 * ##### message handling #####
1031 /**********************************************************
1032 * ShellView_OnSize()
1034 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1036 TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1038 /*resize the ListView to fit our window*/
1039 if(This->hWndList)
1041 MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1044 return S_OK;
1046 /**********************************************************
1047 * ShellView_OnDeactivate()
1049 * NOTES
1050 * internal
1052 static void ShellView_OnDeactivate(IShellViewImpl * This)
1054 TRACE("%p\n",This);
1056 if(This->uState != SVUIA_DEACTIVATE)
1058 if(This->hMenu)
1060 IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1061 IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1062 DestroyMenu(This->hMenu);
1063 This->hMenu = 0;
1066 This->uState = SVUIA_DEACTIVATE;
1070 /**********************************************************
1071 * ShellView_OnActivate()
1073 static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState)
1074 { OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} };
1075 MENUITEMINFOA mii;
1076 CHAR szText[MAX_PATH];
1078 TRACE("%p uState=%x\n",This,uState);
1080 /*don't do anything if the state isn't really changing */
1081 if(This->uState == uState)
1083 return S_OK;
1086 ShellView_OnDeactivate(This);
1088 /*only do This if we are active */
1089 if(uState != SVUIA_DEACTIVATE)
1091 /*merge the menus */
1092 This->hMenu = CreateMenu();
1094 if(This->hMenu)
1096 IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1097 TRACE("-- after fnInsertMenusSB\n");
1099 /*build the top level menu get the menu item's text*/
1100 strcpy(szText,"dummy 31");
1102 ZeroMemory(&mii, sizeof(mii));
1103 mii.cbSize = sizeof(mii);
1104 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1105 mii.fType = MFT_STRING;
1106 mii.fState = MFS_ENABLED;
1107 mii.dwTypeData = szText;
1108 mii.hSubMenu = ShellView_BuildFileMenu(This);
1110 /*insert our menu into the menu bar*/
1111 if(mii.hSubMenu)
1113 InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1116 /*get the view menu so we can merge with it*/
1117 ZeroMemory(&mii, sizeof(mii));
1118 mii.cbSize = sizeof(mii);
1119 mii.fMask = MIIM_SUBMENU;
1121 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1123 ShellView_MergeViewMenu(This, mii.hSubMenu);
1126 /*add the items that should only be added if we have the focus*/
1127 if(SVUIA_ACTIVATE_FOCUS == uState)
1129 /*get the file menu so we can merge with it */
1130 ZeroMemory(&mii, sizeof(mii));
1131 mii.cbSize = sizeof(mii);
1132 mii.fMask = MIIM_SUBMENU;
1134 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1136 ShellView_MergeFileMenu(This, mii.hSubMenu);
1139 TRACE("-- before fnSetMenuSB\n");
1140 IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1143 This->uState = uState;
1144 TRACE("--\n");
1145 return S_OK;
1148 /**********************************************************
1149 * ShellView_OnSetFocus()
1152 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1154 TRACE("%p\n",This);
1156 /* Tell the browser one of our windows has received the focus. This
1157 should always be done before merging menus (OnActivate merges the
1158 menus) if one of our windows has the focus.*/
1160 IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1161 ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1163 /* Set the focus to the listview */
1164 SetFocus(This->hWndList);
1166 /* Notify the ICommDlgBrowser interface */
1167 OnStateChange(This,CDBOSC_SETFOCUS);
1169 return 0;
1172 /**********************************************************
1173 * ShellView_OnKillFocus()
1175 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1177 TRACE("(%p) stub\n",This);
1179 ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1180 /* Notify the ICommDlgBrowser */
1181 OnStateChange(This,CDBOSC_KILLFOCUS);
1183 return 0;
1186 /**********************************************************
1187 * ShellView_OnCommand()
1189 * NOTES
1190 * the CmdID's are the ones from the context menu
1192 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1194 TRACE("(%p)->(0x%08lx 0x%08lx %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1196 switch(dwCmdID)
1198 case FCIDM_SHVIEW_SMALLICON:
1199 This->FolderSettings.ViewMode = FVM_SMALLICON;
1200 SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1201 CheckToolbar(This);
1202 break;
1204 case FCIDM_SHVIEW_BIGICON:
1205 This->FolderSettings.ViewMode = FVM_ICON;
1206 SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1207 CheckToolbar(This);
1208 break;
1210 case FCIDM_SHVIEW_LISTVIEW:
1211 This->FolderSettings.ViewMode = FVM_LIST;
1212 SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1213 CheckToolbar(This);
1214 break;
1216 case FCIDM_SHVIEW_REPORTVIEW:
1217 This->FolderSettings.ViewMode = FVM_DETAILS;
1218 SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1219 CheckToolbar(This);
1220 break;
1222 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1223 case 0x30:
1224 case 0x31:
1225 case 0x32:
1226 case 0x33:
1227 This->ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30);
1228 This->ListViewSortInfo.bIsAscending = TRUE;
1229 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1230 ListView_SortItems(This->hWndList, ShellView_ListViewCompareItems, (LPARAM) (&(This->ListViewSortInfo)));
1231 break;
1233 default:
1234 TRACE("-- COMMAND 0x%04lx unhandled\n", dwCmdID);
1236 return 0;
1239 /**********************************************************
1240 * ShellView_OnNotify()
1243 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1244 { LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1245 NMLVDISPINFOA *lpdi = (NMLVDISPINFOA *)lpnmh;
1246 LPITEMIDLIST pidl;
1248 TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1250 switch(lpnmh->code)
1252 case NM_SETFOCUS:
1253 TRACE("-- NM_SETFOCUS %p\n",This);
1254 ShellView_OnSetFocus(This);
1255 break;
1257 case NM_KILLFOCUS:
1258 TRACE("-- NM_KILLFOCUS %p\n",This);
1259 ShellView_OnDeactivate(This);
1260 /* Notify the ICommDlgBrowser interface */
1261 OnStateChange(This,CDBOSC_KILLFOCUS);
1262 break;
1264 case NM_CUSTOMDRAW:
1265 TRACE("-- NM_CUSTOMDRAW %p\n",This);
1266 return CDRF_DODEFAULT;
1268 case NM_RELEASEDCAPTURE:
1269 TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1270 break;
1272 case NM_CLICK:
1273 TRACE("-- NM_CLICK %p\n",This);
1274 break;
1276 case NM_RCLICK:
1277 TRACE("-- NM_RCLICK %p\n",This);
1278 break;
1280 case NM_DBLCLK:
1281 TRACE("-- NM_DBLCLK %p\n",This);
1282 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1283 break;
1285 case NM_RETURN:
1286 TRACE("-- NM_DBLCLK %p\n",This);
1287 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1288 break;
1290 case HDN_ENDTRACKA:
1291 TRACE("-- HDN_ENDTRACKA %p\n",This);
1292 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1293 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1294 break;
1296 case LVN_DELETEITEM:
1297 TRACE("-- LVN_DELETEITEM %p\n",This);
1298 SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/
1299 break;
1301 case LVN_DELETEALLITEMS:
1302 TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1303 return FALSE;
1305 case LVN_INSERTITEM:
1306 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1307 break;
1309 case LVN_ITEMACTIVATE:
1310 TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1311 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1312 break;
1314 case LVN_COLUMNCLICK:
1315 This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1316 if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1318 This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1320 else
1322 This->ListViewSortInfo.bIsAscending = TRUE;
1324 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1326 ListView_SortItems(lpnmlv->hdr.hwndFrom, ShellView_ListViewCompareItems, (LPARAM) (&(This->ListViewSortInfo)));
1327 break;
1329 case LVN_GETDISPINFOA:
1330 case LVN_GETDISPINFOW:
1331 TRACE("-- LVN_GETDISPINFO %p\n",This);
1332 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1334 if(lpdi->item.mask & LVIF_TEXT) /* text requested */
1336 if (This->pSF2Parent)
1338 SHELLDETAILS sd;
1339 IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1340 if (lpnmh->code == LVN_GETDISPINFOA)
1342 StrRetToStrNA( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1343 TRACE("-- text=%s\n",lpdi->item.pszText);
1345 else /* LVN_GETDISPINFOW */
1347 StrRetToStrNW( ((NMLVDISPINFOW *)lpdi)->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1348 TRACE("-- text=%s\n",debugstr_w((WCHAR*)(lpdi->item.pszText)));
1351 else
1353 FIXME("no SF2\n");
1356 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1358 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1360 break;
1362 case LVN_ITEMCHANGED:
1363 TRACE("-- LVN_ITEMCHANGED %p\n",This);
1364 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1365 break;
1367 case LVN_BEGINDRAG:
1368 case LVN_BEGINRDRAG:
1369 TRACE("-- LVN_BEGINDRAG\n");
1371 if (ShellView_GetSelections(This))
1373 IDataObject * pda;
1374 DWORD dwAttributes = SFGAO_CANLINK;
1375 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1377 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1379 IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource); /* own DropSource interface */
1381 if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1383 if (dwAttributes & SFGAO_CANLINK)
1385 dwEffect |= DROPEFFECT_LINK;
1389 if (pds)
1391 DWORD dwEffect;
1392 DoDragDrop(pda, pds, dwEffect, &dwEffect);
1394 IDataObject_Release(pda);
1397 break;
1399 case LVN_BEGINLABELEDITA:
1401 DWORD dwAttr = SFGAO_CANRENAME;
1402 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1404 TRACE("-- LVN_BEGINLABELEDITA %p\n",This);
1406 IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1407 if (SFGAO_CANRENAME & dwAttr)
1409 return FALSE;
1411 return TRUE;
1414 case LVN_ENDLABELEDITA:
1416 TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1417 if (lpdi->item.pszText)
1419 HRESULT hr;
1420 WCHAR wszNewName[MAX_PATH];
1421 LVITEMA lvItem;
1423 ZeroMemory(&lvItem, sizeof(LVITEMA));
1424 lvItem.iItem = lpdi->item.iItem;
1425 lvItem.mask = LVIF_PARAM;
1426 ListView_GetItemA(This->hWndList, &lvItem);
1428 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1429 if (!MultiByteToWideChar( CP_ACP, 0, lpdi->item.pszText, -1, wszNewName, MAX_PATH ))
1430 wszNewName[MAX_PATH-1] = 0;
1431 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, wszNewName, SHGDN_INFOLDER, &pidl);
1433 if(SUCCEEDED(hr) && pidl)
1435 lvItem.mask = LVIF_PARAM;
1436 lvItem.lParam = (LPARAM)pidl;
1437 ListView_SetItemA(This->hWndList, &lvItem);
1438 return TRUE;
1441 return FALSE;
1444 case LVN_KEYDOWN:
1446 /* MSG msg;
1447 msg.hwnd = This->hWnd;
1448 msg.message = WM_KEYDOWN;
1449 msg.wParam = plvKeyDown->wVKey;
1450 msg.lParam = 0;
1451 msg.time = 0;
1452 msg.pt = 0;*/
1454 LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1456 /* initiate a rename of the selected file or directory */
1457 if(plvKeyDown->wVKey == VK_F2)
1459 /* see how many files are selected */
1460 int i = ListView_GetSelectedCount(This->hWndList);
1462 /* get selected item */
1463 if(i == 1)
1465 /* get selected item */
1466 i = ListView_GetNextItem(This->hWndList, -1,
1467 LVNI_SELECTED);
1469 ListView_EnsureVisible(This->hWndList, i, 0);
1470 ListView_EditLabelA(This->hWndList, i);
1473 #if 0
1474 TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1475 #endif
1476 else if(plvKeyDown->wVKey == VK_DELETE)
1478 UINT i;
1479 int item_index;
1480 LVITEMA item;
1481 LPITEMIDLIST* pItems;
1482 ISFHelper *psfhlp;
1484 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1485 (LPVOID*)&psfhlp);
1487 if (psfhlp == NULL)
1488 break;
1490 if(!(i = ListView_GetSelectedCount(This->hWndList)))
1491 break;
1493 /* allocate memory for the pidl array */
1494 pItems = HeapAlloc(GetProcessHeap(), 0,
1495 sizeof(LPITEMIDLIST) * i);
1497 /* retrieve all selected items */
1498 i = 0;
1499 item_index = -1;
1500 while(ListView_GetSelectedCount(This->hWndList) > i)
1502 /* get selected item */
1503 item_index = ListView_GetNextItem(This->hWndList,
1504 item_index, LVNI_SELECTED);
1505 item.iItem = item_index;
1506 item.mask |= LVIF_PARAM;
1507 ListView_GetItemA(This->hWndList, &item);
1509 /* get item pidl */
1510 pItems[i] = (LPITEMIDLIST)item.lParam;
1512 i++;
1515 /* perform the item deletion */
1516 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1518 /* free pidl array memory */
1519 HeapFree(GetProcessHeap(), 0, pItems);
1522 /* Initiate a refresh */
1523 else if(plvKeyDown->wVKey == VK_F5)
1525 IShellView_Refresh((IShellView*)This);
1528 else
1529 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1531 break;
1533 default:
1534 TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1535 break;
1537 return 0;
1540 /**********************************************************
1541 * ShellView_OnChange()
1544 static LRESULT ShellView_OnChange(IShellViewImpl * This, LPITEMIDLIST * Pidls, LONG wEventId)
1547 TRACE("(%p)(%p,%p,0x%08lx)\n", This, Pidls[0], Pidls[1], wEventId);
1548 switch(wEventId)
1550 case SHCNE_MKDIR:
1551 case SHCNE_CREATE:
1552 LV_AddItem(This, Pidls[0]);
1553 break;
1554 case SHCNE_RMDIR:
1555 case SHCNE_DELETE:
1556 LV_DeleteItem(This, Pidls[0]);
1557 break;
1558 case SHCNE_RENAMEFOLDER:
1559 case SHCNE_RENAMEITEM:
1560 LV_RenameItem(This, Pidls[0], Pidls[1]);
1561 break;
1562 case SHCNE_UPDATEITEM:
1563 break;
1565 return TRUE;
1567 /**********************************************************
1568 * ShellView_WndProc
1571 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1573 IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1574 LPCREATESTRUCTA lpcs;
1576 TRACE("(hwnd=%p msg=%x wparm=%x lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1578 switch (uMessage)
1580 case WM_NCCREATE:
1581 lpcs = (LPCREATESTRUCTA)lParam;
1582 pThis = (IShellViewImpl*)(lpcs->lpCreateParams);
1583 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1584 pThis->hWnd = hWnd; /*set the window handle*/
1585 break;
1587 case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1588 case WM_SETFOCUS: return ShellView_OnSetFocus(pThis);
1589 case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis);
1590 case WM_CREATE: return ShellView_OnCreate(pThis);
1591 case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1592 case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1593 case WM_COMMAND: return ShellView_OnCommand(pThis,
1594 GET_WM_COMMAND_ID(wParam, lParam),
1595 GET_WM_COMMAND_CMD(wParam, lParam),
1596 GET_WM_COMMAND_HWND(wParam, lParam));
1597 case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (LPITEMIDLIST*)wParam, (LONG)lParam);
1599 case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1600 return 0;
1602 case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
1603 break;
1605 case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0);
1607 case WM_DESTROY:
1608 RevokeDragDrop(pThis->hWnd);
1609 SHChangeNotifyDeregister(pThis->hNotify);
1610 break;
1612 case WM_ERASEBKGND:
1613 if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1614 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1615 return 1;
1616 break;
1619 return DefWindowProcA (hWnd, uMessage, wParam, lParam);
1621 /**********************************************************
1624 * The INTERFACE of the IShellView object
1627 **********************************************************
1628 * IShellView_QueryInterface
1630 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj)
1632 IShellViewImpl *This = (IShellViewImpl *)iface;
1634 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1636 *ppvObj = NULL;
1638 if(IsEqualIID(riid, &IID_IUnknown))
1640 *ppvObj = This;
1642 else if(IsEqualIID(riid, &IID_IShellView))
1644 *ppvObj = (IShellView*)This;
1646 else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1648 *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget);
1650 else if(IsEqualIID(riid, &IID_IDropTarget))
1652 *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
1654 else if(IsEqualIID(riid, &IID_IDropSource))
1656 *ppvObj = (IDropSource*)&(This->lpvtblDropSource);
1658 else if(IsEqualIID(riid, &IID_IViewObject))
1660 *ppvObj = (IViewObject*)&(This->lpvtblViewObject);
1663 if(*ppvObj)
1665 IUnknown_AddRef( (IUnknown*)*ppvObj );
1666 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1667 return S_OK;
1669 TRACE("-- Interface: E_NOINTERFACE\n");
1670 return E_NOINTERFACE;
1673 /**********************************************************
1674 * IShellView_AddRef
1676 static ULONG WINAPI IShellView_fnAddRef(IShellView * iface)
1678 IShellViewImpl *This = (IShellViewImpl *)iface;
1679 ULONG refCount = InterlockedIncrement(&This->ref);
1681 TRACE("(%p)->(count=%lu)\n", This, refCount - 1);
1683 return refCount;
1685 /**********************************************************
1686 * IShellView_Release
1688 static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
1690 IShellViewImpl *This = (IShellViewImpl *)iface;
1691 ULONG refCount = InterlockedDecrement(&This->ref);
1693 TRACE("(%p)->(count=%li)\n", This, refCount + 1);
1695 if (!refCount)
1697 TRACE(" destroying IShellView(%p)\n",This);
1699 DestroyWindow(This->hWndList);
1701 if(This->pSFParent)
1702 IShellFolder_Release(This->pSFParent);
1704 if(This->pSF2Parent)
1705 IShellFolder2_Release(This->pSF2Parent);
1707 if(This->apidl)
1708 SHFree(This->apidl);
1710 if(This->pAdvSink)
1711 IAdviseSink_Release(This->pAdvSink);
1713 HeapFree(GetProcessHeap(),0,This);
1715 return refCount;
1718 /**********************************************************
1719 * ShellView_GetWindow
1721 static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd)
1723 IShellViewImpl *This = (IShellViewImpl *)iface;
1725 TRACE("(%p)\n",This);
1727 *phWnd = This->hWnd;
1729 return S_OK;
1732 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode)
1734 IShellViewImpl *This = (IShellViewImpl *)iface;
1736 FIXME("(%p) stub\n",This);
1738 return E_NOTIMPL;
1741 /**********************************************************
1742 * IShellView_TranslateAccelerator
1744 * FIXME:
1745 * use the accel functions
1747 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg)
1749 #if 0
1750 IShellViewImpl *This = (IShellViewImpl *)iface;
1752 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%lx wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1753 #endif
1755 if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1757 TRACE("-- key=0x04%x\n",lpmsg->wParam) ;
1759 return S_FALSE; /* not handled */
1762 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable)
1764 IShellViewImpl *This = (IShellViewImpl *)iface;
1766 FIXME("(%p) stub\n",This);
1768 return E_NOTIMPL;
1771 static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState)
1773 IShellViewImpl *This = (IShellViewImpl *)iface;
1776 CHAR szName[MAX_PATH];
1778 LRESULT lResult;
1779 int nPartArray[1] = {-1};
1781 TRACE("(%p)->(state=%x) stub\n",This, uState);
1783 /*don't do anything if the state isn't really changing*/
1784 if(This->uState == uState)
1786 return S_OK;
1789 /*OnActivate handles the menu merging and internal state*/
1790 ShellView_OnActivate(This, uState);
1792 /*only do This if we are active*/
1793 if(uState != SVUIA_DEACTIVATE)
1797 GetFolderPath is not a method of IShellFolder
1798 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1800 /* set the number of parts */
1801 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1802 (LPARAM)nPartArray, &lResult);
1804 /* set the text for the parts */
1806 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1807 0, (LPARAM)szName, &lResult);
1811 return S_OK;
1814 static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface)
1816 IShellViewImpl *This = (IShellViewImpl *)iface;
1818 TRACE("(%p)\n",This);
1820 ListView_DeleteAllItems(This->hWndList);
1821 ShellView_FillList(This);
1823 return S_OK;
1826 static HRESULT WINAPI IShellView_fnCreateViewWindow(
1827 IShellView * iface,
1828 IShellView *lpPrevView,
1829 LPCFOLDERSETTINGS lpfs,
1830 IShellBrowser * psb,
1831 RECT * prcView,
1832 HWND *phWnd)
1834 IShellViewImpl *This = (IShellViewImpl *)iface;
1836 WNDCLASSA wc;
1837 *phWnd = 0;
1840 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd);
1841 TRACE("-- vmode=%x flags=%x left=%li top=%li right=%li bottom=%li\n",lpfs->ViewMode, lpfs->fFlags ,prcView->left,prcView->top, prcView->right, prcView->bottom);
1843 /*set up the member variables*/
1844 This->pShellBrowser = psb;
1845 This->FolderSettings = *lpfs;
1847 /*get our parent window*/
1848 IShellBrowser_AddRef(This->pShellBrowser);
1849 IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
1851 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1852 This->pCommDlgBrowser=NULL;
1853 if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser,
1854 (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser)))
1856 TRACE("-- CommDlgBrowser\n");
1859 /*if our window class has not been registered, then do so*/
1860 if(!GetClassInfoA(shell32_hInstance, SV_CLASS_NAME, &wc))
1862 ZeroMemory(&wc, sizeof(wc));
1863 wc.style = CS_HREDRAW | CS_VREDRAW;
1864 wc.lpfnWndProc = ShellView_WndProc;
1865 wc.cbClsExtra = 0;
1866 wc.cbWndExtra = 0;
1867 wc.hInstance = shell32_hInstance;
1868 wc.hIcon = 0;
1869 wc.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
1870 wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
1871 wc.lpszMenuName = NULL;
1872 wc.lpszClassName = SV_CLASS_NAME;
1874 if(!RegisterClassA(&wc))
1875 return E_FAIL;
1878 *phWnd = CreateWindowExA(0,
1879 SV_CLASS_NAME,
1880 NULL,
1881 WS_CHILD | WS_VISIBLE | WS_TABSTOP,
1882 prcView->left,
1883 prcView->top,
1884 prcView->right - prcView->left,
1885 prcView->bottom - prcView->top,
1886 This->hWndParent,
1888 shell32_hInstance,
1889 (LPVOID)This);
1891 CheckToolbar(This);
1893 if(!*phWnd) return E_FAIL;
1895 return S_OK;
1898 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
1900 IShellViewImpl *This = (IShellViewImpl *)iface;
1902 TRACE("(%p)\n",This);
1904 /*Make absolutely sure all our UI is cleaned up.*/
1905 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1907 if(This->hMenu)
1909 DestroyMenu(This->hMenu);
1912 DestroyWindow(This->hWnd);
1913 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1914 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1917 return S_OK;
1920 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs)
1922 IShellViewImpl *This = (IShellViewImpl *)iface;
1924 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1925 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1927 if (!lpfs) return E_INVALIDARG;
1929 *lpfs = This->FolderSettings;
1930 return NOERROR;
1933 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1935 IShellViewImpl *This = (IShellViewImpl *)iface;
1937 FIXME("(%p) stub\n",This);
1939 return E_NOTIMPL;
1942 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface)
1944 IShellViewImpl *This = (IShellViewImpl *)iface;
1946 FIXME("(%p) stub\n",This);
1948 return S_OK;
1951 static HRESULT WINAPI IShellView_fnSelectItem(
1952 IShellView * iface,
1953 LPCITEMIDLIST pidl,
1954 UINT uFlags)
1956 IShellViewImpl *This = (IShellViewImpl *)iface;
1957 int i;
1959 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
1961 i = LV_FindItemByPidl(This, pidl);
1963 if (i != -1)
1965 LVITEMA lvItem;
1967 if(uFlags & SVSI_ENSUREVISIBLE)
1968 ListView_EnsureVisible(This->hWndList, i, 0);
1970 ZeroMemory(&lvItem, sizeof(LVITEMA));
1971 lvItem.mask = LVIF_STATE;
1972 lvItem.iItem = 0;
1974 while(ListView_GetItemA(This->hWndList, &lvItem))
1976 if (lvItem.iItem == i)
1978 if (uFlags & SVSI_SELECT)
1979 lvItem.state |= LVIS_SELECTED;
1980 else
1981 lvItem.state &= ~LVIS_SELECTED;
1983 if(uFlags & SVSI_FOCUSED)
1984 lvItem.state &= ~LVIS_FOCUSED;
1986 else
1988 if (uFlags & SVSI_DESELECTOTHERS)
1989 lvItem.state &= ~LVIS_SELECTED;
1991 ListView_SetItemA(This->hWndList, &lvItem);
1992 lvItem.iItem++;
1996 if(uFlags & SVSI_EDIT)
1997 ListView_EditLabelA(This->hWndList, i);
2000 return S_OK;
2003 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
2005 IShellViewImpl *This = (IShellViewImpl *)iface;
2007 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2009 *ppvOut = NULL;
2011 switch(uItem)
2013 case SVGIO_BACKGROUND:
2014 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2015 break;
2017 case SVGIO_SELECTION:
2018 ShellView_GetSelections(This);
2019 IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2020 break;
2022 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2024 if(!*ppvOut) return E_OUTOFMEMORY;
2026 return S_OK;
2029 static const IShellViewVtbl svvt =
2031 IShellView_fnQueryInterface,
2032 IShellView_fnAddRef,
2033 IShellView_fnRelease,
2034 IShellView_fnGetWindow,
2035 IShellView_fnContextSensitiveHelp,
2036 IShellView_fnTranslateAccelerator,
2037 IShellView_fnEnableModeless,
2038 IShellView_fnUIActivate,
2039 IShellView_fnRefresh,
2040 IShellView_fnCreateViewWindow,
2041 IShellView_fnDestroyViewWindow,
2042 IShellView_fnGetCurrentInfo,
2043 IShellView_fnAddPropertySheetPages,
2044 IShellView_fnSaveViewState,
2045 IShellView_fnSelectItem,
2046 IShellView_fnGetItemObject
2050 /**********************************************************
2051 * ISVOleCmdTarget_QueryInterface (IUnknown)
2053 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2054 IOleCommandTarget * iface,
2055 REFIID iid,
2056 LPVOID* ppvObj)
2058 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2060 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2063 /**********************************************************
2064 * ISVOleCmdTarget_AddRef (IUnknown)
2066 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2067 IOleCommandTarget * iface)
2069 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2071 return IShellFolder_AddRef((IShellFolder*)This);
2074 /**********************************************************
2075 * ISVOleCmdTarget_Release (IUnknown)
2077 static ULONG WINAPI ISVOleCmdTarget_Release(
2078 IOleCommandTarget * iface)
2080 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2082 return IShellFolder_Release((IShellFolder*)This);
2085 /**********************************************************
2086 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2088 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2089 IOleCommandTarget *iface,
2090 const GUID* pguidCmdGroup,
2091 ULONG cCmds,
2092 OLECMD * prgCmds,
2093 OLECMDTEXT* pCmdText)
2095 UINT i;
2096 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2098 FIXME("(%p)->(%p(%s) 0x%08lx %p %p\n",
2099 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2101 if (!prgCmds)
2102 return E_POINTER;
2103 for (i = 0; i < cCmds; i++)
2105 FIXME("\tprgCmds[%d].cmdID = %ld\n", i, prgCmds[i].cmdID);
2106 prgCmds[i].cmdf = 0;
2108 return OLECMDERR_E_UNKNOWNGROUP;
2111 /**********************************************************
2112 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2114 * nCmdID is the OLECMDID_* enumeration
2116 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2117 IOleCommandTarget *iface,
2118 const GUID* pguidCmdGroup,
2119 DWORD nCmdID,
2120 DWORD nCmdexecopt,
2121 VARIANT* pvaIn,
2122 VARIANT* pvaOut)
2124 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2126 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08lx Opt:0x%08lx %p %p)\n",
2127 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2129 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2130 (nCmdID == 0x29) &&
2131 (nCmdexecopt == 4) && pvaOut)
2132 return S_OK;
2133 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2134 (nCmdID == 9) &&
2135 (nCmdexecopt == 0))
2136 return 1;
2138 return OLECMDERR_E_UNKNOWNGROUP;
2141 static const IOleCommandTargetVtbl ctvt =
2143 ISVOleCmdTarget_QueryInterface,
2144 ISVOleCmdTarget_AddRef,
2145 ISVOleCmdTarget_Release,
2146 ISVOleCmdTarget_QueryStatus,
2147 ISVOleCmdTarget_Exec
2150 /**********************************************************
2151 * ISVDropTarget implementation
2154 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2155 IDropTarget *iface,
2156 REFIID riid,
2157 LPVOID *ppvObj)
2159 IShellViewImpl *This = impl_from_IDropTarget(iface);
2161 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2163 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2166 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2168 IShellViewImpl *This = impl_from_IDropTarget(iface);
2170 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2172 return IShellFolder_AddRef((IShellFolder*)This);
2175 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2177 IShellViewImpl *This = impl_from_IDropTarget(iface);
2179 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2181 return IShellFolder_Release((IShellFolder*)This);
2184 /******************************************************************************
2185 * drag_notify_subitem [Internal]
2187 * Figure out the shellfolder object, which is currently under the mouse cursor
2188 * and notify it via the IDropTarget interface.
2191 #define SCROLLAREAWIDTH 20
2193 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2194 DWORD *pdwEffect)
2196 LVHITTESTINFO htinfo;
2197 LVITEMA lvItem;
2198 LONG lResult;
2199 HRESULT hr;
2200 RECT clientRect;
2202 /* Map from global to client coordinates and query the index of the listview-item, which is
2203 * currently under the mouse cursor. */
2204 htinfo.pt.x = pt.x;
2205 htinfo.pt.y = pt.y;
2206 htinfo.flags = LVHT_ONITEM;
2207 ScreenToClient(This->hWndList, &htinfo.pt);
2208 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2210 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2211 GetClientRect(This->hWndList, &clientRect);
2212 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2213 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2214 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2216 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2217 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2218 if (htinfo.pt.x < SCROLLAREAWIDTH)
2219 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2220 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2221 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2222 if (htinfo.pt.y < SCROLLAREAWIDTH)
2223 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2224 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2225 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2227 } else {
2228 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2230 This->ptLastMousePos = htinfo.pt;
2232 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2233 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2234 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2236 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2237 if (This->pCurDropTarget) {
2238 IDropTarget_DragLeave(This->pCurDropTarget);
2239 IDropTarget_Release(This->pCurDropTarget);
2240 This->pCurDropTarget = NULL;
2243 This->iDragOverItem = lResult;
2244 if (lResult == -1) {
2245 /* We are not above one of the listview's subitems. Bind to the parent folder's
2246 * DropTarget interface. */
2247 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2248 (LPVOID*)&This->pCurDropTarget);
2249 } else {
2250 /* Query the relative PIDL of the shellfolder object represented by the currently
2251 * dragged over listview-item ... */
2252 ZeroMemory(&lvItem, sizeof(lvItem));
2253 lvItem.mask = LVIF_PARAM;
2254 lvItem.iItem = lResult;
2255 ListView_GetItemA(This->hWndList, &lvItem);
2257 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2258 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2259 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2262 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2263 if (FAILED(hr))
2264 return hr;
2266 /* Notify the item just entered via DragEnter. */
2267 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2270 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2271 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2273 IShellViewImpl *This = impl_from_IDropTarget(iface);
2275 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2276 This->pCurDataObject = pDataObject;
2277 IDataObject_AddRef(pDataObject);
2279 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2282 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2283 DWORD *pdwEffect)
2285 IShellViewImpl *This = impl_from_IDropTarget(iface);
2286 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2289 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2290 IShellViewImpl *This = impl_from_IDropTarget(iface);
2292 IDropTarget_DragLeave(This->pCurDropTarget);
2294 IDropTarget_Release(This->pCurDropTarget);
2295 IDataObject_Release(This->pCurDataObject);
2296 This->pCurDataObject = NULL;
2297 This->pCurDropTarget = NULL;
2298 This->iDragOverItem = 0;
2300 return S_OK;
2303 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2304 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2306 IShellViewImpl *This = impl_from_IDropTarget(iface);
2308 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2310 IDropTarget_Release(This->pCurDropTarget);
2311 IDataObject_Release(This->pCurDataObject);
2312 This->pCurDataObject = NULL;
2313 This->pCurDropTarget = NULL;
2314 This->iDragOverItem = 0;
2316 return S_OK;
2319 static const IDropTargetVtbl dtvt =
2321 ISVDropTarget_QueryInterface,
2322 ISVDropTarget_AddRef,
2323 ISVDropTarget_Release,
2324 ISVDropTarget_DragEnter,
2325 ISVDropTarget_DragOver,
2326 ISVDropTarget_DragLeave,
2327 ISVDropTarget_Drop
2330 /**********************************************************
2331 * ISVDropSource implementation
2334 static HRESULT WINAPI ISVDropSource_QueryInterface(
2335 IDropSource *iface,
2336 REFIID riid,
2337 LPVOID *ppvObj)
2339 IShellViewImpl *This = impl_from_IDropSource(iface);
2341 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2343 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2346 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2348 IShellViewImpl *This = impl_from_IDropSource(iface);
2350 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2352 return IShellFolder_AddRef((IShellFolder*)This);
2355 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2357 IShellViewImpl *This = impl_from_IDropSource(iface);
2359 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2361 return IShellFolder_Release((IShellFolder*)This);
2363 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2364 IDropSource *iface,
2365 BOOL fEscapePressed,
2366 DWORD grfKeyState)
2368 IShellViewImpl *This = impl_from_IDropSource(iface);
2369 TRACE("(%p)\n",This);
2371 if (fEscapePressed)
2372 return DRAGDROP_S_CANCEL;
2373 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2374 return DRAGDROP_S_DROP;
2375 else
2376 return NOERROR;
2379 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2380 IDropSource *iface,
2381 DWORD dwEffect)
2383 IShellViewImpl *This = impl_from_IDropSource(iface);
2384 TRACE("(%p)\n",This);
2386 return DRAGDROP_S_USEDEFAULTCURSORS;
2389 static const IDropSourceVtbl dsvt =
2391 ISVDropSource_QueryInterface,
2392 ISVDropSource_AddRef,
2393 ISVDropSource_Release,
2394 ISVDropSource_QueryContinueDrag,
2395 ISVDropSource_GiveFeedback
2397 /**********************************************************
2398 * ISVViewObject implementation
2401 static HRESULT WINAPI ISVViewObject_QueryInterface(
2402 IViewObject *iface,
2403 REFIID riid,
2404 LPVOID *ppvObj)
2406 IShellViewImpl *This = impl_from_IViewObject(iface);
2408 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2410 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2413 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2415 IShellViewImpl *This = impl_from_IViewObject(iface);
2417 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2419 return IShellFolder_AddRef((IShellFolder*)This);
2422 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2424 IShellViewImpl *This = impl_from_IViewObject(iface);
2426 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2428 return IShellFolder_Release((IShellFolder*)This);
2431 static HRESULT WINAPI ISVViewObject_Draw(
2432 IViewObject *iface,
2433 DWORD dwDrawAspect,
2434 LONG lindex,
2435 void* pvAspect,
2436 DVTARGETDEVICE* ptd,
2437 HDC hdcTargetDev,
2438 HDC hdcDraw,
2439 LPCRECTL lprcBounds,
2440 LPCRECTL lprcWBounds,
2441 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2442 ULONG_PTR dwContinue)
2445 IShellViewImpl *This = impl_from_IViewObject(iface);
2447 FIXME("Stub: This=%p\n",This);
2449 return E_NOTIMPL;
2451 static HRESULT WINAPI ISVViewObject_GetColorSet(
2452 IViewObject *iface,
2453 DWORD dwDrawAspect,
2454 LONG lindex,
2455 void *pvAspect,
2456 DVTARGETDEVICE* ptd,
2457 HDC hicTargetDevice,
2458 LOGPALETTE** ppColorSet)
2461 IShellViewImpl *This = impl_from_IViewObject(iface);
2463 FIXME("Stub: This=%p\n",This);
2465 return E_NOTIMPL;
2467 static HRESULT WINAPI ISVViewObject_Freeze(
2468 IViewObject *iface,
2469 DWORD dwDrawAspect,
2470 LONG lindex,
2471 void* pvAspect,
2472 DWORD* pdwFreeze)
2475 IShellViewImpl *This = impl_from_IViewObject(iface);
2477 FIXME("Stub: This=%p\n",This);
2479 return E_NOTIMPL;
2481 static HRESULT WINAPI ISVViewObject_Unfreeze(
2482 IViewObject *iface,
2483 DWORD dwFreeze)
2486 IShellViewImpl *This = impl_from_IViewObject(iface);
2488 FIXME("Stub: This=%p\n",This);
2490 return E_NOTIMPL;
2492 static HRESULT WINAPI ISVViewObject_SetAdvise(
2493 IViewObject *iface,
2494 DWORD aspects,
2495 DWORD advf,
2496 IAdviseSink* pAdvSink)
2499 IShellViewImpl *This = impl_from_IViewObject(iface);
2501 FIXME("partial stub: %p %08lx %08lx %p\n",
2502 This, aspects, advf, pAdvSink);
2504 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2505 This->pAdvSink = pAdvSink;
2506 This->dwAspects = aspects;
2507 This->dwAdvf = advf;
2509 return S_OK;
2512 static HRESULT WINAPI ISVViewObject_GetAdvise(
2513 IViewObject *iface,
2514 DWORD* pAspects,
2515 DWORD* pAdvf,
2516 IAdviseSink** ppAdvSink)
2519 IShellViewImpl *This = impl_from_IViewObject(iface);
2521 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2522 This, pAspects, pAdvf, ppAdvSink);
2524 if( ppAdvSink )
2526 IAdviseSink_AddRef( This->pAdvSink );
2527 *ppAdvSink = This->pAdvSink;
2529 if( pAspects )
2530 *pAspects = This->dwAspects;
2531 if( pAdvf )
2532 *pAdvf = This->dwAdvf;
2534 return S_OK;
2538 static const IViewObjectVtbl vovt =
2540 ISVViewObject_QueryInterface,
2541 ISVViewObject_AddRef,
2542 ISVViewObject_Release,
2543 ISVViewObject_Draw,
2544 ISVViewObject_GetColorSet,
2545 ISVViewObject_Freeze,
2546 ISVViewObject_Unfreeze,
2547 ISVViewObject_SetAdvise,
2548 ISVViewObject_GetAdvise