user: Use computed icon rectangle if SS_CENTERIMAGE style is set.
[wine/multimedia.git] / dlls / shell32 / shlview.c
blob1385e363f4374964a14b15412e7d5471993e1fad
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 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%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) {
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 ZeroMemory(&lvItem, sizeof(LVITEMA));
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 ZeroMemory(&lvItem, sizeof(lvItem)); /* create the listview item*/
556 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/
557 lvItem.iItem = ListView_GetItemCount(This->hWndList); /*add the item to the end of the list*/
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 ZeroMemory(&lvItem, sizeof(lvItem)); /* create the listview item*/
591 lvItem.mask = LVIF_PARAM; /* only the pidl */
592 lvItem.iItem = nItem;
593 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
595 SHFree((LPITEMIDLIST)lvItem.lParam);
596 lvItem.mask = LVIF_PARAM;
597 lvItem.iItem = nItem;
598 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */
599 SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem);
600 SendMessageA(This->hWndList, LVM_UPDATE, nItem, 0);
601 return TRUE; /* FIXME: better handling */
603 return FALSE;
605 /**********************************************************
606 * ShellView_FillList()
608 * - gets the objectlist from the shellfolder
609 * - sorts the list
610 * - fills the list into the view
613 static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg )
615 LPITEMIDLIST pidl = ptr;
616 IShellViewImpl *This = arg;
617 /* in a commdlg This works as a filemask*/
618 if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl);
619 SHFree(pidl);
620 return TRUE;
623 static HRESULT ShellView_FillList(IShellViewImpl * This)
625 LPENUMIDLIST pEnumIDList;
626 LPITEMIDLIST pidl;
627 DWORD dwFetched;
628 HRESULT hRes;
629 HDPA hdpa;
631 TRACE("%p\n",This);
633 /* get the itemlist from the shfolder*/
634 hRes = IShellFolder_EnumObjects(This->pSFParent,This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
635 if (hRes != S_OK)
637 if (hRes==S_FALSE)
638 return(NOERROR);
639 return(hRes);
642 /* create a pointer array */
643 hdpa = DPA_Create(16);
644 if (!hdpa)
646 return(E_OUTOFMEMORY);
649 /* copy the items into the array*/
650 while((S_OK == IEnumIDList_Next(pEnumIDList,1, &pidl, &dwFetched)) && dwFetched)
652 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
654 SHFree(pidl);
658 /* sort the array */
659 DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent);
661 /*turn the listview's redrawing off*/
662 SendMessageA(This->hWndList, WM_SETREDRAW, FALSE, 0);
664 DPA_DestroyCallback( hdpa, fill_list, This );
666 /*turn the listview's redrawing back on and force it to draw*/
667 SendMessageA(This->hWndList, WM_SETREDRAW, TRUE, 0);
669 IEnumIDList_Release(pEnumIDList); /* destroy the list*/
671 return S_OK;
674 /**********************************************************
675 * ShellView_OnCreate()
677 static LRESULT ShellView_OnCreate(IShellViewImpl * This)
679 IDropTarget* pdt;
680 SHChangeNotifyEntry ntreg;
681 IPersistFolder2 * ppf2 = NULL;
683 TRACE("%p\n",This);
685 if(ShellView_CreateList(This))
687 if(ShellView_InitList(This))
689 ShellView_FillList(This);
693 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown*)&This->lpVtbl, &IID_IDropTarget, (LPVOID*)&pdt)))
695 RegisterDragDrop(This->hWnd, pdt);
696 IDropTarget_Release(pdt);
699 /* register for receiving notifications */
700 IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
701 if (ppf2)
703 IPersistFolder2_GetCurFolder(ppf2, (LPITEMIDLIST*)&ntreg.pidl);
704 ntreg.fRecursive = TRUE;
705 This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
706 SHFree((LPITEMIDLIST)ntreg.pidl);
707 IPersistFolder2_Release(ppf2);
710 This->hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel");
712 return S_OK;
715 /**********************************************************
716 * #### Handling of the menus ####
719 /**********************************************************
720 * ShellView_BuildFileMenu()
722 static HMENU ShellView_BuildFileMenu(IShellViewImpl * This)
723 { CHAR szText[MAX_PATH];
724 MENUITEMINFOA mii;
725 int nTools,i;
726 HMENU hSubMenu;
728 TRACE("(%p)\n",This);
730 hSubMenu = CreatePopupMenu();
731 if(hSubMenu)
732 { /*get the number of items in our global array*/
733 for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
735 /*add the menu items*/
736 for(i = 0; i < nTools; i++)
738 LoadStringA(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
740 ZeroMemory(&mii, sizeof(mii));
741 mii.cbSize = sizeof(mii);
742 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
744 if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
746 mii.fType = MFT_STRING;
747 mii.fState = MFS_ENABLED;
748 mii.dwTypeData = szText;
749 mii.wID = Tools[i].idCommand;
751 else
753 mii.fType = MFT_SEPARATOR;
755 /* tack This item onto the end of the menu */
756 InsertMenuItemA(hSubMenu, (UINT)-1, TRUE, &mii);
759 TRACE("-- return (menu=%p)\n",hSubMenu);
760 return hSubMenu;
762 /**********************************************************
763 * ShellView_MergeFileMenu()
765 static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu)
766 { TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu);
768 if(hSubMenu)
769 { /*insert This item at the beginning of the menu */
770 _InsertMenuItem(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
771 _InsertMenuItem(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, "dummy45", MFS_ENABLED);
774 TRACE("--\n");
777 /**********************************************************
778 * ShellView_MergeViewMenu()
781 static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu)
783 TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
785 if(hSubMenu)
786 { /*add a separator at the correct position in the menu*/
787 MENUITEMINFOA mii;
788 static char view[] = "View";
790 _InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
792 ZeroMemory(&mii, sizeof(mii));
793 mii.cbSize = sizeof(mii);
794 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
795 mii.fType = MFT_STRING;
796 mii.dwTypeData = view;
797 mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
798 InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
802 /**********************************************************
803 * ShellView_GetSelections()
805 * - fills the this->apidl list with the selected objects
807 * RETURNS
808 * number of selected items
810 static UINT ShellView_GetSelections(IShellViewImpl * This)
812 LVITEMA lvItem;
813 UINT i = 0;
815 if (This->apidl)
817 SHFree(This->apidl);
820 This->cidl = ListView_GetSelectedCount(This->hWndList);
821 This->apidl = (LPITEMIDLIST*)SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
823 TRACE("selected=%i\n", This->cidl);
825 if(This->apidl)
827 TRACE("-- Items selected =%u\n", This->cidl);
829 ZeroMemory(&lvItem, sizeof(lvItem));
830 lvItem.mask = LVIF_STATE | LVIF_PARAM;
831 lvItem.stateMask = LVIS_SELECTED;
833 while(ListView_GetItemA(This->hWndList, &lvItem) && (i < This->cidl))
835 if(lvItem.state & LVIS_SELECTED)
837 This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
838 i++;
839 TRACE("-- selected Item found\n");
841 lvItem.iItem++;
844 return This->cidl;
848 /**********************************************************
849 * ShellView_OpenSelectedItems()
851 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
853 static UINT CF_IDLIST = 0;
854 HRESULT hr;
855 IDataObject* selection;
856 FORMATETC fetc;
857 STGMEDIUM stgm;
858 LPIDA pIDList;
859 LPCITEMIDLIST parent_pidl;
860 int i;
862 if (0 == ShellView_GetSelections(This))
864 return S_OK;
866 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
867 (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
868 0, (LPVOID *)&selection);
869 if (FAILED(hr))
870 return hr;
872 if (0 == CF_IDLIST)
874 CF_IDLIST = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
876 fetc.cfFormat = CF_IDLIST;
877 fetc.ptd = NULL;
878 fetc.dwAspect = DVASPECT_CONTENT;
879 fetc.lindex = -1;
880 fetc.tymed = TYMED_HGLOBAL;
882 hr = IDataObject_QueryGetData(selection, &fetc);
883 if (FAILED(hr))
884 return hr;
886 hr = IDataObject_GetData(selection, &fetc, &stgm);
887 if (FAILED(hr))
888 return hr;
890 pIDList = GlobalLock(stgm.u.hGlobal);
892 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
893 for (i = pIDList->cidl; i > 0; --i)
895 LPCITEMIDLIST pidl;
896 SFGAOF attribs;
898 pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
900 attribs = SFGAO_FOLDER;
901 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
903 if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
905 SHELLEXECUTEINFOA shexinfo;
907 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOA);
908 shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */
909 shexinfo.hwnd = NULL;
910 shexinfo.lpVerb = NULL;
911 shexinfo.lpFile = NULL;
912 shexinfo.lpParameters = NULL;
913 shexinfo.lpDirectory = NULL;
914 shexinfo.nShow = SW_NORMAL;
915 shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
917 ShellExecuteExA(&shexinfo); /* Discard error/success info */
919 ILFree((LPITEMIDLIST)shexinfo.lpIDList);
923 GlobalUnlock(stgm.u.hGlobal);
924 ReleaseStgMedium(&stgm);
926 IDataObject_Release(selection);
928 return S_OK;
931 /**********************************************************
932 * ShellView_DoContextMenu()
934 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
935 { UINT uCommand;
936 DWORD wFlags;
937 HMENU hMenu;
938 BOOL fExplore = FALSE;
939 HWND hwndTree = 0;
940 LPCONTEXTMENU pContextMenu = NULL;
941 IContextMenu2 *pCM = NULL;
942 CMINVOKECOMMANDINFO cmi;
944 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
946 /* look, what's selected and create a context menu object of it*/
947 if( ShellView_GetSelections(This) )
949 IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
950 (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
952 if(pContextMenu)
954 TRACE("-- pContextMenu\n");
955 hMenu = CreatePopupMenu();
957 if( hMenu )
959 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
960 if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
962 TRACE("-- explore mode\n");
963 fExplore = TRUE;
966 /* build the flags depending on what we can do with the selected item */
967 wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
969 /* let the ContextMenu merge its items in */
970 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
972 if (This->FolderSettings.fFlags & FWF_DESKTOP)
973 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
975 if( bDefault )
977 TRACE("-- get menu default command\n");
978 uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
980 else
982 TRACE("-- track popup\n");
983 uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
986 if(uCommand > 0)
988 TRACE("-- uCommand=%u\n", uCommand);
989 if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
991 TRACE("-- dlg: OnDefaultCommand\n");
992 if (OnDefaultCommand(This) != S_OK)
994 ShellView_OpenSelectedItems(This);
997 else
999 TRACE("-- explore -- invoke command\n");
1000 ZeroMemory(&cmi, sizeof(cmi));
1001 cmi.cbSize = sizeof(cmi);
1002 cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
1003 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1004 IContextMenu_InvokeCommand(pContextMenu, &cmi);
1007 DestroyMenu(hMenu);
1010 if (pContextMenu)
1011 IContextMenu_Release(pContextMenu);
1014 else /* background context menu */
1016 hMenu = CreatePopupMenu();
1018 pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
1019 IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1021 uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1022 DestroyMenu(hMenu);
1024 TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1026 ZeroMemory(&cmi, sizeof(cmi));
1027 cmi.cbSize = sizeof(cmi);
1028 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1029 cmi.hwnd = This->hWndParent;
1030 IContextMenu2_InvokeCommand(pCM, &cmi);
1032 IContextMenu2_Release(pCM);
1036 /**********************************************************
1037 * ##### message handling #####
1040 /**********************************************************
1041 * ShellView_OnSize()
1043 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1045 TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1047 /*resize the ListView to fit our window*/
1048 if(This->hWndList)
1050 MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1053 return S_OK;
1055 /**********************************************************
1056 * ShellView_OnDeactivate()
1058 * NOTES
1059 * internal
1061 static void ShellView_OnDeactivate(IShellViewImpl * This)
1063 TRACE("%p\n",This);
1065 if(This->uState != SVUIA_DEACTIVATE)
1067 if(This->hMenu)
1069 IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1070 IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1071 DestroyMenu(This->hMenu);
1072 This->hMenu = 0;
1075 This->uState = SVUIA_DEACTIVATE;
1079 /**********************************************************
1080 * ShellView_OnActivate()
1082 static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState)
1083 { OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} };
1084 MENUITEMINFOA mii;
1085 CHAR szText[MAX_PATH];
1087 TRACE("%p uState=%x\n",This,uState);
1089 /*don't do anything if the state isn't really changing */
1090 if(This->uState == uState)
1092 return S_OK;
1095 ShellView_OnDeactivate(This);
1097 /*only do This if we are active */
1098 if(uState != SVUIA_DEACTIVATE)
1100 /*merge the menus */
1101 This->hMenu = CreateMenu();
1103 if(This->hMenu)
1105 IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1106 TRACE("-- after fnInsertMenusSB\n");
1108 /*build the top level menu get the menu item's text*/
1109 strcpy(szText,"dummy 31");
1111 ZeroMemory(&mii, sizeof(mii));
1112 mii.cbSize = sizeof(mii);
1113 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1114 mii.fType = MFT_STRING;
1115 mii.fState = MFS_ENABLED;
1116 mii.dwTypeData = szText;
1117 mii.hSubMenu = ShellView_BuildFileMenu(This);
1119 /*insert our menu into the menu bar*/
1120 if(mii.hSubMenu)
1122 InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1125 /*get the view menu so we can merge with it*/
1126 ZeroMemory(&mii, sizeof(mii));
1127 mii.cbSize = sizeof(mii);
1128 mii.fMask = MIIM_SUBMENU;
1130 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1132 ShellView_MergeViewMenu(This, mii.hSubMenu);
1135 /*add the items that should only be added if we have the focus*/
1136 if(SVUIA_ACTIVATE_FOCUS == uState)
1138 /*get the file menu so we can merge with it */
1139 ZeroMemory(&mii, sizeof(mii));
1140 mii.cbSize = sizeof(mii);
1141 mii.fMask = MIIM_SUBMENU;
1143 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1145 ShellView_MergeFileMenu(This, mii.hSubMenu);
1148 TRACE("-- before fnSetMenuSB\n");
1149 IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1152 This->uState = uState;
1153 TRACE("--\n");
1154 return S_OK;
1157 /**********************************************************
1158 * ShellView_OnSetFocus()
1161 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1163 TRACE("%p\n",This);
1165 /* Tell the browser one of our windows has received the focus. This
1166 should always be done before merging menus (OnActivate merges the
1167 menus) if one of our windows has the focus.*/
1169 IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1170 ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1172 /* Set the focus to the listview */
1173 SetFocus(This->hWndList);
1175 /* Notify the ICommDlgBrowser interface */
1176 OnStateChange(This,CDBOSC_SETFOCUS);
1178 return 0;
1181 /**********************************************************
1182 * ShellView_OnKillFocus()
1184 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1186 TRACE("(%p) stub\n",This);
1188 ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1189 /* Notify the ICommDlgBrowser */
1190 OnStateChange(This,CDBOSC_KILLFOCUS);
1192 return 0;
1195 /**********************************************************
1196 * ShellView_OnCommand()
1198 * NOTES
1199 * the CmdID's are the ones from the context menu
1201 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1203 TRACE("(%p)->(0x%08lx 0x%08lx %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1205 switch(dwCmdID)
1207 case FCIDM_SHVIEW_SMALLICON:
1208 This->FolderSettings.ViewMode = FVM_SMALLICON;
1209 SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1210 CheckToolbar(This);
1211 break;
1213 case FCIDM_SHVIEW_BIGICON:
1214 This->FolderSettings.ViewMode = FVM_ICON;
1215 SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1216 CheckToolbar(This);
1217 break;
1219 case FCIDM_SHVIEW_LISTVIEW:
1220 This->FolderSettings.ViewMode = FVM_LIST;
1221 SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1222 CheckToolbar(This);
1223 break;
1225 case FCIDM_SHVIEW_REPORTVIEW:
1226 This->FolderSettings.ViewMode = FVM_DETAILS;
1227 SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1228 CheckToolbar(This);
1229 break;
1231 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1232 case 0x30:
1233 case 0x31:
1234 case 0x32:
1235 case 0x33:
1236 This->ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30);
1237 This->ListViewSortInfo.bIsAscending = TRUE;
1238 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1239 SendMessageA(This->hWndList, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1240 break;
1242 default:
1243 TRACE("-- COMMAND 0x%04lx unhandled\n", dwCmdID);
1245 return 0;
1248 /**********************************************************
1249 * ShellView_OnNotify()
1252 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1253 { LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1254 NMLVDISPINFOA *lpdi = (NMLVDISPINFOA *)lpnmh;
1255 LPITEMIDLIST pidl;
1257 TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1259 switch(lpnmh->code)
1261 case NM_SETFOCUS:
1262 TRACE("-- NM_SETFOCUS %p\n",This);
1263 ShellView_OnSetFocus(This);
1264 break;
1266 case NM_KILLFOCUS:
1267 TRACE("-- NM_KILLFOCUS %p\n",This);
1268 ShellView_OnDeactivate(This);
1269 /* Notify the ICommDlgBrowser interface */
1270 OnStateChange(This,CDBOSC_KILLFOCUS);
1271 break;
1273 case NM_CUSTOMDRAW:
1274 TRACE("-- NM_CUSTOMDRAW %p\n",This);
1275 return CDRF_DODEFAULT;
1277 case NM_RELEASEDCAPTURE:
1278 TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1279 break;
1281 case NM_CLICK:
1282 TRACE("-- NM_CLICK %p\n",This);
1283 break;
1285 case NM_RCLICK:
1286 TRACE("-- NM_RCLICK %p\n",This);
1287 break;
1289 case NM_DBLCLK:
1290 TRACE("-- NM_DBLCLK %p\n",This);
1291 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1292 break;
1294 case NM_RETURN:
1295 TRACE("-- NM_DBLCLK %p\n",This);
1296 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1297 break;
1299 case HDN_ENDTRACKA:
1300 TRACE("-- HDN_ENDTRACKA %p\n",This);
1301 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1302 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1303 break;
1305 case LVN_DELETEITEM:
1306 TRACE("-- LVN_DELETEITEM %p\n",This);
1307 SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/
1308 break;
1310 case LVN_DELETEALLITEMS:
1311 TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1312 return FALSE;
1314 case LVN_INSERTITEM:
1315 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1316 break;
1318 case LVN_ITEMACTIVATE:
1319 TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1320 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1321 break;
1323 case LVN_COLUMNCLICK:
1324 This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1325 if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1327 This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1329 else
1331 This->ListViewSortInfo.bIsAscending = TRUE;
1333 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1335 SendMessageA(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1336 break;
1338 case LVN_GETDISPINFOA:
1339 case LVN_GETDISPINFOW:
1340 TRACE("-- LVN_GETDISPINFO %p\n",This);
1341 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1343 if(lpdi->item.mask & LVIF_TEXT) /* text requested */
1345 if (This->pSF2Parent)
1347 SHELLDETAILS sd;
1348 IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1349 if (lpnmh->code == LVN_GETDISPINFOA)
1351 StrRetToStrNA( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1352 TRACE("-- text=%s\n",lpdi->item.pszText);
1354 else /* LVN_GETDISPINFOW */
1356 StrRetToStrNW( ((NMLVDISPINFOW *)lpdi)->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1357 TRACE("-- text=%s\n",debugstr_w((WCHAR*)(lpdi->item.pszText)));
1360 else
1362 FIXME("no SF2\n");
1365 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1367 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1369 break;
1371 case LVN_ITEMCHANGED:
1372 TRACE("-- LVN_ITEMCHANGED %p\n",This);
1373 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1374 break;
1376 case LVN_BEGINDRAG:
1377 case LVN_BEGINRDRAG:
1378 TRACE("-- LVN_BEGINDRAG\n");
1380 if (ShellView_GetSelections(This))
1382 IDataObject * pda;
1383 DWORD dwAttributes = SFGAO_CANLINK;
1384 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1386 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1388 IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource); /* own DropSource interface */
1390 if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1392 if (dwAttributes & SFGAO_CANLINK)
1394 dwEffect |= DROPEFFECT_LINK;
1398 if (pds)
1400 DWORD dwEffect;
1401 DoDragDrop(pda, pds, dwEffect, &dwEffect);
1403 IDataObject_Release(pda);
1406 break;
1408 case LVN_BEGINLABELEDITA:
1410 DWORD dwAttr = SFGAO_CANRENAME;
1411 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1413 TRACE("-- LVN_BEGINLABELEDITA %p\n",This);
1415 IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1416 if (SFGAO_CANRENAME & dwAttr)
1418 return FALSE;
1420 return TRUE;
1423 case LVN_ENDLABELEDITA:
1425 TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1426 if (lpdi->item.pszText)
1428 HRESULT hr;
1429 WCHAR wszNewName[MAX_PATH];
1430 LVITEMA lvItem;
1432 ZeroMemory(&lvItem, sizeof(LVITEMA));
1433 lvItem.iItem = lpdi->item.iItem;
1434 lvItem.mask = LVIF_PARAM;
1435 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
1437 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1438 if (!MultiByteToWideChar( CP_ACP, 0, lpdi->item.pszText, -1, wszNewName, MAX_PATH ))
1439 wszNewName[MAX_PATH-1] = 0;
1440 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, wszNewName, SHGDN_INFOLDER, &pidl);
1442 if(SUCCEEDED(hr) && pidl)
1444 lvItem.mask = LVIF_PARAM;
1445 lvItem.lParam = (LPARAM)pidl;
1446 SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem);
1447 return TRUE;
1450 return FALSE;
1453 case LVN_KEYDOWN:
1455 /* MSG msg;
1456 msg.hwnd = This->hWnd;
1457 msg.message = WM_KEYDOWN;
1458 msg.wParam = plvKeyDown->wVKey;
1459 msg.lParam = 0;
1460 msg.time = 0;
1461 msg.pt = 0;*/
1463 LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1465 /* initiate a rename of the selected file or directory */
1466 if(plvKeyDown->wVKey == VK_F2)
1468 /* see how many files are selected */
1469 int i = ListView_GetSelectedCount(This->hWndList);
1471 /* get selected item */
1472 if(i == 1)
1474 /* get selected item */
1475 i = ListView_GetNextItem(This->hWndList, -1,
1476 LVNI_SELECTED);
1478 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1479 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
1482 #if 0
1483 TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1484 #endif
1485 else if(plvKeyDown->wVKey == VK_DELETE)
1487 UINT i;
1488 int item_index;
1489 LVITEMA item;
1490 LPITEMIDLIST* pItems;
1491 ISFHelper *psfhlp;
1493 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1494 (LPVOID*)&psfhlp);
1496 if (psfhlp == NULL)
1497 break;
1499 if(!(i = ListView_GetSelectedCount(This->hWndList)))
1500 break;
1502 /* allocate memory for the pidl array */
1503 pItems = HeapAlloc(GetProcessHeap(), 0,
1504 sizeof(LPITEMIDLIST) * i);
1506 /* retrieve all selected items */
1507 i = 0;
1508 item_index = -1;
1509 while(ListView_GetSelectedCount(This->hWndList) > i)
1511 /* get selected item */
1512 item_index = ListView_GetNextItem(This->hWndList,
1513 item_index, LVNI_SELECTED);
1514 item.iItem = item_index;
1515 item.mask = LVIF_PARAM;
1516 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &item);
1518 /* get item pidl */
1519 pItems[i] = (LPITEMIDLIST)item.lParam;
1521 i++;
1524 /* perform the item deletion */
1525 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1527 /* free pidl array memory */
1528 HeapFree(GetProcessHeap(), 0, pItems);
1531 /* Initiate a refresh */
1532 else if(plvKeyDown->wVKey == VK_F5)
1534 IShellView_Refresh((IShellView*)This);
1537 else
1538 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1540 break;
1542 default:
1543 TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1544 break;
1546 return 0;
1549 /**********************************************************
1550 * ShellView_OnChange()
1553 static LRESULT ShellView_OnChange(IShellViewImpl * This, LPITEMIDLIST * Pidls, LONG wEventId)
1556 TRACE("(%p)(%p,%p,0x%08lx)\n", This, Pidls[0], Pidls[1], wEventId);
1557 switch(wEventId)
1559 case SHCNE_MKDIR:
1560 case SHCNE_CREATE:
1561 LV_AddItem(This, Pidls[0]);
1562 break;
1563 case SHCNE_RMDIR:
1564 case SHCNE_DELETE:
1565 LV_DeleteItem(This, Pidls[0]);
1566 break;
1567 case SHCNE_RENAMEFOLDER:
1568 case SHCNE_RENAMEITEM:
1569 LV_RenameItem(This, Pidls[0], Pidls[1]);
1570 break;
1571 case SHCNE_UPDATEITEM:
1572 break;
1574 return TRUE;
1576 /**********************************************************
1577 * ShellView_WndProc
1580 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1582 IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1583 LPCREATESTRUCTA lpcs;
1585 TRACE("(hwnd=%p msg=%x wparm=%x lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1587 switch (uMessage)
1589 case WM_NCCREATE:
1590 lpcs = (LPCREATESTRUCTA)lParam;
1591 pThis = (IShellViewImpl*)(lpcs->lpCreateParams);
1592 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1593 pThis->hWnd = hWnd; /*set the window handle*/
1594 break;
1596 case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1597 case WM_SETFOCUS: return ShellView_OnSetFocus(pThis);
1598 case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis);
1599 case WM_CREATE: return ShellView_OnCreate(pThis);
1600 case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1601 case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1602 case WM_COMMAND: return ShellView_OnCommand(pThis,
1603 GET_WM_COMMAND_ID(wParam, lParam),
1604 GET_WM_COMMAND_CMD(wParam, lParam),
1605 GET_WM_COMMAND_HWND(wParam, lParam));
1606 case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (LPITEMIDLIST*)wParam, (LONG)lParam);
1608 case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1609 return 0;
1611 case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
1612 break;
1614 case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0);
1616 case WM_DESTROY:
1617 RevokeDragDrop(pThis->hWnd);
1618 SHChangeNotifyDeregister(pThis->hNotify);
1619 break;
1621 case WM_ERASEBKGND:
1622 if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1623 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1624 return 1;
1625 break;
1628 return DefWindowProcA (hWnd, uMessage, wParam, lParam);
1630 /**********************************************************
1633 * The INTERFACE of the IShellView object
1636 **********************************************************
1637 * IShellView_QueryInterface
1639 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj)
1641 IShellViewImpl *This = (IShellViewImpl *)iface;
1643 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1645 *ppvObj = NULL;
1647 if(IsEqualIID(riid, &IID_IUnknown))
1649 *ppvObj = This;
1651 else if(IsEqualIID(riid, &IID_IShellView))
1653 *ppvObj = (IShellView*)This;
1655 else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1657 *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget);
1659 else if(IsEqualIID(riid, &IID_IDropTarget))
1661 *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
1663 else if(IsEqualIID(riid, &IID_IDropSource))
1665 *ppvObj = (IDropSource*)&(This->lpvtblDropSource);
1667 else if(IsEqualIID(riid, &IID_IViewObject))
1669 *ppvObj = (IViewObject*)&(This->lpvtblViewObject);
1672 if(*ppvObj)
1674 IUnknown_AddRef( (IUnknown*)*ppvObj );
1675 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1676 return S_OK;
1678 TRACE("-- Interface: E_NOINTERFACE\n");
1679 return E_NOINTERFACE;
1682 /**********************************************************
1683 * IShellView_AddRef
1685 static ULONG WINAPI IShellView_fnAddRef(IShellView * iface)
1687 IShellViewImpl *This = (IShellViewImpl *)iface;
1688 ULONG refCount = InterlockedIncrement(&This->ref);
1690 TRACE("(%p)->(count=%lu)\n", This, refCount - 1);
1692 return refCount;
1694 /**********************************************************
1695 * IShellView_Release
1697 static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
1699 IShellViewImpl *This = (IShellViewImpl *)iface;
1700 ULONG refCount = InterlockedDecrement(&This->ref);
1702 TRACE("(%p)->(count=%li)\n", This, refCount + 1);
1704 if (!refCount)
1706 TRACE(" destroying IShellView(%p)\n",This);
1708 DestroyWindow(This->hWndList);
1710 if(This->pSFParent)
1711 IShellFolder_Release(This->pSFParent);
1713 if(This->pSF2Parent)
1714 IShellFolder2_Release(This->pSF2Parent);
1716 if(This->apidl)
1717 SHFree(This->apidl);
1719 if(This->pAdvSink)
1720 IAdviseSink_Release(This->pAdvSink);
1722 HeapFree(GetProcessHeap(),0,This);
1724 return refCount;
1727 /**********************************************************
1728 * ShellView_GetWindow
1730 static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd)
1732 IShellViewImpl *This = (IShellViewImpl *)iface;
1734 TRACE("(%p)\n",This);
1736 *phWnd = This->hWnd;
1738 return S_OK;
1741 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode)
1743 IShellViewImpl *This = (IShellViewImpl *)iface;
1745 FIXME("(%p) stub\n",This);
1747 return E_NOTIMPL;
1750 /**********************************************************
1751 * IShellView_TranslateAccelerator
1753 * FIXME:
1754 * use the accel functions
1756 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg)
1758 #if 0
1759 IShellViewImpl *This = (IShellViewImpl *)iface;
1761 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%lx wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1762 #endif
1764 if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1766 TRACE("-- key=0x04%x\n",lpmsg->wParam) ;
1768 return S_FALSE; /* not handled */
1771 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable)
1773 IShellViewImpl *This = (IShellViewImpl *)iface;
1775 FIXME("(%p) stub\n",This);
1777 return E_NOTIMPL;
1780 static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState)
1782 IShellViewImpl *This = (IShellViewImpl *)iface;
1785 CHAR szName[MAX_PATH];
1787 LRESULT lResult;
1788 int nPartArray[1] = {-1};
1790 TRACE("(%p)->(state=%x) stub\n",This, uState);
1792 /*don't do anything if the state isn't really changing*/
1793 if(This->uState == uState)
1795 return S_OK;
1798 /*OnActivate handles the menu merging and internal state*/
1799 ShellView_OnActivate(This, uState);
1801 /*only do This if we are active*/
1802 if(uState != SVUIA_DEACTIVATE)
1806 GetFolderPath is not a method of IShellFolder
1807 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1809 /* set the number of parts */
1810 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1811 (LPARAM)nPartArray, &lResult);
1813 /* set the text for the parts */
1815 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1816 0, (LPARAM)szName, &lResult);
1820 return S_OK;
1823 static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface)
1825 IShellViewImpl *This = (IShellViewImpl *)iface;
1827 TRACE("(%p)\n",This);
1829 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
1830 ShellView_FillList(This);
1832 return S_OK;
1835 static HRESULT WINAPI IShellView_fnCreateViewWindow(
1836 IShellView * iface,
1837 IShellView *lpPrevView,
1838 LPCFOLDERSETTINGS lpfs,
1839 IShellBrowser * psb,
1840 RECT * prcView,
1841 HWND *phWnd)
1843 IShellViewImpl *This = (IShellViewImpl *)iface;
1845 WNDCLASSA wc;
1846 *phWnd = 0;
1849 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd);
1850 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);
1852 /*set up the member variables*/
1853 This->pShellBrowser = psb;
1854 This->FolderSettings = *lpfs;
1856 /*get our parent window*/
1857 IShellBrowser_AddRef(This->pShellBrowser);
1858 IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
1860 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1861 This->pCommDlgBrowser=NULL;
1862 if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser,
1863 (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser)))
1865 TRACE("-- CommDlgBrowser\n");
1868 /*if our window class has not been registered, then do so*/
1869 if(!GetClassInfoA(shell32_hInstance, SV_CLASS_NAME, &wc))
1871 ZeroMemory(&wc, sizeof(wc));
1872 wc.style = CS_HREDRAW | CS_VREDRAW;
1873 wc.lpfnWndProc = ShellView_WndProc;
1874 wc.cbClsExtra = 0;
1875 wc.cbWndExtra = 0;
1876 wc.hInstance = shell32_hInstance;
1877 wc.hIcon = 0;
1878 wc.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
1879 wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
1880 wc.lpszMenuName = NULL;
1881 wc.lpszClassName = SV_CLASS_NAME;
1883 if(!RegisterClassA(&wc))
1884 return E_FAIL;
1887 *phWnd = CreateWindowExA(0,
1888 SV_CLASS_NAME,
1889 NULL,
1890 WS_CHILD | WS_TABSTOP,
1891 prcView->left,
1892 prcView->top,
1893 prcView->right - prcView->left,
1894 prcView->bottom - prcView->top,
1895 This->hWndParent,
1897 shell32_hInstance,
1898 (LPVOID)This);
1900 CheckToolbar(This);
1902 if(!*phWnd) return E_FAIL;
1904 SetWindowPos(*phWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
1905 UpdateWindow(*phWnd);
1907 return S_OK;
1910 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
1912 IShellViewImpl *This = (IShellViewImpl *)iface;
1914 TRACE("(%p)\n",This);
1916 /*Make absolutely sure all our UI is cleaned up.*/
1917 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1919 if(This->hMenu)
1921 DestroyMenu(This->hMenu);
1924 DestroyWindow(This->hWnd);
1925 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1926 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1929 return S_OK;
1932 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs)
1934 IShellViewImpl *This = (IShellViewImpl *)iface;
1936 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1937 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1939 if (!lpfs) return E_INVALIDARG;
1941 *lpfs = This->FolderSettings;
1942 return NOERROR;
1945 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1947 IShellViewImpl *This = (IShellViewImpl *)iface;
1949 FIXME("(%p) stub\n",This);
1951 return E_NOTIMPL;
1954 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface)
1956 IShellViewImpl *This = (IShellViewImpl *)iface;
1958 FIXME("(%p) stub\n",This);
1960 return S_OK;
1963 static HRESULT WINAPI IShellView_fnSelectItem(
1964 IShellView * iface,
1965 LPCITEMIDLIST pidl,
1966 UINT uFlags)
1968 IShellViewImpl *This = (IShellViewImpl *)iface;
1969 int i;
1971 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
1973 i = LV_FindItemByPidl(This, pidl);
1975 if (i != -1)
1977 LVITEMA lvItem;
1979 if(uFlags & SVSI_ENSUREVISIBLE)
1980 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1982 ZeroMemory(&lvItem, sizeof(LVITEMA));
1983 lvItem.mask = LVIF_STATE;
1984 lvItem.iItem = 0;
1986 while(SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem))
1988 if (lvItem.iItem == i)
1990 if (uFlags & SVSI_SELECT)
1991 lvItem.state |= LVIS_SELECTED;
1992 else
1993 lvItem.state &= ~LVIS_SELECTED;
1995 if(uFlags & SVSI_FOCUSED)
1996 lvItem.state &= ~LVIS_FOCUSED;
1998 else
2000 if (uFlags & SVSI_DESELECTOTHERS)
2001 lvItem.state &= ~LVIS_SELECTED;
2003 SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem);
2004 lvItem.iItem++;
2008 if(uFlags & SVSI_EDIT)
2009 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
2012 return S_OK;
2015 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
2017 IShellViewImpl *This = (IShellViewImpl *)iface;
2019 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2021 *ppvOut = NULL;
2023 switch(uItem)
2025 case SVGIO_BACKGROUND:
2026 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2027 break;
2029 case SVGIO_SELECTION:
2030 ShellView_GetSelections(This);
2031 IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2032 break;
2034 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2036 if(!*ppvOut) return E_OUTOFMEMORY;
2038 return S_OK;
2041 static const IShellViewVtbl svvt =
2043 IShellView_fnQueryInterface,
2044 IShellView_fnAddRef,
2045 IShellView_fnRelease,
2046 IShellView_fnGetWindow,
2047 IShellView_fnContextSensitiveHelp,
2048 IShellView_fnTranslateAccelerator,
2049 IShellView_fnEnableModeless,
2050 IShellView_fnUIActivate,
2051 IShellView_fnRefresh,
2052 IShellView_fnCreateViewWindow,
2053 IShellView_fnDestroyViewWindow,
2054 IShellView_fnGetCurrentInfo,
2055 IShellView_fnAddPropertySheetPages,
2056 IShellView_fnSaveViewState,
2057 IShellView_fnSelectItem,
2058 IShellView_fnGetItemObject
2062 /**********************************************************
2063 * ISVOleCmdTarget_QueryInterface (IUnknown)
2065 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2066 IOleCommandTarget * iface,
2067 REFIID iid,
2068 LPVOID* ppvObj)
2070 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2072 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2075 /**********************************************************
2076 * ISVOleCmdTarget_AddRef (IUnknown)
2078 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2079 IOleCommandTarget * iface)
2081 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2083 return IShellFolder_AddRef((IShellFolder*)This);
2086 /**********************************************************
2087 * ISVOleCmdTarget_Release (IUnknown)
2089 static ULONG WINAPI ISVOleCmdTarget_Release(
2090 IOleCommandTarget * iface)
2092 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2094 return IShellFolder_Release((IShellFolder*)This);
2097 /**********************************************************
2098 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2100 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2101 IOleCommandTarget *iface,
2102 const GUID* pguidCmdGroup,
2103 ULONG cCmds,
2104 OLECMD * prgCmds,
2105 OLECMDTEXT* pCmdText)
2107 UINT i;
2108 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2110 FIXME("(%p)->(%p(%s) 0x%08lx %p %p\n",
2111 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2113 if (!prgCmds)
2114 return E_POINTER;
2115 for (i = 0; i < cCmds; i++)
2117 FIXME("\tprgCmds[%d].cmdID = %ld\n", i, prgCmds[i].cmdID);
2118 prgCmds[i].cmdf = 0;
2120 return OLECMDERR_E_UNKNOWNGROUP;
2123 /**********************************************************
2124 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2126 * nCmdID is the OLECMDID_* enumeration
2128 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2129 IOleCommandTarget *iface,
2130 const GUID* pguidCmdGroup,
2131 DWORD nCmdID,
2132 DWORD nCmdexecopt,
2133 VARIANT* pvaIn,
2134 VARIANT* pvaOut)
2136 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2138 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08lx Opt:0x%08lx %p %p)\n",
2139 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2141 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2142 (nCmdID == 0x29) &&
2143 (nCmdexecopt == 4) && pvaOut)
2144 return S_OK;
2145 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2146 (nCmdID == 9) &&
2147 (nCmdexecopt == 0))
2148 return 1;
2150 return OLECMDERR_E_UNKNOWNGROUP;
2153 static const IOleCommandTargetVtbl ctvt =
2155 ISVOleCmdTarget_QueryInterface,
2156 ISVOleCmdTarget_AddRef,
2157 ISVOleCmdTarget_Release,
2158 ISVOleCmdTarget_QueryStatus,
2159 ISVOleCmdTarget_Exec
2162 /**********************************************************
2163 * ISVDropTarget implementation
2166 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2167 IDropTarget *iface,
2168 REFIID riid,
2169 LPVOID *ppvObj)
2171 IShellViewImpl *This = impl_from_IDropTarget(iface);
2173 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2175 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2178 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2180 IShellViewImpl *This = impl_from_IDropTarget(iface);
2182 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2184 return IShellFolder_AddRef((IShellFolder*)This);
2187 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2189 IShellViewImpl *This = impl_from_IDropTarget(iface);
2191 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2193 return IShellFolder_Release((IShellFolder*)This);
2196 /******************************************************************************
2197 * drag_notify_subitem [Internal]
2199 * Figure out the shellfolder object, which is currently under the mouse cursor
2200 * and notify it via the IDropTarget interface.
2203 #define SCROLLAREAWIDTH 20
2205 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2206 DWORD *pdwEffect)
2208 LVHITTESTINFO htinfo;
2209 LVITEMA lvItem;
2210 LONG lResult;
2211 HRESULT hr;
2212 RECT clientRect;
2214 /* Map from global to client coordinates and query the index of the listview-item, which is
2215 * currently under the mouse cursor. */
2216 htinfo.pt.x = pt.x;
2217 htinfo.pt.y = pt.y;
2218 htinfo.flags = LVHT_ONITEM;
2219 ScreenToClient(This->hWndList, &htinfo.pt);
2220 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2222 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2223 GetClientRect(This->hWndList, &clientRect);
2224 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2225 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2226 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2228 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2229 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2230 if (htinfo.pt.x < SCROLLAREAWIDTH)
2231 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2232 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2233 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2234 if (htinfo.pt.y < SCROLLAREAWIDTH)
2235 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2236 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2237 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2239 } else {
2240 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2242 This->ptLastMousePos = htinfo.pt;
2244 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2245 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2246 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2248 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2249 if (This->pCurDropTarget) {
2250 IDropTarget_DragLeave(This->pCurDropTarget);
2251 IDropTarget_Release(This->pCurDropTarget);
2252 This->pCurDropTarget = NULL;
2255 This->iDragOverItem = lResult;
2256 if (lResult == -1) {
2257 /* We are not above one of the listview's subitems. Bind to the parent folder's
2258 * DropTarget interface. */
2259 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2260 (LPVOID*)&This->pCurDropTarget);
2261 } else {
2262 /* Query the relative PIDL of the shellfolder object represented by the currently
2263 * dragged over listview-item ... */
2264 ZeroMemory(&lvItem, sizeof(lvItem));
2265 lvItem.mask = LVIF_PARAM;
2266 lvItem.iItem = lResult;
2267 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
2269 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2270 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2271 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2274 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2275 if (FAILED(hr))
2276 return hr;
2278 /* Notify the item just entered via DragEnter. */
2279 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2282 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2283 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2285 IShellViewImpl *This = impl_from_IDropTarget(iface);
2287 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2288 This->pCurDataObject = pDataObject;
2289 IDataObject_AddRef(pDataObject);
2291 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2294 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2295 DWORD *pdwEffect)
2297 IShellViewImpl *This = impl_from_IDropTarget(iface);
2298 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2301 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2302 IShellViewImpl *This = impl_from_IDropTarget(iface);
2304 IDropTarget_DragLeave(This->pCurDropTarget);
2306 IDropTarget_Release(This->pCurDropTarget);
2307 IDataObject_Release(This->pCurDataObject);
2308 This->pCurDataObject = NULL;
2309 This->pCurDropTarget = NULL;
2310 This->iDragOverItem = 0;
2312 return S_OK;
2315 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2316 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2318 IShellViewImpl *This = impl_from_IDropTarget(iface);
2320 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2322 IDropTarget_Release(This->pCurDropTarget);
2323 IDataObject_Release(This->pCurDataObject);
2324 This->pCurDataObject = NULL;
2325 This->pCurDropTarget = NULL;
2326 This->iDragOverItem = 0;
2328 return S_OK;
2331 static const IDropTargetVtbl dtvt =
2333 ISVDropTarget_QueryInterface,
2334 ISVDropTarget_AddRef,
2335 ISVDropTarget_Release,
2336 ISVDropTarget_DragEnter,
2337 ISVDropTarget_DragOver,
2338 ISVDropTarget_DragLeave,
2339 ISVDropTarget_Drop
2342 /**********************************************************
2343 * ISVDropSource implementation
2346 static HRESULT WINAPI ISVDropSource_QueryInterface(
2347 IDropSource *iface,
2348 REFIID riid,
2349 LPVOID *ppvObj)
2351 IShellViewImpl *This = impl_from_IDropSource(iface);
2353 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2355 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2358 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2360 IShellViewImpl *This = impl_from_IDropSource(iface);
2362 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2364 return IShellFolder_AddRef((IShellFolder*)This);
2367 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2369 IShellViewImpl *This = impl_from_IDropSource(iface);
2371 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2373 return IShellFolder_Release((IShellFolder*)This);
2375 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2376 IDropSource *iface,
2377 BOOL fEscapePressed,
2378 DWORD grfKeyState)
2380 IShellViewImpl *This = impl_from_IDropSource(iface);
2381 TRACE("(%p)\n",This);
2383 if (fEscapePressed)
2384 return DRAGDROP_S_CANCEL;
2385 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2386 return DRAGDROP_S_DROP;
2387 else
2388 return NOERROR;
2391 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2392 IDropSource *iface,
2393 DWORD dwEffect)
2395 IShellViewImpl *This = impl_from_IDropSource(iface);
2396 TRACE("(%p)\n",This);
2398 return DRAGDROP_S_USEDEFAULTCURSORS;
2401 static const IDropSourceVtbl dsvt =
2403 ISVDropSource_QueryInterface,
2404 ISVDropSource_AddRef,
2405 ISVDropSource_Release,
2406 ISVDropSource_QueryContinueDrag,
2407 ISVDropSource_GiveFeedback
2409 /**********************************************************
2410 * ISVViewObject implementation
2413 static HRESULT WINAPI ISVViewObject_QueryInterface(
2414 IViewObject *iface,
2415 REFIID riid,
2416 LPVOID *ppvObj)
2418 IShellViewImpl *This = impl_from_IViewObject(iface);
2420 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2422 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2425 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2427 IShellViewImpl *This = impl_from_IViewObject(iface);
2429 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2431 return IShellFolder_AddRef((IShellFolder*)This);
2434 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2436 IShellViewImpl *This = impl_from_IViewObject(iface);
2438 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2440 return IShellFolder_Release((IShellFolder*)This);
2443 static HRESULT WINAPI ISVViewObject_Draw(
2444 IViewObject *iface,
2445 DWORD dwDrawAspect,
2446 LONG lindex,
2447 void* pvAspect,
2448 DVTARGETDEVICE* ptd,
2449 HDC hdcTargetDev,
2450 HDC hdcDraw,
2451 LPCRECTL lprcBounds,
2452 LPCRECTL lprcWBounds,
2453 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2454 ULONG_PTR dwContinue)
2457 IShellViewImpl *This = impl_from_IViewObject(iface);
2459 FIXME("Stub: This=%p\n",This);
2461 return E_NOTIMPL;
2463 static HRESULT WINAPI ISVViewObject_GetColorSet(
2464 IViewObject *iface,
2465 DWORD dwDrawAspect,
2466 LONG lindex,
2467 void *pvAspect,
2468 DVTARGETDEVICE* ptd,
2469 HDC hicTargetDevice,
2470 LOGPALETTE** ppColorSet)
2473 IShellViewImpl *This = impl_from_IViewObject(iface);
2475 FIXME("Stub: This=%p\n",This);
2477 return E_NOTIMPL;
2479 static HRESULT WINAPI ISVViewObject_Freeze(
2480 IViewObject *iface,
2481 DWORD dwDrawAspect,
2482 LONG lindex,
2483 void* pvAspect,
2484 DWORD* pdwFreeze)
2487 IShellViewImpl *This = impl_from_IViewObject(iface);
2489 FIXME("Stub: This=%p\n",This);
2491 return E_NOTIMPL;
2493 static HRESULT WINAPI ISVViewObject_Unfreeze(
2494 IViewObject *iface,
2495 DWORD dwFreeze)
2498 IShellViewImpl *This = impl_from_IViewObject(iface);
2500 FIXME("Stub: This=%p\n",This);
2502 return E_NOTIMPL;
2504 static HRESULT WINAPI ISVViewObject_SetAdvise(
2505 IViewObject *iface,
2506 DWORD aspects,
2507 DWORD advf,
2508 IAdviseSink* pAdvSink)
2511 IShellViewImpl *This = impl_from_IViewObject(iface);
2513 FIXME("partial stub: %p %08lx %08lx %p\n",
2514 This, aspects, advf, pAdvSink);
2516 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2517 This->pAdvSink = pAdvSink;
2518 This->dwAspects = aspects;
2519 This->dwAdvf = advf;
2521 return S_OK;
2524 static HRESULT WINAPI ISVViewObject_GetAdvise(
2525 IViewObject *iface,
2526 DWORD* pAspects,
2527 DWORD* pAdvf,
2528 IAdviseSink** ppAdvSink)
2531 IShellViewImpl *This = impl_from_IViewObject(iface);
2533 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2534 This, pAspects, pAdvf, ppAdvSink);
2536 if( ppAdvSink )
2538 IAdviseSink_AddRef( This->pAdvSink );
2539 *ppAdvSink = This->pAdvSink;
2541 if( pAspects )
2542 *pAspects = This->dwAspects;
2543 if( pAdvf )
2544 *pAdvf = This->dwAdvf;
2546 return S_OK;
2550 static const IViewObjectVtbl vovt =
2552 ISVViewObject_QueryInterface,
2553 ISVViewObject_AddRef,
2554 ISVViewObject_Release,
2555 ISVViewObject_Draw,
2556 ISVViewObject_GetColorSet,
2557 ISVViewObject_Freeze,
2558 ISVViewObject_Unfreeze,
2559 ISVViewObject_SetAdvise,
2560 ISVViewObject_GetAdvise