shell: Convert the filesystem shell folder to Unicode.
[wine/multimedia.git] / dlls / shell32 / shlview.c
blobf9f07ce70b4bd2c3f7e3c91a270647c8053cb7d5
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_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 SetWindowPos(*phWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
1896 UpdateWindow(*phWnd);
1898 return S_OK;
1901 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
1903 IShellViewImpl *This = (IShellViewImpl *)iface;
1905 TRACE("(%p)\n",This);
1907 /*Make absolutely sure all our UI is cleaned up.*/
1908 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1910 if(This->hMenu)
1912 DestroyMenu(This->hMenu);
1915 DestroyWindow(This->hWnd);
1916 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1917 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1920 return S_OK;
1923 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs)
1925 IShellViewImpl *This = (IShellViewImpl *)iface;
1927 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1928 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1930 if (!lpfs) return E_INVALIDARG;
1932 *lpfs = This->FolderSettings;
1933 return NOERROR;
1936 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1938 IShellViewImpl *This = (IShellViewImpl *)iface;
1940 FIXME("(%p) stub\n",This);
1942 return E_NOTIMPL;
1945 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface)
1947 IShellViewImpl *This = (IShellViewImpl *)iface;
1949 FIXME("(%p) stub\n",This);
1951 return S_OK;
1954 static HRESULT WINAPI IShellView_fnSelectItem(
1955 IShellView * iface,
1956 LPCITEMIDLIST pidl,
1957 UINT uFlags)
1959 IShellViewImpl *This = (IShellViewImpl *)iface;
1960 int i;
1962 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
1964 i = LV_FindItemByPidl(This, pidl);
1966 if (i != -1)
1968 LVITEMA lvItem;
1970 if(uFlags & SVSI_ENSUREVISIBLE)
1971 ListView_EnsureVisible(This->hWndList, i, 0);
1973 ZeroMemory(&lvItem, sizeof(LVITEMA));
1974 lvItem.mask = LVIF_STATE;
1975 lvItem.iItem = 0;
1977 while(ListView_GetItemA(This->hWndList, &lvItem))
1979 if (lvItem.iItem == i)
1981 if (uFlags & SVSI_SELECT)
1982 lvItem.state |= LVIS_SELECTED;
1983 else
1984 lvItem.state &= ~LVIS_SELECTED;
1986 if(uFlags & SVSI_FOCUSED)
1987 lvItem.state &= ~LVIS_FOCUSED;
1989 else
1991 if (uFlags & SVSI_DESELECTOTHERS)
1992 lvItem.state &= ~LVIS_SELECTED;
1994 ListView_SetItemA(This->hWndList, &lvItem);
1995 lvItem.iItem++;
1999 if(uFlags & SVSI_EDIT)
2000 ListView_EditLabelA(This->hWndList, i);
2003 return S_OK;
2006 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
2008 IShellViewImpl *This = (IShellViewImpl *)iface;
2010 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2012 *ppvOut = NULL;
2014 switch(uItem)
2016 case SVGIO_BACKGROUND:
2017 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2018 break;
2020 case SVGIO_SELECTION:
2021 ShellView_GetSelections(This);
2022 IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2023 break;
2025 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2027 if(!*ppvOut) return E_OUTOFMEMORY;
2029 return S_OK;
2032 static const IShellViewVtbl svvt =
2034 IShellView_fnQueryInterface,
2035 IShellView_fnAddRef,
2036 IShellView_fnRelease,
2037 IShellView_fnGetWindow,
2038 IShellView_fnContextSensitiveHelp,
2039 IShellView_fnTranslateAccelerator,
2040 IShellView_fnEnableModeless,
2041 IShellView_fnUIActivate,
2042 IShellView_fnRefresh,
2043 IShellView_fnCreateViewWindow,
2044 IShellView_fnDestroyViewWindow,
2045 IShellView_fnGetCurrentInfo,
2046 IShellView_fnAddPropertySheetPages,
2047 IShellView_fnSaveViewState,
2048 IShellView_fnSelectItem,
2049 IShellView_fnGetItemObject
2053 /**********************************************************
2054 * ISVOleCmdTarget_QueryInterface (IUnknown)
2056 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2057 IOleCommandTarget * iface,
2058 REFIID iid,
2059 LPVOID* ppvObj)
2061 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2063 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2066 /**********************************************************
2067 * ISVOleCmdTarget_AddRef (IUnknown)
2069 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2070 IOleCommandTarget * iface)
2072 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2074 return IShellFolder_AddRef((IShellFolder*)This);
2077 /**********************************************************
2078 * ISVOleCmdTarget_Release (IUnknown)
2080 static ULONG WINAPI ISVOleCmdTarget_Release(
2081 IOleCommandTarget * iface)
2083 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2085 return IShellFolder_Release((IShellFolder*)This);
2088 /**********************************************************
2089 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2091 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2092 IOleCommandTarget *iface,
2093 const GUID* pguidCmdGroup,
2094 ULONG cCmds,
2095 OLECMD * prgCmds,
2096 OLECMDTEXT* pCmdText)
2098 UINT i;
2099 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2101 FIXME("(%p)->(%p(%s) 0x%08lx %p %p\n",
2102 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2104 if (!prgCmds)
2105 return E_POINTER;
2106 for (i = 0; i < cCmds; i++)
2108 FIXME("\tprgCmds[%d].cmdID = %ld\n", i, prgCmds[i].cmdID);
2109 prgCmds[i].cmdf = 0;
2111 return OLECMDERR_E_UNKNOWNGROUP;
2114 /**********************************************************
2115 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2117 * nCmdID is the OLECMDID_* enumeration
2119 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2120 IOleCommandTarget *iface,
2121 const GUID* pguidCmdGroup,
2122 DWORD nCmdID,
2123 DWORD nCmdexecopt,
2124 VARIANT* pvaIn,
2125 VARIANT* pvaOut)
2127 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2129 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08lx Opt:0x%08lx %p %p)\n",
2130 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2132 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2133 (nCmdID == 0x29) &&
2134 (nCmdexecopt == 4) && pvaOut)
2135 return S_OK;
2136 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2137 (nCmdID == 9) &&
2138 (nCmdexecopt == 0))
2139 return 1;
2141 return OLECMDERR_E_UNKNOWNGROUP;
2144 static const IOleCommandTargetVtbl ctvt =
2146 ISVOleCmdTarget_QueryInterface,
2147 ISVOleCmdTarget_AddRef,
2148 ISVOleCmdTarget_Release,
2149 ISVOleCmdTarget_QueryStatus,
2150 ISVOleCmdTarget_Exec
2153 /**********************************************************
2154 * ISVDropTarget implementation
2157 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2158 IDropTarget *iface,
2159 REFIID riid,
2160 LPVOID *ppvObj)
2162 IShellViewImpl *This = impl_from_IDropTarget(iface);
2164 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2166 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2169 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2171 IShellViewImpl *This = impl_from_IDropTarget(iface);
2173 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2175 return IShellFolder_AddRef((IShellFolder*)This);
2178 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2180 IShellViewImpl *This = impl_from_IDropTarget(iface);
2182 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2184 return IShellFolder_Release((IShellFolder*)This);
2187 /******************************************************************************
2188 * drag_notify_subitem [Internal]
2190 * Figure out the shellfolder object, which is currently under the mouse cursor
2191 * and notify it via the IDropTarget interface.
2194 #define SCROLLAREAWIDTH 20
2196 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2197 DWORD *pdwEffect)
2199 LVHITTESTINFO htinfo;
2200 LVITEMA lvItem;
2201 LONG lResult;
2202 HRESULT hr;
2203 RECT clientRect;
2205 /* Map from global to client coordinates and query the index of the listview-item, which is
2206 * currently under the mouse cursor. */
2207 htinfo.pt.x = pt.x;
2208 htinfo.pt.y = pt.y;
2209 htinfo.flags = LVHT_ONITEM;
2210 ScreenToClient(This->hWndList, &htinfo.pt);
2211 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2213 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2214 GetClientRect(This->hWndList, &clientRect);
2215 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2216 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2217 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2219 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2220 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2221 if (htinfo.pt.x < SCROLLAREAWIDTH)
2222 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2223 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2224 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2225 if (htinfo.pt.y < SCROLLAREAWIDTH)
2226 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2227 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2228 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2230 } else {
2231 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2233 This->ptLastMousePos = htinfo.pt;
2235 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2236 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2237 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2239 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2240 if (This->pCurDropTarget) {
2241 IDropTarget_DragLeave(This->pCurDropTarget);
2242 IDropTarget_Release(This->pCurDropTarget);
2243 This->pCurDropTarget = NULL;
2246 This->iDragOverItem = lResult;
2247 if (lResult == -1) {
2248 /* We are not above one of the listview's subitems. Bind to the parent folder's
2249 * DropTarget interface. */
2250 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2251 (LPVOID*)&This->pCurDropTarget);
2252 } else {
2253 /* Query the relative PIDL of the shellfolder object represented by the currently
2254 * dragged over listview-item ... */
2255 ZeroMemory(&lvItem, sizeof(lvItem));
2256 lvItem.mask = LVIF_PARAM;
2257 lvItem.iItem = lResult;
2258 ListView_GetItemA(This->hWndList, &lvItem);
2260 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2261 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2262 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2265 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2266 if (FAILED(hr))
2267 return hr;
2269 /* Notify the item just entered via DragEnter. */
2270 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2273 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2274 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2276 IShellViewImpl *This = impl_from_IDropTarget(iface);
2278 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2279 This->pCurDataObject = pDataObject;
2280 IDataObject_AddRef(pDataObject);
2282 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2285 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2286 DWORD *pdwEffect)
2288 IShellViewImpl *This = impl_from_IDropTarget(iface);
2289 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2292 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2293 IShellViewImpl *This = impl_from_IDropTarget(iface);
2295 IDropTarget_DragLeave(This->pCurDropTarget);
2297 IDropTarget_Release(This->pCurDropTarget);
2298 IDataObject_Release(This->pCurDataObject);
2299 This->pCurDataObject = NULL;
2300 This->pCurDropTarget = NULL;
2301 This->iDragOverItem = 0;
2303 return S_OK;
2306 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2307 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2309 IShellViewImpl *This = impl_from_IDropTarget(iface);
2311 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2313 IDropTarget_Release(This->pCurDropTarget);
2314 IDataObject_Release(This->pCurDataObject);
2315 This->pCurDataObject = NULL;
2316 This->pCurDropTarget = NULL;
2317 This->iDragOverItem = 0;
2319 return S_OK;
2322 static const IDropTargetVtbl dtvt =
2324 ISVDropTarget_QueryInterface,
2325 ISVDropTarget_AddRef,
2326 ISVDropTarget_Release,
2327 ISVDropTarget_DragEnter,
2328 ISVDropTarget_DragOver,
2329 ISVDropTarget_DragLeave,
2330 ISVDropTarget_Drop
2333 /**********************************************************
2334 * ISVDropSource implementation
2337 static HRESULT WINAPI ISVDropSource_QueryInterface(
2338 IDropSource *iface,
2339 REFIID riid,
2340 LPVOID *ppvObj)
2342 IShellViewImpl *This = impl_from_IDropSource(iface);
2344 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2346 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2349 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2351 IShellViewImpl *This = impl_from_IDropSource(iface);
2353 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2355 return IShellFolder_AddRef((IShellFolder*)This);
2358 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2360 IShellViewImpl *This = impl_from_IDropSource(iface);
2362 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2364 return IShellFolder_Release((IShellFolder*)This);
2366 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2367 IDropSource *iface,
2368 BOOL fEscapePressed,
2369 DWORD grfKeyState)
2371 IShellViewImpl *This = impl_from_IDropSource(iface);
2372 TRACE("(%p)\n",This);
2374 if (fEscapePressed)
2375 return DRAGDROP_S_CANCEL;
2376 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2377 return DRAGDROP_S_DROP;
2378 else
2379 return NOERROR;
2382 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2383 IDropSource *iface,
2384 DWORD dwEffect)
2386 IShellViewImpl *This = impl_from_IDropSource(iface);
2387 TRACE("(%p)\n",This);
2389 return DRAGDROP_S_USEDEFAULTCURSORS;
2392 static const IDropSourceVtbl dsvt =
2394 ISVDropSource_QueryInterface,
2395 ISVDropSource_AddRef,
2396 ISVDropSource_Release,
2397 ISVDropSource_QueryContinueDrag,
2398 ISVDropSource_GiveFeedback
2400 /**********************************************************
2401 * ISVViewObject implementation
2404 static HRESULT WINAPI ISVViewObject_QueryInterface(
2405 IViewObject *iface,
2406 REFIID riid,
2407 LPVOID *ppvObj)
2409 IShellViewImpl *This = impl_from_IViewObject(iface);
2411 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2413 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2416 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2418 IShellViewImpl *This = impl_from_IViewObject(iface);
2420 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2422 return IShellFolder_AddRef((IShellFolder*)This);
2425 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2427 IShellViewImpl *This = impl_from_IViewObject(iface);
2429 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2431 return IShellFolder_Release((IShellFolder*)This);
2434 static HRESULT WINAPI ISVViewObject_Draw(
2435 IViewObject *iface,
2436 DWORD dwDrawAspect,
2437 LONG lindex,
2438 void* pvAspect,
2439 DVTARGETDEVICE* ptd,
2440 HDC hdcTargetDev,
2441 HDC hdcDraw,
2442 LPCRECTL lprcBounds,
2443 LPCRECTL lprcWBounds,
2444 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2445 ULONG_PTR dwContinue)
2448 IShellViewImpl *This = impl_from_IViewObject(iface);
2450 FIXME("Stub: This=%p\n",This);
2452 return E_NOTIMPL;
2454 static HRESULT WINAPI ISVViewObject_GetColorSet(
2455 IViewObject *iface,
2456 DWORD dwDrawAspect,
2457 LONG lindex,
2458 void *pvAspect,
2459 DVTARGETDEVICE* ptd,
2460 HDC hicTargetDevice,
2461 LOGPALETTE** ppColorSet)
2464 IShellViewImpl *This = impl_from_IViewObject(iface);
2466 FIXME("Stub: This=%p\n",This);
2468 return E_NOTIMPL;
2470 static HRESULT WINAPI ISVViewObject_Freeze(
2471 IViewObject *iface,
2472 DWORD dwDrawAspect,
2473 LONG lindex,
2474 void* pvAspect,
2475 DWORD* pdwFreeze)
2478 IShellViewImpl *This = impl_from_IViewObject(iface);
2480 FIXME("Stub: This=%p\n",This);
2482 return E_NOTIMPL;
2484 static HRESULT WINAPI ISVViewObject_Unfreeze(
2485 IViewObject *iface,
2486 DWORD dwFreeze)
2489 IShellViewImpl *This = impl_from_IViewObject(iface);
2491 FIXME("Stub: This=%p\n",This);
2493 return E_NOTIMPL;
2495 static HRESULT WINAPI ISVViewObject_SetAdvise(
2496 IViewObject *iface,
2497 DWORD aspects,
2498 DWORD advf,
2499 IAdviseSink* pAdvSink)
2502 IShellViewImpl *This = impl_from_IViewObject(iface);
2504 FIXME("partial stub: %p %08lx %08lx %p\n",
2505 This, aspects, advf, pAdvSink);
2507 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2508 This->pAdvSink = pAdvSink;
2509 This->dwAspects = aspects;
2510 This->dwAdvf = advf;
2512 return S_OK;
2515 static HRESULT WINAPI ISVViewObject_GetAdvise(
2516 IViewObject *iface,
2517 DWORD* pAspects,
2518 DWORD* pAdvf,
2519 IAdviseSink** ppAdvSink)
2522 IShellViewImpl *This = impl_from_IViewObject(iface);
2524 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2525 This, pAspects, pAdvf, ppAdvSink);
2527 if( ppAdvSink )
2529 IAdviseSink_AddRef( This->pAdvSink );
2530 *ppAdvSink = This->pAdvSink;
2532 if( pAspects )
2533 *pAspects = This->dwAspects;
2534 if( pAdvf )
2535 *pAdvf = This->dwAdvf;
2537 return S_OK;
2541 static const IViewObjectVtbl vovt =
2543 ISVViewObject_QueryInterface,
2544 ISVViewObject_AddRef,
2545 ISVViewObject_Release,
2546 ISVViewObject_Draw,
2547 ISVViewObject_GetColorSet,
2548 ISVViewObject_Freeze,
2549 ISVViewObject_Unfreeze,
2550 ISVViewObject_SetAdvise,
2551 ISVViewObject_GetAdvise