Changes in crossover-wine-src-6.1.0 except for configure
[wine/hacks.git] / dlls / shell32 / shlview.c
blob3f471ee59e1833557c72b06cbb04c5738648b378
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * FIXME: The order by part of the background context menu should be
24 * buily according to the columns shown.
26 * FIXME: Load/Save the view state from/into the stream provied by
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 1
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 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 static const 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%08x\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 %08x\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) {
346 * FIXME: look at the registry value
347 * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
348 * and activate drop shadows if necessary
350 if (0)
351 SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, CLR_NONE);
352 else
353 SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, GetSysColor(COLOR_DESKTOP));
355 SendMessageW(This->hWndList, LVM_SETTEXTCOLOR, 0, RGB(255,255,255));
358 /* UpdateShellSettings(); */
359 return TRUE;
362 /**********************************************************
363 * ShellView_InitList()
365 * - adds all needed columns to the shellview
367 static BOOL ShellView_InitList(IShellViewImpl * This)
369 LVCOLUMNW lvColumn;
370 SHELLDETAILS sd;
371 int i;
372 WCHAR szTemp[50];
374 TRACE("%p\n",This);
376 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
378 lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
379 lvColumn.pszText = szTemp;
381 if (This->pSF2Parent)
383 for (i=0; 1; i++)
385 if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd)))
386 break;
387 lvColumn.fmt = sd.fmt;
388 lvColumn.cx = sd.cxChar*8; /* chars->pixel */
389 StrRetToStrNW( szTemp, 50, &sd.str, NULL);
390 SendMessageW(This->hWndList, LVM_INSERTCOLUMNW, i, (LPARAM) &lvColumn);
393 else
395 FIXME("no SF2\n");
398 SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ShellSmallIconList);
399 SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)ShellBigIconList);
401 return TRUE;
403 /**********************************************************
404 * ShellView_CompareItems()
406 * NOTES
407 * internal, CALLBACK for DSA_Sort
409 static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
411 int ret;
412 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
414 if(!lpData) return 0;
416 ret = (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2));
417 TRACE("ret=%i\n",ret);
418 return ret;
421 /*************************************************************************
422 * ShellView_ListViewCompareItems
424 * Compare Function for the Listview (FileOpen Dialog)
426 * PARAMS
427 * lParam1 [I] the first ItemIdList to compare with
428 * lParam2 [I] the second ItemIdList to compare with
429 * lpData [I] The column ID for the header Ctrl to process
431 * RETURNS
432 * A negative value if the first item should precede the second,
433 * a positive value if the first item should follow the second,
434 * or zero if the two items are equivalent
436 * NOTES
437 * FIXME: function does what ShellView_CompareItems is supposed to do.
438 * unify it and figure out how to use the undocumented first parameter
439 * of IShellFolder_CompareIDs to do the job this function does and
440 * move this code to IShellFolder.
441 * make LISTVIEW_SORT_INFO obsolete
442 * the way this function works is only usable if we had only
443 * filesystemfolders (25/10/99 jsch)
445 static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
447 INT nDiff=0;
448 FILETIME fd1, fd2;
449 char strName1[MAX_PATH], strName2[MAX_PATH];
450 BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
451 LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1;
452 LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2;
453 LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData;
456 bIsFolder1 = _ILIsFolder(pItemIdList1);
457 bIsFolder2 = _ILIsFolder(pItemIdList2);
458 bIsBothFolder = bIsFolder1 && bIsFolder2;
460 /* When sorting between a File and a Folder, the Folder gets sorted first */
461 if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
463 nDiff = bIsFolder1 ? -1 : 1;
465 else
467 /* Sort by Time: Folders or Files can be sorted */
469 if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
471 _ILGetFileDateTime(pItemIdList1, &fd1);
472 _ILGetFileDateTime(pItemIdList2, &fd2);
473 nDiff = CompareFileTime(&fd2, &fd1);
475 /* Sort by Attribute: Folder or Files can be sorted */
476 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
478 _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH);
479 _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH);
480 nDiff = lstrcmpiA(strName1, strName2);
482 /* Sort by FileName: Folder or Files can be sorted */
483 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
485 /* Sort by Text */
486 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
487 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
488 nDiff = lstrcmpiA(strName1, strName2);
490 /* Sort by File Size, Only valid for Files */
491 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
493 nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0));
495 /* Sort by File Type, Only valid for Files */
496 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
498 /* Sort by Type */
499 _ILGetFileType(pItemIdList1, strName1, MAX_PATH);
500 _ILGetFileType(pItemIdList2, strName2, MAX_PATH);
501 nDiff = lstrcmpiA(strName1, strName2);
504 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
506 if(nDiff == 0)
508 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
509 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
510 nDiff = lstrcmpiA(strName1, strName2);
513 if(!pSortInfo->bIsAscending)
515 nDiff = -nDiff;
518 return nDiff;
522 /**********************************************************
523 * LV_FindItemByPidl()
525 static int LV_FindItemByPidl(
526 IShellViewImpl * This,
527 LPCITEMIDLIST pidl)
529 LVITEMA lvItem;
530 lvItem.iSubItem = 0;
531 lvItem.mask = LVIF_PARAM;
532 for(lvItem.iItem = 0;
533 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
534 lvItem.iItem++)
536 LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam;
537 HRESULT hr = IShellFolder_CompareIDs(This->pSFParent, 0, pidl, currentpidl);
538 if(SUCCEEDED(hr) && !HRESULT_CODE(hr))
540 return lvItem.iItem;
543 return -1;
546 /**********************************************************
547 * LV_AddItem()
549 static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
551 LVITEMA lvItem;
553 TRACE("(%p)(pidl=%p)\n", This, pidl);
555 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/
556 lvItem.iItem = ListView_GetItemCount(This->hWndList); /*add the item to the end of the list*/
557 lvItem.iSubItem = 0;
558 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/
559 lvItem.pszText = LPSTR_TEXTCALLBACKA; /*get text on a callback basis*/
560 lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/
561 return (-1==ListView_InsertItemA(This->hWndList, &lvItem))? FALSE: TRUE;
564 /**********************************************************
565 * LV_DeleteItem()
567 static BOOLEAN LV_DeleteItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
569 int nIndex;
571 TRACE("(%p)(pidl=%p)\n", This, pidl);
573 nIndex = LV_FindItemByPidl(This, ILFindLastID(pidl));
574 return (-1==ListView_DeleteItem(This->hWndList, nIndex))? FALSE: TRUE;
577 /**********************************************************
578 * LV_RenameItem()
580 static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew )
582 int nItem;
583 LVITEMA lvItem;
585 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew);
587 nItem = LV_FindItemByPidl(This, ILFindLastID(pidlOld));
588 if ( -1 != nItem )
590 lvItem.mask = LVIF_PARAM; /* only the pidl */
591 lvItem.iItem = nItem;
592 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
594 SHFree((LPITEMIDLIST)lvItem.lParam);
595 lvItem.mask = LVIF_PARAM;
596 lvItem.iItem = nItem;
597 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */
598 SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem);
599 SendMessageA(This->hWndList, LVM_UPDATE, nItem, 0);
600 return TRUE; /* FIXME: better handling */
602 return FALSE;
604 /**********************************************************
605 * ShellView_FillList()
607 * - gets the objectlist from the shellfolder
608 * - sorts the list
609 * - fills the list into the view
612 static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg )
614 LPITEMIDLIST pidl = ptr;
615 IShellViewImpl *This = arg;
616 /* in a commdlg This works as a filemask*/
617 if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl);
618 SHFree(pidl);
619 return TRUE;
622 static HRESULT ShellView_FillList(IShellViewImpl * This)
624 LPENUMIDLIST pEnumIDList;
625 LPITEMIDLIST pidl;
626 DWORD dwFetched;
627 HRESULT hRes;
628 HDPA hdpa;
630 TRACE("%p\n",This);
632 /* get the itemlist from the shfolder*/
633 hRes = IShellFolder_EnumObjects(This->pSFParent,This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
634 if (hRes != S_OK)
636 if (hRes==S_FALSE)
637 return(NOERROR);
638 return(hRes);
641 /* create a pointer array */
642 hdpa = DPA_Create(16);
643 if (!hdpa)
645 return(E_OUTOFMEMORY);
648 /* copy the items into the array*/
649 while((S_OK == IEnumIDList_Next(pEnumIDList,1, &pidl, &dwFetched)) && dwFetched)
651 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
653 SHFree(pidl);
657 /* sort the array */
658 DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent);
660 /*turn the listview's redrawing off*/
661 SendMessageA(This->hWndList, WM_SETREDRAW, FALSE, 0);
663 DPA_DestroyCallback( hdpa, fill_list, This );
665 /*turn the listview's redrawing back on and force it to draw*/
666 SendMessageA(This->hWndList, WM_SETREDRAW, TRUE, 0);
668 IEnumIDList_Release(pEnumIDList); /* destroy the list*/
670 return S_OK;
673 /**********************************************************
674 * ShellView_OnCreate()
676 static LRESULT ShellView_OnCreate(IShellViewImpl * This)
678 IDropTarget* pdt;
679 SHChangeNotifyEntry ntreg;
680 IPersistFolder2 * ppf2 = NULL;
682 TRACE("%p\n",This);
684 if(ShellView_CreateList(This))
686 if(ShellView_InitList(This))
688 ShellView_FillList(This);
692 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown*)&This->lpVtbl, &IID_IDropTarget, (LPVOID*)&pdt)))
694 RegisterDragDrop(This->hWnd, pdt);
695 IDropTarget_Release(pdt);
698 /* register for receiving notifications */
699 IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
700 if (ppf2)
702 IPersistFolder2_GetCurFolder(ppf2, (LPITEMIDLIST*)&ntreg.pidl);
703 ntreg.fRecursive = TRUE;
704 This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
705 SHFree((LPITEMIDLIST)ntreg.pidl);
706 IPersistFolder2_Release(ppf2);
709 This->hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel");
711 return S_OK;
714 /**********************************************************
715 * #### Handling of the menus ####
718 /**********************************************************
719 * ShellView_BuildFileMenu()
721 static HMENU ShellView_BuildFileMenu(IShellViewImpl * This)
722 { CHAR szText[MAX_PATH];
723 MENUITEMINFOA mii;
724 int nTools,i;
725 HMENU hSubMenu;
727 TRACE("(%p)\n",This);
729 hSubMenu = CreatePopupMenu();
730 if(hSubMenu)
731 { /*get the number of items in our global array*/
732 for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
734 /*add the menu items*/
735 for(i = 0; i < nTools; i++)
737 LoadStringA(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
739 ZeroMemory(&mii, sizeof(mii));
740 mii.cbSize = sizeof(mii);
741 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
743 if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
745 mii.fType = MFT_STRING;
746 mii.fState = MFS_ENABLED;
747 mii.dwTypeData = szText;
748 mii.wID = Tools[i].idCommand;
750 else
752 mii.fType = MFT_SEPARATOR;
754 /* tack This item onto the end of the menu */
755 InsertMenuItemA(hSubMenu, (UINT)-1, TRUE, &mii);
758 TRACE("-- return (menu=%p)\n",hSubMenu);
759 return hSubMenu;
761 /**********************************************************
762 * ShellView_MergeFileMenu()
764 static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu)
765 { TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu);
767 if(hSubMenu)
768 { /*insert This item at the beginning of the menu */
769 _InsertMenuItem(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
770 _InsertMenuItem(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, "dummy45", MFS_ENABLED);
773 TRACE("--\n");
776 /**********************************************************
777 * ShellView_MergeViewMenu()
780 static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu)
782 TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
784 if(hSubMenu)
785 { /*add a separator at the correct position in the menu*/
786 MENUITEMINFOA mii;
787 static char view[] = "View";
789 _InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
791 ZeroMemory(&mii, sizeof(mii));
792 mii.cbSize = sizeof(mii);
793 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
794 mii.fType = MFT_STRING;
795 mii.dwTypeData = view;
796 mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
797 InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
801 /**********************************************************
802 * ShellView_GetSelections()
804 * - fills the this->apidl list with the selected objects
806 * RETURNS
807 * number of selected items
809 static UINT ShellView_GetSelections(IShellViewImpl * This)
811 LVITEMA lvItem;
812 UINT i = 0;
814 SHFree(This->apidl);
816 This->cidl = ListView_GetSelectedCount(This->hWndList);
817 This->apidl = (LPITEMIDLIST*)SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
819 TRACE("selected=%i\n", This->cidl);
821 if(This->apidl)
823 TRACE("-- Items selected =%u\n", This->cidl);
825 lvItem.mask = LVIF_STATE | LVIF_PARAM;
826 lvItem.stateMask = LVIS_SELECTED;
827 lvItem.iItem = 0;
828 lvItem.iSubItem = 0;
830 while(ListView_GetItemA(This->hWndList, &lvItem) && (i < This->cidl))
832 if(lvItem.state & LVIS_SELECTED)
834 This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
835 i++;
836 TRACE("-- selected Item found\n");
838 lvItem.iItem++;
841 return This->cidl;
845 /**********************************************************
846 * ShellView_OpenSelectedItems()
848 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
850 static UINT CF_IDLIST = 0;
851 HRESULT hr;
852 IDataObject* selection;
853 FORMATETC fetc;
854 STGMEDIUM stgm;
855 LPIDA pIDList;
856 LPCITEMIDLIST parent_pidl;
857 int i;
859 if (0 == ShellView_GetSelections(This))
861 return S_OK;
863 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
864 (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
865 0, (LPVOID *)&selection);
866 if (FAILED(hr))
867 return hr;
869 if (0 == CF_IDLIST)
871 CF_IDLIST = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
873 fetc.cfFormat = CF_IDLIST;
874 fetc.ptd = NULL;
875 fetc.dwAspect = DVASPECT_CONTENT;
876 fetc.lindex = -1;
877 fetc.tymed = TYMED_HGLOBAL;
879 hr = IDataObject_QueryGetData(selection, &fetc);
880 if (FAILED(hr))
881 return hr;
883 hr = IDataObject_GetData(selection, &fetc, &stgm);
884 if (FAILED(hr))
885 return hr;
887 pIDList = GlobalLock(stgm.u.hGlobal);
889 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
890 for (i = pIDList->cidl; i > 0; --i)
892 LPCITEMIDLIST pidl;
893 SFGAOF attribs;
895 pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
897 attribs = SFGAO_FOLDER;
898 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
900 if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
902 SHELLEXECUTEINFOA shexinfo;
904 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOA);
905 shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */
906 shexinfo.hwnd = NULL;
907 shexinfo.lpVerb = NULL;
908 shexinfo.lpFile = NULL;
909 shexinfo.lpParameters = NULL;
910 shexinfo.lpDirectory = NULL;
911 shexinfo.nShow = SW_NORMAL;
912 shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
914 ShellExecuteExA(&shexinfo); /* Discard error/success info */
916 ILFree((LPITEMIDLIST)shexinfo.lpIDList);
920 GlobalUnlock(stgm.u.hGlobal);
921 ReleaseStgMedium(&stgm);
923 IDataObject_Release(selection);
925 return S_OK;
928 /**********************************************************
929 * ShellView_DoContextMenu()
931 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
932 { UINT uCommand;
933 DWORD wFlags;
934 HMENU hMenu;
935 BOOL fExplore = FALSE;
936 HWND hwndTree = 0;
937 LPCONTEXTMENU pContextMenu = NULL;
938 IContextMenu2 *pCM = NULL;
939 CMINVOKECOMMANDINFO cmi;
941 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
943 /* look, what's selected and create a context menu object of it*/
944 if( ShellView_GetSelections(This) )
946 IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
947 (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
949 if(pContextMenu)
951 TRACE("-- pContextMenu\n");
952 hMenu = CreatePopupMenu();
954 if( hMenu )
956 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
957 if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
959 TRACE("-- explore mode\n");
960 fExplore = TRUE;
963 /* build the flags depending on what we can do with the selected item */
964 wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
966 /* let the ContextMenu merge its items in */
967 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
969 if (This->FolderSettings.fFlags & FWF_DESKTOP)
970 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
972 if( bDefault )
974 TRACE("-- get menu default command\n");
975 uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
977 else
979 TRACE("-- track popup\n");
980 uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
983 if(uCommand > 0)
985 TRACE("-- uCommand=%u\n", uCommand);
986 if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
988 TRACE("-- dlg: OnDefaultCommand\n");
989 if (OnDefaultCommand(This) != S_OK)
991 ShellView_OpenSelectedItems(This);
994 else
996 TRACE("-- explore -- invoke command\n");
997 ZeroMemory(&cmi, sizeof(cmi));
998 cmi.cbSize = sizeof(cmi);
999 cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
1000 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1001 IContextMenu_InvokeCommand(pContextMenu, &cmi);
1004 DestroyMenu(hMenu);
1007 if (pContextMenu)
1008 IContextMenu_Release(pContextMenu);
1011 else /* background context menu */
1013 hMenu = CreatePopupMenu();
1015 pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
1016 IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1018 uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1019 DestroyMenu(hMenu);
1021 TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1023 ZeroMemory(&cmi, sizeof(cmi));
1024 cmi.cbSize = sizeof(cmi);
1025 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1026 cmi.hwnd = This->hWndParent;
1027 IContextMenu2_InvokeCommand(pCM, &cmi);
1029 IContextMenu2_Release(pCM);
1033 /**********************************************************
1034 * ##### message handling #####
1037 /**********************************************************
1038 * ShellView_OnSize()
1040 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1042 TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1044 /*resize the ListView to fit our window*/
1045 if(This->hWndList)
1047 MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1050 return S_OK;
1052 /**********************************************************
1053 * ShellView_OnDeactivate()
1055 * NOTES
1056 * internal
1058 static void ShellView_OnDeactivate(IShellViewImpl * This)
1060 TRACE("%p\n",This);
1062 if(This->uState != SVUIA_DEACTIVATE)
1064 if(This->hMenu)
1066 IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1067 IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1068 DestroyMenu(This->hMenu);
1069 This->hMenu = 0;
1072 This->uState = SVUIA_DEACTIVATE;
1076 /**********************************************************
1077 * ShellView_OnActivate()
1079 static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState)
1080 { OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} };
1081 MENUITEMINFOA mii;
1082 CHAR szText[MAX_PATH];
1084 TRACE("%p uState=%x\n",This,uState);
1086 /*don't do anything if the state isn't really changing */
1087 if(This->uState == uState)
1089 return S_OK;
1092 ShellView_OnDeactivate(This);
1094 /*only do This if we are active */
1095 if(uState != SVUIA_DEACTIVATE)
1097 /*merge the menus */
1098 This->hMenu = CreateMenu();
1100 if(This->hMenu)
1102 IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1103 TRACE("-- after fnInsertMenusSB\n");
1105 /*build the top level menu get the menu item's text*/
1106 strcpy(szText,"dummy 31");
1108 ZeroMemory(&mii, sizeof(mii));
1109 mii.cbSize = sizeof(mii);
1110 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1111 mii.fType = MFT_STRING;
1112 mii.fState = MFS_ENABLED;
1113 mii.dwTypeData = szText;
1114 mii.hSubMenu = ShellView_BuildFileMenu(This);
1116 /*insert our menu into the menu bar*/
1117 if(mii.hSubMenu)
1119 InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1122 /*get the view menu so we can merge with it*/
1123 ZeroMemory(&mii, sizeof(mii));
1124 mii.cbSize = sizeof(mii);
1125 mii.fMask = MIIM_SUBMENU;
1127 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1129 ShellView_MergeViewMenu(This, mii.hSubMenu);
1132 /*add the items that should only be added if we have the focus*/
1133 if(SVUIA_ACTIVATE_FOCUS == uState)
1135 /*get the file menu so we can merge with it */
1136 ZeroMemory(&mii, sizeof(mii));
1137 mii.cbSize = sizeof(mii);
1138 mii.fMask = MIIM_SUBMENU;
1140 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1142 ShellView_MergeFileMenu(This, mii.hSubMenu);
1145 TRACE("-- before fnSetMenuSB\n");
1146 IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1149 This->uState = uState;
1150 TRACE("--\n");
1151 return S_OK;
1154 /**********************************************************
1155 * ShellView_OnSetFocus()
1158 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1160 TRACE("%p\n",This);
1162 /* Tell the browser one of our windows has received the focus. This
1163 should always be done before merging menus (OnActivate merges the
1164 menus) if one of our windows has the focus.*/
1166 IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1167 ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1169 /* Set the focus to the listview */
1170 SetFocus(This->hWndList);
1172 /* Notify the ICommDlgBrowser interface */
1173 OnStateChange(This,CDBOSC_SETFOCUS);
1175 return 0;
1178 /**********************************************************
1179 * ShellView_OnKillFocus()
1181 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1183 TRACE("(%p) stub\n",This);
1185 ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1186 /* Notify the ICommDlgBrowser */
1187 OnStateChange(This,CDBOSC_KILLFOCUS);
1189 return 0;
1192 /**********************************************************
1193 * ShellView_OnCommand()
1195 * NOTES
1196 * the CmdID's are the ones from the context menu
1198 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1200 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1202 switch(dwCmdID)
1204 case FCIDM_SHVIEW_SMALLICON:
1205 This->FolderSettings.ViewMode = FVM_SMALLICON;
1206 SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1207 CheckToolbar(This);
1208 break;
1210 case FCIDM_SHVIEW_BIGICON:
1211 This->FolderSettings.ViewMode = FVM_ICON;
1212 SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1213 CheckToolbar(This);
1214 break;
1216 case FCIDM_SHVIEW_LISTVIEW:
1217 This->FolderSettings.ViewMode = FVM_LIST;
1218 SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1219 CheckToolbar(This);
1220 break;
1222 case FCIDM_SHVIEW_REPORTVIEW:
1223 This->FolderSettings.ViewMode = FVM_DETAILS;
1224 SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1225 CheckToolbar(This);
1226 break;
1228 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1229 case 0x30:
1230 case 0x31:
1231 case 0x32:
1232 case 0x33:
1233 This->ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30);
1234 This->ListViewSortInfo.bIsAscending = TRUE;
1235 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1236 SendMessageA(This->hWndList, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1237 break;
1239 default:
1240 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID);
1242 return 0;
1245 /**********************************************************
1246 * ShellView_OnNotify()
1249 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1250 { LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1251 NMLVDISPINFOA *lpdi = (NMLVDISPINFOA *)lpnmh;
1252 LPITEMIDLIST pidl;
1254 TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1256 switch(lpnmh->code)
1258 case NM_SETFOCUS:
1259 TRACE("-- NM_SETFOCUS %p\n",This);
1260 ShellView_OnSetFocus(This);
1261 break;
1263 case NM_KILLFOCUS:
1264 TRACE("-- NM_KILLFOCUS %p\n",This);
1265 ShellView_OnDeactivate(This);
1266 /* Notify the ICommDlgBrowser interface */
1267 OnStateChange(This,CDBOSC_KILLFOCUS);
1268 break;
1270 case NM_CUSTOMDRAW:
1271 TRACE("-- NM_CUSTOMDRAW %p\n",This);
1272 return CDRF_DODEFAULT;
1274 case NM_RELEASEDCAPTURE:
1275 TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1276 break;
1278 case NM_CLICK:
1279 TRACE("-- NM_CLICK %p\n",This);
1280 break;
1282 case NM_RCLICK:
1283 TRACE("-- NM_RCLICK %p\n",This);
1284 break;
1286 case NM_DBLCLK:
1287 TRACE("-- NM_DBLCLK %p\n",This);
1288 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1289 break;
1291 case NM_RETURN:
1292 TRACE("-- NM_DBLCLK %p\n",This);
1293 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1294 break;
1296 case HDN_ENDTRACKA:
1297 TRACE("-- HDN_ENDTRACKA %p\n",This);
1298 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1299 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1300 break;
1302 case LVN_DELETEITEM:
1303 TRACE("-- LVN_DELETEITEM %p\n",This);
1304 SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/
1305 break;
1307 case LVN_DELETEALLITEMS:
1308 TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1309 return FALSE;
1311 case LVN_INSERTITEM:
1312 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1313 break;
1315 case LVN_ITEMACTIVATE:
1316 TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1317 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1318 break;
1320 case LVN_COLUMNCLICK:
1321 This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1322 if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1324 This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1326 else
1328 This->ListViewSortInfo.bIsAscending = TRUE;
1330 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1332 SendMessageA(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1333 break;
1335 case LVN_GETDISPINFOA:
1336 case LVN_GETDISPINFOW:
1337 TRACE("-- LVN_GETDISPINFO %p\n",This);
1338 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1340 if(lpdi->item.mask & LVIF_TEXT) /* text requested */
1342 if (This->pSF2Parent)
1344 SHELLDETAILS sd;
1345 IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1346 if (lpnmh->code == LVN_GETDISPINFOA)
1348 StrRetToStrNA( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1349 TRACE("-- text=%s\n",lpdi->item.pszText);
1351 else /* LVN_GETDISPINFOW */
1353 StrRetToStrNW( ((NMLVDISPINFOW *)lpdi)->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1354 TRACE("-- text=%s\n",debugstr_w((WCHAR*)(lpdi->item.pszText)));
1357 else
1359 FIXME("no SF2\n");
1362 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1364 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1366 break;
1368 case LVN_ITEMCHANGED:
1369 TRACE("-- LVN_ITEMCHANGED %p\n",This);
1370 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1371 break;
1373 case LVN_BEGINDRAG:
1374 case LVN_BEGINRDRAG:
1375 TRACE("-- LVN_BEGINDRAG\n");
1377 if (ShellView_GetSelections(This))
1379 IDataObject * pda;
1380 DWORD dwAttributes = SFGAO_CANLINK;
1381 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1383 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1385 IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource); /* own DropSource interface */
1387 if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1389 if (dwAttributes & SFGAO_CANLINK)
1391 dwEffect |= DROPEFFECT_LINK;
1395 if (pds)
1397 DWORD dwEffect;
1398 DoDragDrop(pda, pds, dwEffect, &dwEffect);
1400 IDataObject_Release(pda);
1403 break;
1405 case LVN_BEGINLABELEDITA:
1407 DWORD dwAttr = SFGAO_CANRENAME;
1408 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1410 TRACE("-- LVN_BEGINLABELEDITA %p\n",This);
1412 IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1413 if (SFGAO_CANRENAME & dwAttr)
1415 return FALSE;
1417 return TRUE;
1420 case LVN_ENDLABELEDITA:
1422 TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1423 if (lpdi->item.pszText)
1425 HRESULT hr;
1426 WCHAR wszNewName[MAX_PATH];
1427 LVITEMA lvItem;
1429 lvItem.iItem = lpdi->item.iItem;
1430 lvItem.iSubItem = 0;
1431 lvItem.mask = LVIF_PARAM;
1432 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
1434 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1435 if (!MultiByteToWideChar( CP_ACP, 0, lpdi->item.pszText, -1, wszNewName, MAX_PATH ))
1436 wszNewName[MAX_PATH-1] = 0;
1437 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, wszNewName, SHGDN_INFOLDER, &pidl);
1439 if(SUCCEEDED(hr) && pidl)
1441 lvItem.mask = LVIF_PARAM;
1442 lvItem.lParam = (LPARAM)pidl;
1443 SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem);
1444 return TRUE;
1447 return FALSE;
1450 case LVN_KEYDOWN:
1452 /* MSG msg;
1453 msg.hwnd = This->hWnd;
1454 msg.message = WM_KEYDOWN;
1455 msg.wParam = plvKeyDown->wVKey;
1456 msg.lParam = 0;
1457 msg.time = 0;
1458 msg.pt = 0;*/
1460 LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1462 /* initiate a rename of the selected file or directory */
1463 if(plvKeyDown->wVKey == VK_F2)
1465 /* see how many files are selected */
1466 int i = ListView_GetSelectedCount(This->hWndList);
1468 /* get selected item */
1469 if(i == 1)
1471 /* get selected item */
1472 i = ListView_GetNextItem(This->hWndList, -1,
1473 LVNI_SELECTED);
1475 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1476 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
1479 #if 0
1480 TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1481 #endif
1482 else if(plvKeyDown->wVKey == VK_DELETE)
1484 UINT i;
1485 int item_index;
1486 LVITEMA item;
1487 LPITEMIDLIST* pItems;
1488 ISFHelper *psfhlp;
1490 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1491 (LPVOID*)&psfhlp);
1493 if (psfhlp == NULL)
1494 break;
1496 if(!(i = ListView_GetSelectedCount(This->hWndList)))
1497 break;
1499 /* allocate memory for the pidl array */
1500 pItems = HeapAlloc(GetProcessHeap(), 0,
1501 sizeof(LPITEMIDLIST) * i);
1503 /* retrieve all selected items */
1504 i = 0;
1505 item_index = -1;
1506 while(ListView_GetSelectedCount(This->hWndList) > i)
1508 /* get selected item */
1509 item_index = ListView_GetNextItem(This->hWndList,
1510 item_index, LVNI_SELECTED);
1511 item.iItem = item_index;
1512 item.mask = LVIF_PARAM;
1513 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &item);
1515 /* get item pidl */
1516 pItems[i] = (LPITEMIDLIST)item.lParam;
1518 i++;
1521 /* perform the item deletion */
1522 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1524 /* free pidl array memory */
1525 HeapFree(GetProcessHeap(), 0, pItems);
1528 /* Initiate a refresh */
1529 else if(plvKeyDown->wVKey == VK_F5)
1531 IShellView_Refresh((IShellView*)This);
1534 else
1535 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1537 break;
1539 default:
1540 TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1541 break;
1543 return 0;
1546 /**********************************************************
1547 * ShellView_OnChange()
1550 static LRESULT ShellView_OnChange(IShellViewImpl * This, LPITEMIDLIST * Pidls, LONG wEventId)
1553 TRACE("(%p)(%p,%p,0x%08x)\n", This, Pidls[0], Pidls[1], wEventId);
1554 switch(wEventId)
1556 case SHCNE_MKDIR:
1557 case SHCNE_CREATE:
1558 LV_AddItem(This, Pidls[0]);
1559 break;
1560 case SHCNE_RMDIR:
1561 case SHCNE_DELETE:
1562 LV_DeleteItem(This, Pidls[0]);
1563 break;
1564 case SHCNE_RENAMEFOLDER:
1565 case SHCNE_RENAMEITEM:
1566 LV_RenameItem(This, Pidls[0], Pidls[1]);
1567 break;
1568 case SHCNE_UPDATEITEM:
1569 break;
1571 return TRUE;
1573 /**********************************************************
1574 * ShellView_WndProc
1577 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1579 IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1580 LPCREATESTRUCTA lpcs;
1582 TRACE("(hwnd=%p msg=%x wparm=%x lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1584 switch (uMessage)
1586 case WM_NCCREATE:
1587 lpcs = (LPCREATESTRUCTA)lParam;
1588 pThis = (IShellViewImpl*)(lpcs->lpCreateParams);
1589 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1590 pThis->hWnd = hWnd; /*set the window handle*/
1591 break;
1593 case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1594 case WM_SETFOCUS: return ShellView_OnSetFocus(pThis);
1595 case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis);
1596 case WM_CREATE: return ShellView_OnCreate(pThis);
1597 case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1598 case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1599 case WM_COMMAND: return ShellView_OnCommand(pThis,
1600 GET_WM_COMMAND_ID(wParam, lParam),
1601 GET_WM_COMMAND_CMD(wParam, lParam),
1602 GET_WM_COMMAND_HWND(wParam, lParam));
1603 case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (LPITEMIDLIST*)wParam, (LONG)lParam);
1605 case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1606 return 0;
1608 case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
1609 break;
1611 case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0);
1613 case WM_DESTROY:
1614 RevokeDragDrop(pThis->hWnd);
1615 SHChangeNotifyDeregister(pThis->hNotify);
1616 break;
1618 case WM_ERASEBKGND:
1619 if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1620 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1621 return 1;
1622 break;
1625 return DefWindowProcA (hWnd, uMessage, wParam, lParam);
1627 /**********************************************************
1630 * The INTERFACE of the IShellView object
1633 **********************************************************
1634 * IShellView_QueryInterface
1636 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj)
1638 IShellViewImpl *This = (IShellViewImpl *)iface;
1640 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1642 *ppvObj = NULL;
1644 if(IsEqualIID(riid, &IID_IUnknown))
1646 *ppvObj = This;
1648 else if(IsEqualIID(riid, &IID_IShellView))
1650 *ppvObj = (IShellView*)This;
1652 else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1654 *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget);
1656 else if(IsEqualIID(riid, &IID_IDropTarget))
1658 *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
1660 else if(IsEqualIID(riid, &IID_IDropSource))
1662 *ppvObj = (IDropSource*)&(This->lpvtblDropSource);
1664 else if(IsEqualIID(riid, &IID_IViewObject))
1666 *ppvObj = (IViewObject*)&(This->lpvtblViewObject);
1669 if(*ppvObj)
1671 IUnknown_AddRef( (IUnknown*)*ppvObj );
1672 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1673 return S_OK;
1675 TRACE("-- Interface: E_NOINTERFACE\n");
1676 return E_NOINTERFACE;
1679 /**********************************************************
1680 * IShellView_AddRef
1682 static ULONG WINAPI IShellView_fnAddRef(IShellView * iface)
1684 IShellViewImpl *This = (IShellViewImpl *)iface;
1685 ULONG refCount = InterlockedIncrement(&This->ref);
1687 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
1689 return refCount;
1691 /**********************************************************
1692 * IShellView_Release
1694 static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
1696 IShellViewImpl *This = (IShellViewImpl *)iface;
1697 ULONG refCount = InterlockedDecrement(&This->ref);
1699 TRACE("(%p)->(count=%i)\n", This, refCount + 1);
1701 if (!refCount)
1703 TRACE(" destroying IShellView(%p)\n",This);
1705 DestroyWindow(This->hWndList);
1707 if(This->pSFParent)
1708 IShellFolder_Release(This->pSFParent);
1710 if(This->pSF2Parent)
1711 IShellFolder2_Release(This->pSF2Parent);
1713 SHFree(This->apidl);
1715 if(This->pAdvSink)
1716 IAdviseSink_Release(This->pAdvSink);
1718 HeapFree(GetProcessHeap(),0,This);
1720 return refCount;
1723 /**********************************************************
1724 * ShellView_GetWindow
1726 static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd)
1728 IShellViewImpl *This = (IShellViewImpl *)iface;
1730 TRACE("(%p)\n",This);
1732 *phWnd = This->hWnd;
1734 return S_OK;
1737 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode)
1739 IShellViewImpl *This = (IShellViewImpl *)iface;
1741 FIXME("(%p) stub\n",This);
1743 return E_NOTIMPL;
1746 /**********************************************************
1747 * IShellView_TranslateAccelerator
1749 * FIXME:
1750 * use the accel functions
1752 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg)
1754 #if 0
1755 IShellViewImpl *This = (IShellViewImpl *)iface;
1757 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1758 #endif
1760 if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1762 TRACE("-- key=0x04%x\n",lpmsg->wParam) ;
1764 return S_FALSE; /* not handled */
1767 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable)
1769 IShellViewImpl *This = (IShellViewImpl *)iface;
1771 FIXME("(%p) stub\n",This);
1773 return E_NOTIMPL;
1776 static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState)
1778 IShellViewImpl *This = (IShellViewImpl *)iface;
1781 CHAR szName[MAX_PATH];
1783 LRESULT lResult;
1784 int nPartArray[1] = {-1};
1786 TRACE("(%p)->(state=%x) stub\n",This, uState);
1788 /*don't do anything if the state isn't really changing*/
1789 if(This->uState == uState)
1791 return S_OK;
1794 /*OnActivate handles the menu merging and internal state*/
1795 ShellView_OnActivate(This, uState);
1797 /*only do This if we are active*/
1798 if(uState != SVUIA_DEACTIVATE)
1802 GetFolderPath is not a method of IShellFolder
1803 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1805 /* set the number of parts */
1806 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1807 (LPARAM)nPartArray, &lResult);
1809 /* set the text for the parts */
1811 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1812 0, (LPARAM)szName, &lResult);
1816 return S_OK;
1819 static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface)
1821 IShellViewImpl *This = (IShellViewImpl *)iface;
1823 TRACE("(%p)\n",This);
1825 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
1826 ShellView_FillList(This);
1828 return S_OK;
1831 static HRESULT WINAPI IShellView_fnCreateViewWindow(
1832 IShellView * iface,
1833 IShellView *lpPrevView,
1834 LPCFOLDERSETTINGS lpfs,
1835 IShellBrowser * psb,
1836 RECT * prcView,
1837 HWND *phWnd)
1839 IShellViewImpl *This = (IShellViewImpl *)iface;
1841 WNDCLASSA wc;
1842 *phWnd = 0;
1845 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd);
1846 TRACE("-- vmode=%x flags=%x left=%i top=%i right=%i bottom=%i\n",lpfs->ViewMode, lpfs->fFlags ,prcView->left,prcView->top, prcView->right, prcView->bottom);
1848 /*set up the member variables*/
1849 This->pShellBrowser = psb;
1850 This->FolderSettings = *lpfs;
1852 /*get our parent window*/
1853 IShellBrowser_AddRef(This->pShellBrowser);
1854 IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
1856 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1857 This->pCommDlgBrowser=NULL;
1858 if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser,
1859 (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser)))
1861 TRACE("-- CommDlgBrowser\n");
1864 /*if our window class has not been registered, then do so*/
1865 if(!GetClassInfoA(shell32_hInstance, SV_CLASS_NAME, &wc))
1867 ZeroMemory(&wc, sizeof(wc));
1868 wc.style = CS_HREDRAW | CS_VREDRAW;
1869 wc.lpfnWndProc = ShellView_WndProc;
1870 wc.cbClsExtra = 0;
1871 wc.cbWndExtra = 0;
1872 wc.hInstance = shell32_hInstance;
1873 wc.hIcon = 0;
1874 wc.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
1875 wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
1876 wc.lpszMenuName = NULL;
1877 wc.lpszClassName = SV_CLASS_NAME;
1879 if(!RegisterClassA(&wc))
1880 return E_FAIL;
1883 *phWnd = CreateWindowExA(0,
1884 SV_CLASS_NAME,
1885 NULL,
1886 WS_CHILD | WS_TABSTOP,
1887 prcView->left,
1888 prcView->top,
1889 prcView->right - prcView->left,
1890 prcView->bottom - prcView->top,
1891 This->hWndParent,
1893 shell32_hInstance,
1894 (LPVOID)This);
1896 CheckToolbar(This);
1898 if(!*phWnd) return E_FAIL;
1900 SetWindowPos(*phWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
1901 UpdateWindow(*phWnd);
1903 return S_OK;
1906 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
1908 IShellViewImpl *This = (IShellViewImpl *)iface;
1910 TRACE("(%p)\n",This);
1912 /*Make absolutely sure all our UI is cleaned up.*/
1913 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1915 if(This->hMenu)
1917 DestroyMenu(This->hMenu);
1920 DestroyWindow(This->hWnd);
1921 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1922 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1925 return S_OK;
1928 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs)
1930 IShellViewImpl *This = (IShellViewImpl *)iface;
1932 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1933 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1935 if (!lpfs) return E_INVALIDARG;
1937 *lpfs = This->FolderSettings;
1938 return NOERROR;
1941 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1943 IShellViewImpl *This = (IShellViewImpl *)iface;
1945 FIXME("(%p) stub\n",This);
1947 return E_NOTIMPL;
1950 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface)
1952 IShellViewImpl *This = (IShellViewImpl *)iface;
1954 FIXME("(%p) stub\n",This);
1956 return S_OK;
1959 static HRESULT WINAPI IShellView_fnSelectItem(
1960 IShellView * iface,
1961 LPCITEMIDLIST pidl,
1962 UINT uFlags)
1964 IShellViewImpl *This = (IShellViewImpl *)iface;
1965 int i;
1967 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
1969 i = LV_FindItemByPidl(This, pidl);
1971 if (i != -1)
1973 LVITEMA lvItem;
1975 if(uFlags & SVSI_ENSUREVISIBLE)
1976 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1978 lvItem.mask = LVIF_STATE;
1979 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
1980 lvItem.iItem = 0;
1981 lvItem.iSubItem = 0;
1983 while(SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem))
1985 if (lvItem.iItem == i)
1987 if (uFlags & SVSI_SELECT)
1988 lvItem.state |= LVIS_SELECTED;
1989 else
1990 lvItem.state &= ~LVIS_SELECTED;
1992 if(uFlags & SVSI_FOCUSED)
1993 lvItem.state &= ~LVIS_FOCUSED;
1995 else
1997 if (uFlags & SVSI_DESELECTOTHERS)
1998 lvItem.state &= ~LVIS_SELECTED;
2000 SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem);
2001 lvItem.iItem++;
2005 if(uFlags & SVSI_EDIT)
2006 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
2009 return S_OK;
2012 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
2014 HRESULT hr = S_OK;
2015 IShellViewImpl *This = (IShellViewImpl *)iface;
2017 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2019 *ppvOut = NULL;
2021 switch(uItem)
2023 case SVGIO_BACKGROUND:
2024 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2025 break;
2027 case SVGIO_SELECTION:
2028 ShellView_GetSelections(This);
2029 IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2030 break;
2032 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2034 if(!*ppvOut) return E_OUTOFMEMORY;
2037 * Return the correct interface
2039 if (riid)
2041 IUnknown *check = *ppvOut;
2042 hr = IUnknown_QueryInterface(check, riid, ppvOut);
2043 if (hr==S_OK)
2044 IUnknown_Release(check);
2047 return hr;
2050 static const IShellViewVtbl svvt =
2052 IShellView_fnQueryInterface,
2053 IShellView_fnAddRef,
2054 IShellView_fnRelease,
2055 IShellView_fnGetWindow,
2056 IShellView_fnContextSensitiveHelp,
2057 IShellView_fnTranslateAccelerator,
2058 IShellView_fnEnableModeless,
2059 IShellView_fnUIActivate,
2060 IShellView_fnRefresh,
2061 IShellView_fnCreateViewWindow,
2062 IShellView_fnDestroyViewWindow,
2063 IShellView_fnGetCurrentInfo,
2064 IShellView_fnAddPropertySheetPages,
2065 IShellView_fnSaveViewState,
2066 IShellView_fnSelectItem,
2067 IShellView_fnGetItemObject
2071 /**********************************************************
2072 * ISVOleCmdTarget_QueryInterface (IUnknown)
2074 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2075 IOleCommandTarget * iface,
2076 REFIID iid,
2077 LPVOID* ppvObj)
2079 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2081 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2084 /**********************************************************
2085 * ISVOleCmdTarget_AddRef (IUnknown)
2087 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2088 IOleCommandTarget * iface)
2090 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2092 return IShellFolder_AddRef((IShellFolder*)This);
2095 /**********************************************************
2096 * ISVOleCmdTarget_Release (IUnknown)
2098 static ULONG WINAPI ISVOleCmdTarget_Release(
2099 IOleCommandTarget * iface)
2101 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2103 return IShellFolder_Release((IShellFolder*)This);
2106 /**********************************************************
2107 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2109 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2110 IOleCommandTarget *iface,
2111 const GUID* pguidCmdGroup,
2112 ULONG cCmds,
2113 OLECMD * prgCmds,
2114 OLECMDTEXT* pCmdText)
2116 UINT i;
2117 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2119 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2120 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2122 if (!prgCmds)
2123 return E_POINTER;
2124 for (i = 0; i < cCmds; i++)
2126 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2127 prgCmds[i].cmdf = 0;
2129 return OLECMDERR_E_UNKNOWNGROUP;
2132 /**********************************************************
2133 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2135 * nCmdID is the OLECMDID_* enumeration
2137 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2138 IOleCommandTarget *iface,
2139 const GUID* pguidCmdGroup,
2140 DWORD nCmdID,
2141 DWORD nCmdexecopt,
2142 VARIANT* pvaIn,
2143 VARIANT* pvaOut)
2145 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2147 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2148 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2150 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2151 (nCmdID == 0x29) &&
2152 (nCmdexecopt == 4) && pvaOut)
2153 return S_OK;
2154 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2155 (nCmdID == 9) &&
2156 (nCmdexecopt == 0))
2157 return 1;
2159 return OLECMDERR_E_UNKNOWNGROUP;
2162 static const IOleCommandTargetVtbl ctvt =
2164 ISVOleCmdTarget_QueryInterface,
2165 ISVOleCmdTarget_AddRef,
2166 ISVOleCmdTarget_Release,
2167 ISVOleCmdTarget_QueryStatus,
2168 ISVOleCmdTarget_Exec
2171 /**********************************************************
2172 * ISVDropTarget implementation
2175 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2176 IDropTarget *iface,
2177 REFIID riid,
2178 LPVOID *ppvObj)
2180 IShellViewImpl *This = impl_from_IDropTarget(iface);
2182 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2184 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2187 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2189 IShellViewImpl *This = impl_from_IDropTarget(iface);
2191 TRACE("(%p)->(count=%u)\n",This,This->ref);
2193 return IShellFolder_AddRef((IShellFolder*)This);
2196 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2198 IShellViewImpl *This = impl_from_IDropTarget(iface);
2200 TRACE("(%p)->(count=%u)\n",This,This->ref);
2202 return IShellFolder_Release((IShellFolder*)This);
2205 /******************************************************************************
2206 * drag_notify_subitem [Internal]
2208 * Figure out the shellfolder object, which is currently under the mouse cursor
2209 * and notify it via the IDropTarget interface.
2212 #define SCROLLAREAWIDTH 20
2214 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2215 DWORD *pdwEffect)
2217 LVHITTESTINFO htinfo;
2218 LVITEMA lvItem;
2219 LONG lResult;
2220 HRESULT hr;
2221 RECT clientRect;
2223 /* Map from global to client coordinates and query the index of the listview-item, which is
2224 * currently under the mouse cursor. */
2225 htinfo.pt.x = pt.x;
2226 htinfo.pt.y = pt.y;
2227 htinfo.flags = LVHT_ONITEM;
2228 ScreenToClient(This->hWndList, &htinfo.pt);
2229 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2231 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2232 GetClientRect(This->hWndList, &clientRect);
2233 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2234 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2235 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2237 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2238 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2239 if (htinfo.pt.x < SCROLLAREAWIDTH)
2240 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2241 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2242 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2243 if (htinfo.pt.y < SCROLLAREAWIDTH)
2244 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2245 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2246 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2248 } else {
2249 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2251 This->ptLastMousePos = htinfo.pt;
2253 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2254 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2255 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2257 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2258 if (This->pCurDropTarget) {
2259 IDropTarget_DragLeave(This->pCurDropTarget);
2260 IDropTarget_Release(This->pCurDropTarget);
2261 This->pCurDropTarget = NULL;
2264 This->iDragOverItem = lResult;
2265 if (lResult == -1) {
2266 /* We are not above one of the listview's subitems. Bind to the parent folder's
2267 * DropTarget interface. */
2268 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2269 (LPVOID*)&This->pCurDropTarget);
2270 } else {
2271 /* Query the relative PIDL of the shellfolder object represented by the currently
2272 * dragged over listview-item ... */
2273 lvItem.mask = LVIF_PARAM;
2274 lvItem.iItem = lResult;
2275 lvItem.iSubItem = 0;
2276 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
2278 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2279 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2280 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2283 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2284 if (FAILED(hr))
2285 return hr;
2287 /* Notify the item just entered via DragEnter. */
2288 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2291 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2292 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2294 IShellViewImpl *This = impl_from_IDropTarget(iface);
2296 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2297 This->pCurDataObject = pDataObject;
2298 IDataObject_AddRef(pDataObject);
2300 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2303 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2304 DWORD *pdwEffect)
2306 IShellViewImpl *This = impl_from_IDropTarget(iface);
2307 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2310 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2311 IShellViewImpl *This = impl_from_IDropTarget(iface);
2313 IDropTarget_DragLeave(This->pCurDropTarget);
2315 IDropTarget_Release(This->pCurDropTarget);
2316 IDataObject_Release(This->pCurDataObject);
2317 This->pCurDataObject = NULL;
2318 This->pCurDropTarget = NULL;
2319 This->iDragOverItem = 0;
2321 return S_OK;
2324 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2325 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2327 IShellViewImpl *This = impl_from_IDropTarget(iface);
2329 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2331 IDropTarget_Release(This->pCurDropTarget);
2332 IDataObject_Release(This->pCurDataObject);
2333 This->pCurDataObject = NULL;
2334 This->pCurDropTarget = NULL;
2335 This->iDragOverItem = 0;
2337 return S_OK;
2340 static const IDropTargetVtbl dtvt =
2342 ISVDropTarget_QueryInterface,
2343 ISVDropTarget_AddRef,
2344 ISVDropTarget_Release,
2345 ISVDropTarget_DragEnter,
2346 ISVDropTarget_DragOver,
2347 ISVDropTarget_DragLeave,
2348 ISVDropTarget_Drop
2351 /**********************************************************
2352 * ISVDropSource implementation
2355 static HRESULT WINAPI ISVDropSource_QueryInterface(
2356 IDropSource *iface,
2357 REFIID riid,
2358 LPVOID *ppvObj)
2360 IShellViewImpl *This = impl_from_IDropSource(iface);
2362 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2364 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2367 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2369 IShellViewImpl *This = impl_from_IDropSource(iface);
2371 TRACE("(%p)->(count=%u)\n",This,This->ref);
2373 return IShellFolder_AddRef((IShellFolder*)This);
2376 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2378 IShellViewImpl *This = impl_from_IDropSource(iface);
2380 TRACE("(%p)->(count=%u)\n",This,This->ref);
2382 return IShellFolder_Release((IShellFolder*)This);
2384 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2385 IDropSource *iface,
2386 BOOL fEscapePressed,
2387 DWORD grfKeyState)
2389 IShellViewImpl *This = impl_from_IDropSource(iface);
2390 TRACE("(%p)\n",This);
2392 if (fEscapePressed)
2393 return DRAGDROP_S_CANCEL;
2394 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2395 return DRAGDROP_S_DROP;
2396 else
2397 return NOERROR;
2400 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2401 IDropSource *iface,
2402 DWORD dwEffect)
2404 IShellViewImpl *This = impl_from_IDropSource(iface);
2405 TRACE("(%p)\n",This);
2407 return DRAGDROP_S_USEDEFAULTCURSORS;
2410 static const IDropSourceVtbl dsvt =
2412 ISVDropSource_QueryInterface,
2413 ISVDropSource_AddRef,
2414 ISVDropSource_Release,
2415 ISVDropSource_QueryContinueDrag,
2416 ISVDropSource_GiveFeedback
2418 /**********************************************************
2419 * ISVViewObject implementation
2422 static HRESULT WINAPI ISVViewObject_QueryInterface(
2423 IViewObject *iface,
2424 REFIID riid,
2425 LPVOID *ppvObj)
2427 IShellViewImpl *This = impl_from_IViewObject(iface);
2429 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2431 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2434 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2436 IShellViewImpl *This = impl_from_IViewObject(iface);
2438 TRACE("(%p)->(count=%u)\n",This,This->ref);
2440 return IShellFolder_AddRef((IShellFolder*)This);
2443 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2445 IShellViewImpl *This = impl_from_IViewObject(iface);
2447 TRACE("(%p)->(count=%u)\n",This,This->ref);
2449 return IShellFolder_Release((IShellFolder*)This);
2452 static HRESULT WINAPI ISVViewObject_Draw(
2453 IViewObject *iface,
2454 DWORD dwDrawAspect,
2455 LONG lindex,
2456 void* pvAspect,
2457 DVTARGETDEVICE* ptd,
2458 HDC hdcTargetDev,
2459 HDC hdcDraw,
2460 LPCRECTL lprcBounds,
2461 LPCRECTL lprcWBounds,
2462 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2463 ULONG_PTR dwContinue)
2466 IShellViewImpl *This = impl_from_IViewObject(iface);
2468 FIXME("Stub: This=%p\n",This);
2470 return E_NOTIMPL;
2472 static HRESULT WINAPI ISVViewObject_GetColorSet(
2473 IViewObject *iface,
2474 DWORD dwDrawAspect,
2475 LONG lindex,
2476 void *pvAspect,
2477 DVTARGETDEVICE* ptd,
2478 HDC hicTargetDevice,
2479 LOGPALETTE** ppColorSet)
2482 IShellViewImpl *This = impl_from_IViewObject(iface);
2484 FIXME("Stub: This=%p\n",This);
2486 return E_NOTIMPL;
2488 static HRESULT WINAPI ISVViewObject_Freeze(
2489 IViewObject *iface,
2490 DWORD dwDrawAspect,
2491 LONG lindex,
2492 void* pvAspect,
2493 DWORD* pdwFreeze)
2496 IShellViewImpl *This = impl_from_IViewObject(iface);
2498 FIXME("Stub: This=%p\n",This);
2500 return E_NOTIMPL;
2502 static HRESULT WINAPI ISVViewObject_Unfreeze(
2503 IViewObject *iface,
2504 DWORD dwFreeze)
2507 IShellViewImpl *This = impl_from_IViewObject(iface);
2509 FIXME("Stub: This=%p\n",This);
2511 return E_NOTIMPL;
2513 static HRESULT WINAPI ISVViewObject_SetAdvise(
2514 IViewObject *iface,
2515 DWORD aspects,
2516 DWORD advf,
2517 IAdviseSink* pAdvSink)
2520 IShellViewImpl *This = impl_from_IViewObject(iface);
2522 FIXME("partial stub: %p %08x %08x %p\n",
2523 This, aspects, advf, pAdvSink);
2525 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2526 This->pAdvSink = pAdvSink;
2527 This->dwAspects = aspects;
2528 This->dwAdvf = advf;
2530 return S_OK;
2533 static HRESULT WINAPI ISVViewObject_GetAdvise(
2534 IViewObject *iface,
2535 DWORD* pAspects,
2536 DWORD* pAdvf,
2537 IAdviseSink** ppAdvSink)
2540 IShellViewImpl *This = impl_from_IViewObject(iface);
2542 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2543 This, pAspects, pAdvf, ppAdvSink);
2545 if( ppAdvSink )
2547 IAdviseSink_AddRef( This->pAdvSink );
2548 *ppAdvSink = This->pAdvSink;
2550 if( pAspects )
2551 *pAspects = This->dwAspects;
2552 if( pAdvf )
2553 *pAdvf = This->dwAdvf;
2555 return S_OK;
2559 static const IViewObjectVtbl vovt =
2561 ISVViewObject_QueryInterface,
2562 ISVViewObject_AddRef,
2563 ISVViewObject_Release,
2564 ISVViewObject_Draw,
2565 ISVViewObject_GetColorSet,
2566 ISVViewObject_Freeze,
2567 ISVViewObject_Unfreeze,
2568 ISVViewObject_SetAdvise,
2569 ISVViewObject_GetAdvise