winecfg: Update Norwegian resource.
[wine/wine-kai.git] / dlls / shell32 / shlview.c
blob390fdc9f1444873c485619e8f23cea60507732bc
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 static const WCHAR SV_CLASS_NAME[] = {'S','H','E','L','L','D','L','L','_','D','e','f','V','i','e','w',0};
73 typedef struct
74 { BOOL bIsAscending;
75 INT nHeaderID;
76 INT nLastHeaderID;
77 }LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;
79 typedef struct
81 const IShellViewVtbl* lpVtbl;
82 LONG ref;
83 const IOleCommandTargetVtbl* lpvtblOleCommandTarget;
84 const IDropTargetVtbl* lpvtblDropTarget;
85 const IDropSourceVtbl* lpvtblDropSource;
86 const IViewObjectVtbl* lpvtblViewObject;
87 IShellFolder* pSFParent;
88 IShellFolder2* pSF2Parent;
89 IShellBrowser* pShellBrowser;
90 ICommDlgBrowser* pCommDlgBrowser;
91 HWND hWnd; /* SHELLDLL_DefView */
92 HWND hWndList; /* ListView control */
93 HWND hWndParent;
94 FOLDERSETTINGS FolderSettings;
95 HMENU hMenu;
96 UINT uState;
97 UINT cidl;
98 LPITEMIDLIST *apidl;
99 LISTVIEW_SORT_INFO ListViewSortInfo;
100 ULONG hNotify; /* change notification handle */
101 HANDLE hAccel;
102 DWORD dwAspects;
103 DWORD dwAdvf;
104 IAdviseSink *pAdvSink;
105 IDropTarget* pCurDropTarget; /* The sub-item, which is currently dragged over */
106 IDataObject* pCurDataObject; /* The dragged data-object */
107 LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */
108 UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
109 POINT ptLastMousePos; /* Mouse position at last DragOver call */
110 } IShellViewImpl;
112 static const IShellViewVtbl svvt;
113 static const IOleCommandTargetVtbl ctvt;
114 static const IDropTargetVtbl dtvt;
115 static const IDropSourceVtbl dsvt;
116 static const IViewObjectVtbl vovt;
119 static inline IShellViewImpl *impl_from_IOleCommandTarget( IOleCommandTarget *iface )
121 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblOleCommandTarget));
124 static inline IShellViewImpl *impl_from_IDropTarget( IDropTarget *iface )
126 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropTarget));
129 static inline IShellViewImpl *impl_from_IDropSource( IDropSource *iface )
131 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropSource));
134 static inline IShellViewImpl *impl_from_IViewObject( IViewObject *iface )
136 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblViewObject));
139 /* ListView Header ID's */
140 #define LISTVIEW_COLUMN_NAME 0
141 #define LISTVIEW_COLUMN_SIZE 1
142 #define LISTVIEW_COLUMN_TYPE 2
143 #define LISTVIEW_COLUMN_TIME 3
144 #define LISTVIEW_COLUMN_ATTRIB 4
146 /*menu items */
147 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
148 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
149 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
151 #define ID_LISTVIEW 1
153 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
155 /*windowsx.h */
156 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
157 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
158 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
161 Items merged into the toolbar and the filemenu
163 typedef struct
164 { int idCommand;
165 int iImage;
166 int idButtonString;
167 int idMenuString;
168 BYTE bState;
169 BYTE bStyle;
170 } MYTOOLINFO, *LPMYTOOLINFO;
172 static const MYTOOLINFO Tools[] =
174 { FCIDM_SHVIEW_BIGICON, 0, 0, IDS_VIEW_LARGE, TBSTATE_ENABLED, BTNS_BUTTON },
175 { FCIDM_SHVIEW_SMALLICON, 0, 0, IDS_VIEW_SMALL, TBSTATE_ENABLED, BTNS_BUTTON },
176 { FCIDM_SHVIEW_LISTVIEW, 0, 0, IDS_VIEW_LIST, TBSTATE_ENABLED, BTNS_BUTTON },
177 { FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON },
178 { -1, 0, 0, 0, 0, 0}
181 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
183 /**********************************************************
184 * IShellView_Constructor
186 IShellView * IShellView_Constructor( IShellFolder * pFolder)
187 { IShellViewImpl * sv;
188 sv=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellViewImpl));
189 sv->ref=1;
190 sv->lpVtbl=&svvt;
191 sv->lpvtblOleCommandTarget=&ctvt;
192 sv->lpvtblDropTarget=&dtvt;
193 sv->lpvtblDropSource=&dsvt;
194 sv->lpvtblViewObject=&vovt;
196 sv->pSFParent = pFolder;
197 if(pFolder) IShellFolder_AddRef(pFolder);
198 IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent);
200 sv->pCurDropTarget = NULL;
201 sv->pCurDataObject = NULL;
202 sv->iDragOverItem = 0;
203 sv->cScrollDelay = 0;
204 sv->ptLastMousePos.x = 0;
205 sv->ptLastMousePos.y = 0;
207 TRACE("(%p)->(%p)\n",sv, pFolder);
208 return (IShellView *) sv;
211 /**********************************************************
213 * ##### helperfunctions for communication with ICommDlgBrowser #####
215 static BOOL IsInCommDlg(IShellViewImpl * This)
216 { return(This->pCommDlgBrowser != NULL);
219 static HRESULT IncludeObject(IShellViewImpl * This, LPCITEMIDLIST pidl)
221 HRESULT ret = S_OK;
223 if ( IsInCommDlg(This) )
225 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
226 ret = ICommDlgBrowser_IncludeObject(This->pCommDlgBrowser, (IShellView*)This, pidl);
227 TRACE("--0x%08x\n", ret);
229 return ret;
232 static HRESULT OnDefaultCommand(IShellViewImpl * This)
234 HRESULT ret = S_FALSE;
236 if (IsInCommDlg(This))
238 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
239 ret = ICommDlgBrowser_OnDefaultCommand(This->pCommDlgBrowser, (IShellView*)This);
240 TRACE("-- returns %08x\n", ret);
242 return ret;
245 static HRESULT OnStateChange(IShellViewImpl * This, UINT uFlags)
247 HRESULT ret = S_FALSE;
249 if (IsInCommDlg(This))
251 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
252 ret = ICommDlgBrowser_OnStateChange(This->pCommDlgBrowser, (IShellView*)This, uFlags);
253 TRACE("--\n");
255 return ret;
257 /**********************************************************
258 * set the toolbar of the filedialog buttons
260 * - activates the buttons from the shellbrowser according to
261 * the view state
263 static void CheckToolbar(IShellViewImpl * This)
265 LRESULT result;
267 TRACE("\n");
269 if (IsInCommDlg(This))
271 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
272 FCIDM_TB_SMALLICON, (This->FolderSettings.ViewMode==FVM_LIST)? TRUE : FALSE, &result);
273 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
274 FCIDM_TB_REPORTVIEW, (This->FolderSettings.ViewMode==FVM_DETAILS)? TRUE : FALSE, &result);
275 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
276 FCIDM_TB_SMALLICON, TRUE, &result);
277 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
278 FCIDM_TB_REPORTVIEW, TRUE, &result);
282 /**********************************************************
284 * ##### helperfunctions for initializing the view #####
286 /**********************************************************
287 * change the style of the listview control
289 static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove)
291 DWORD tmpstyle;
293 TRACE("(%p)\n", This);
295 tmpstyle = GetWindowLongW(This->hWndList, GWL_STYLE);
296 SetWindowLongW(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
299 /**********************************************************
300 * ShellView_CreateList()
302 * - creates the list view window
304 static BOOL ShellView_CreateList (IShellViewImpl * This)
305 { DWORD dwStyle, dwExStyle;
307 TRACE("%p\n",This);
309 dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
310 LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT | LVS_AUTOARRANGE;
311 dwExStyle = WS_EX_CLIENTEDGE;
313 switch (This->FolderSettings.ViewMode)
315 case FVM_ICON: dwStyle |= LVS_ICON; break;
316 case FVM_DETAILS: dwStyle |= LVS_REPORT; break;
317 case FVM_SMALLICON: dwStyle |= LVS_SMALLICON; break;
318 case FVM_LIST: dwStyle |= LVS_LIST; break;
319 default: dwStyle |= LVS_LIST; break;
322 if (This->FolderSettings.fFlags & FWF_AUTOARRANGE) dwStyle |= LVS_AUTOARRANGE;
323 if (This->FolderSettings.fFlags & FWF_DESKTOP)
324 This->FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
325 if (This->FolderSettings.fFlags & FWF_SINGLESEL) dwStyle |= LVS_SINGLESEL;
326 if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE)
327 dwExStyle &= ~WS_EX_CLIENTEDGE;
329 This->hWndList=CreateWindowExW( dwExStyle,
330 WC_LISTVIEWW,
331 NULL,
332 dwStyle,
333 0,0,0,0,
334 This->hWnd,
335 (HMENU)ID_LISTVIEW,
336 shell32_hInstance,
337 NULL);
339 if(!This->hWndList)
340 return FALSE;
342 This->ListViewSortInfo.bIsAscending = TRUE;
343 This->ListViewSortInfo.nHeaderID = -1;
344 This->ListViewSortInfo.nLastHeaderID = -1;
346 if (This->FolderSettings.fFlags & FWF_DESKTOP) {
348 * FIXME: look at the registry value
349 * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
350 * and activate drop shadows if necessary
352 if (0)
353 SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, CLR_NONE);
354 else
355 SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, GetSysColor(COLOR_DESKTOP));
357 SendMessageW(This->hWndList, LVM_SETTEXTCOLOR, 0, RGB(255,255,255));
360 /* UpdateShellSettings(); */
361 return TRUE;
364 /**********************************************************
365 * ShellView_InitList()
367 * - adds all needed columns to the shellview
369 static BOOL ShellView_InitList(IShellViewImpl * This)
371 LVCOLUMNW lvColumn;
372 SHELLDETAILS sd;
373 int i;
374 WCHAR szTemp[50];
376 TRACE("%p\n",This);
378 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
380 lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
381 lvColumn.pszText = szTemp;
383 if (This->pSF2Parent)
385 for (i=0; 1; i++)
387 if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd)))
388 break;
389 lvColumn.fmt = sd.fmt;
390 lvColumn.cx = sd.cxChar*8; /* chars->pixel */
391 StrRetToStrNW( szTemp, 50, &sd.str, NULL);
392 SendMessageW(This->hWndList, LVM_INSERTCOLUMNW, i, (LPARAM) &lvColumn);
395 else
397 FIXME("no SF2\n");
400 SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ShellSmallIconList);
401 SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)ShellBigIconList);
403 return TRUE;
405 /**********************************************************
406 * ShellView_CompareItems()
408 * NOTES
409 * internal, CALLBACK for DSA_Sort
411 static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
413 int ret;
414 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
416 if(!lpData) return 0;
418 ret = (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2));
419 TRACE("ret=%i\n",ret);
420 return ret;
423 /*************************************************************************
424 * ShellView_ListViewCompareItems
426 * Compare Function for the Listview (FileOpen Dialog)
428 * PARAMS
429 * lParam1 [I] the first ItemIdList to compare with
430 * lParam2 [I] the second ItemIdList to compare with
431 * lpData [I] The column ID for the header Ctrl to process
433 * RETURNS
434 * A negative value if the first item should precede the second,
435 * a positive value if the first item should follow the second,
436 * or zero if the two items are equivalent
438 * NOTES
439 * FIXME: function does what ShellView_CompareItems is supposed to do.
440 * unify it and figure out how to use the undocumented first parameter
441 * of IShellFolder_CompareIDs to do the job this function does and
442 * move this code to IShellFolder.
443 * make LISTVIEW_SORT_INFO obsolete
444 * the way this function works is only usable if we had only
445 * filesystemfolders (25/10/99 jsch)
447 static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
449 INT nDiff=0;
450 FILETIME fd1, fd2;
451 char strName1[MAX_PATH], strName2[MAX_PATH];
452 BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
453 LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1;
454 LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2;
455 LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData;
458 bIsFolder1 = _ILIsFolder(pItemIdList1);
459 bIsFolder2 = _ILIsFolder(pItemIdList2);
460 bIsBothFolder = bIsFolder1 && bIsFolder2;
462 /* When sorting between a File and a Folder, the Folder gets sorted first */
463 if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
465 nDiff = bIsFolder1 ? -1 : 1;
467 else
469 /* Sort by Time: Folders or Files can be sorted */
471 if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
473 _ILGetFileDateTime(pItemIdList1, &fd1);
474 _ILGetFileDateTime(pItemIdList2, &fd2);
475 nDiff = CompareFileTime(&fd2, &fd1);
477 /* Sort by Attribute: Folder or Files can be sorted */
478 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
480 _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH);
481 _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH);
482 nDiff = lstrcmpiA(strName1, strName2);
484 /* Sort by FileName: Folder or Files can be sorted */
485 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
487 /* Sort by Text */
488 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
489 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
490 nDiff = lstrcmpiA(strName1, strName2);
492 /* Sort by File Size, Only valid for Files */
493 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
495 nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0));
497 /* Sort by File Type, Only valid for Files */
498 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
500 /* Sort by Type */
501 _ILGetFileType(pItemIdList1, strName1, MAX_PATH);
502 _ILGetFileType(pItemIdList2, strName2, MAX_PATH);
503 nDiff = lstrcmpiA(strName1, strName2);
506 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
508 if(nDiff == 0)
510 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
511 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
512 nDiff = lstrcmpiA(strName1, strName2);
515 if(!pSortInfo->bIsAscending)
517 nDiff = -nDiff;
520 return nDiff;
524 /**********************************************************
525 * LV_FindItemByPidl()
527 static int LV_FindItemByPidl(
528 IShellViewImpl * This,
529 LPCITEMIDLIST pidl)
531 LVITEMW lvItem;
532 lvItem.iSubItem = 0;
533 lvItem.mask = LVIF_PARAM;
534 for(lvItem.iItem = 0;
535 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
536 lvItem.iItem++)
538 LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam;
539 HRESULT hr = IShellFolder_CompareIDs(This->pSFParent, 0, pidl, currentpidl);
540 if(SUCCEEDED(hr) && !HRESULT_CODE(hr))
542 return lvItem.iItem;
545 return -1;
548 /**********************************************************
549 * LV_AddItem()
551 static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
553 LVITEMW lvItem;
555 TRACE("(%p)(pidl=%p)\n", This, pidl);
557 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/
558 lvItem.iItem = ListView_GetItemCount(This->hWndList); /*add the item to the end of the list*/
559 lvItem.iSubItem = 0;
560 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/
561 lvItem.pszText = LPSTR_TEXTCALLBACKW; /*get text on a callback basis*/
562 lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/
563 return (-1==ListView_InsertItemW(This->hWndList, &lvItem))? FALSE: TRUE;
566 /**********************************************************
567 * LV_DeleteItem()
569 static BOOLEAN LV_DeleteItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
571 int nIndex;
573 TRACE("(%p)(pidl=%p)\n", This, pidl);
575 nIndex = LV_FindItemByPidl(This, ILFindLastID(pidl));
576 return (-1==ListView_DeleteItem(This->hWndList, nIndex))? FALSE: TRUE;
579 /**********************************************************
580 * LV_RenameItem()
582 static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew )
584 int nItem;
585 LVITEMW lvItem;
587 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew);
589 nItem = LV_FindItemByPidl(This, ILFindLastID(pidlOld));
590 if ( -1 != nItem )
592 lvItem.mask = LVIF_PARAM; /* only the pidl */
593 lvItem.iItem = nItem;
594 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
596 SHFree((LPITEMIDLIST)lvItem.lParam);
597 lvItem.mask = LVIF_PARAM;
598 lvItem.iItem = nItem;
599 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */
600 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
601 SendMessageW(This->hWndList, LVM_UPDATE, nItem, 0);
602 return TRUE; /* FIXME: better handling */
604 return FALSE;
606 /**********************************************************
607 * ShellView_FillList()
609 * - gets the objectlist from the shellfolder
610 * - sorts the list
611 * - fills the list into the view
614 static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg )
616 LPITEMIDLIST pidl = ptr;
617 IShellViewImpl *This = arg;
618 /* in a commdlg This works as a filemask*/
619 if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl);
620 SHFree(pidl);
621 return TRUE;
624 static HRESULT ShellView_FillList(IShellViewImpl * This)
626 LPENUMIDLIST pEnumIDList;
627 LPITEMIDLIST pidl;
628 DWORD dwFetched;
629 HRESULT hRes;
630 HDPA hdpa;
632 TRACE("%p\n",This);
634 /* get the itemlist from the shfolder*/
635 hRes = IShellFolder_EnumObjects(This->pSFParent,This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
636 if (hRes != S_OK)
638 if (hRes==S_FALSE)
639 return(NOERROR);
640 return(hRes);
643 /* create a pointer array */
644 hdpa = DPA_Create(16);
645 if (!hdpa)
647 return(E_OUTOFMEMORY);
650 /* copy the items into the array*/
651 while((S_OK == IEnumIDList_Next(pEnumIDList,1, &pidl, &dwFetched)) && dwFetched)
653 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
655 SHFree(pidl);
659 /* sort the array */
660 DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent);
662 /*turn the listview's redrawing off*/
663 SendMessageA(This->hWndList, WM_SETREDRAW, FALSE, 0);
665 DPA_DestroyCallback( hdpa, fill_list, This );
667 /*turn the listview's redrawing back on and force it to draw*/
668 SendMessageA(This->hWndList, WM_SETREDRAW, TRUE, 0);
670 IEnumIDList_Release(pEnumIDList); /* destroy the list*/
672 return S_OK;
675 /**********************************************************
676 * ShellView_OnCreate()
678 static LRESULT ShellView_OnCreate(IShellViewImpl * This)
680 IDropTarget* pdt;
681 SHChangeNotifyEntry ntreg;
682 IPersistFolder2 * ppf2 = NULL;
684 TRACE("%p\n",This);
686 if(ShellView_CreateList(This))
688 if(ShellView_InitList(This))
690 ShellView_FillList(This);
694 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown*)&This->lpVtbl, &IID_IDropTarget, (LPVOID*)&pdt)))
696 RegisterDragDrop(This->hWnd, pdt);
697 IDropTarget_Release(pdt);
700 /* register for receiving notifications */
701 IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
702 if (ppf2)
704 IPersistFolder2_GetCurFolder(ppf2, (LPITEMIDLIST*)&ntreg.pidl);
705 ntreg.fRecursive = TRUE;
706 This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
707 SHFree((LPITEMIDLIST)ntreg.pidl);
708 IPersistFolder2_Release(ppf2);
711 This->hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel");
713 return S_OK;
716 /**********************************************************
717 * #### Handling of the menus ####
720 /**********************************************************
721 * ShellView_BuildFileMenu()
723 static HMENU ShellView_BuildFileMenu(IShellViewImpl * This)
724 { WCHAR szText[MAX_PATH];
725 MENUITEMINFOW mii;
726 int nTools,i;
727 HMENU hSubMenu;
729 TRACE("(%p)\n",This);
731 hSubMenu = CreatePopupMenu();
732 if(hSubMenu)
733 { /*get the number of items in our global array*/
734 for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
736 /*add the menu items*/
737 for(i = 0; i < nTools; i++)
739 LoadStringW(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
741 ZeroMemory(&mii, sizeof(mii));
742 mii.cbSize = sizeof(mii);
743 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
745 if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
747 mii.fType = MFT_STRING;
748 mii.fState = MFS_ENABLED;
749 mii.dwTypeData = szText;
750 mii.wID = Tools[i].idCommand;
752 else
754 mii.fType = MFT_SEPARATOR;
756 /* tack This item onto the end of the menu */
757 InsertMenuItemW(hSubMenu, (UINT)-1, TRUE, &mii);
760 TRACE("-- return (menu=%p)\n",hSubMenu);
761 return hSubMenu;
763 /**********************************************************
764 * ShellView_MergeFileMenu()
766 static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu)
767 { TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu);
769 if(hSubMenu)
770 { /*insert This item at the beginning of the menu */
771 MENUITEMINFOA mii;
773 mii.cbSize = sizeof(mii);
774 mii.fMask = MIIM_ID | MIIM_TYPE;
775 mii.wID = 0;
776 mii.fType = MFT_SEPARATOR;
777 InsertMenuItemA(hSubMenu, 0, TRUE, &mii);
779 mii.cbSize = sizeof(mii);
780 mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
781 mii.dwTypeData = (LPSTR)"dummy45";
782 mii.fState = MFS_ENABLED;
783 mii.wID = IDM_MYFILEITEM;
784 mii.fType = MFT_STRING;
785 InsertMenuItemA(hSubMenu, 0, TRUE, &mii);
787 TRACE("--\n");
790 /**********************************************************
791 * ShellView_MergeViewMenu()
794 static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu)
796 TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
798 if(hSubMenu)
799 { /*add a separator at the correct position in the menu*/
800 MENUITEMINFOA mii;
801 static char view[] = "View";
803 ZeroMemory(&mii, sizeof(mii));
804 mii.cbSize = sizeof(mii);
805 mii.fMask = MIIM_ID | MIIM_TYPE;
806 mii.wID = 0;
807 mii.fType = MFT_SEPARATOR;
808 InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
810 mii.cbSize = sizeof(mii);
811 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
812 mii.fType = MFT_STRING;
813 mii.dwTypeData = view;
814 mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
815 InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
819 /**********************************************************
820 * ShellView_GetSelections()
822 * - fills the this->apidl list with the selected objects
824 * RETURNS
825 * number of selected items
827 static UINT ShellView_GetSelections(IShellViewImpl * This)
829 LVITEMW lvItem;
830 UINT i = 0;
832 SHFree(This->apidl);
834 This->cidl = ListView_GetSelectedCount(This->hWndList);
835 This->apidl = (LPITEMIDLIST*)SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
837 TRACE("selected=%i\n", This->cidl);
839 if(This->apidl)
841 TRACE("-- Items selected =%u\n", This->cidl);
843 lvItem.mask = LVIF_STATE | LVIF_PARAM;
844 lvItem.stateMask = LVIS_SELECTED;
845 lvItem.iItem = 0;
846 lvItem.iSubItem = 0;
848 while(ListView_GetItemW(This->hWndList, &lvItem) && (i < This->cidl))
850 if(lvItem.state & LVIS_SELECTED)
852 This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
853 i++;
854 TRACE("-- selected Item found\n");
856 lvItem.iItem++;
859 return This->cidl;
863 /**********************************************************
864 * ShellView_OpenSelectedItems()
866 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
868 static UINT CF_IDLIST = 0;
869 HRESULT hr;
870 IDataObject* selection;
871 FORMATETC fetc;
872 STGMEDIUM stgm;
873 LPIDA pIDList;
874 LPCITEMIDLIST parent_pidl;
875 WCHAR parent_path[MAX_PATH];
876 LPCWSTR parent_dir = NULL;
877 SFGAOF attribs;
878 int i;
880 if (0 == ShellView_GetSelections(This))
882 return S_OK;
884 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
885 (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
886 0, (LPVOID *)&selection);
887 if (FAILED(hr))
888 return hr;
890 if (0 == CF_IDLIST)
892 CF_IDLIST = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
894 fetc.cfFormat = CF_IDLIST;
895 fetc.ptd = NULL;
896 fetc.dwAspect = DVASPECT_CONTENT;
897 fetc.lindex = -1;
898 fetc.tymed = TYMED_HGLOBAL;
900 hr = IDataObject_QueryGetData(selection, &fetc);
901 if (FAILED(hr))
902 return hr;
904 hr = IDataObject_GetData(selection, &fetc, &stgm);
905 if (FAILED(hr))
906 return hr;
908 pIDList = GlobalLock(stgm.u.hGlobal);
910 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
911 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &parent_pidl, &attribs);
912 if (SUCCEEDED(hr) && (attribs & SFGAO_FILESYSTEM) &&
913 SHGetPathFromIDListW(parent_pidl, parent_path))
915 parent_dir = parent_path;
918 for (i = pIDList->cidl; i > 0; --i)
920 LPCITEMIDLIST pidl;
922 pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
924 attribs = SFGAO_FOLDER;
925 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
927 if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
929 SHELLEXECUTEINFOW shexinfo;
931 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
932 shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */
933 shexinfo.hwnd = NULL;
934 shexinfo.lpVerb = NULL;
935 shexinfo.lpFile = NULL;
936 shexinfo.lpParameters = NULL;
937 shexinfo.lpDirectory = parent_dir;
938 shexinfo.nShow = SW_NORMAL;
939 shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
941 ShellExecuteExW(&shexinfo); /* Discard error/success info */
943 ILFree((LPITEMIDLIST)shexinfo.lpIDList);
947 GlobalUnlock(stgm.u.hGlobal);
948 ReleaseStgMedium(&stgm);
950 IDataObject_Release(selection);
952 return S_OK;
955 /**********************************************************
956 * ShellView_DoContextMenu()
958 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
959 { UINT uCommand;
960 DWORD wFlags;
961 HMENU hMenu;
962 BOOL fExplore = FALSE;
963 HWND hwndTree = 0;
964 LPCONTEXTMENU pContextMenu = NULL;
965 IContextMenu2 *pCM = NULL;
966 CMINVOKECOMMANDINFO cmi;
968 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
970 /* look, what's selected and create a context menu object of it*/
971 if( ShellView_GetSelections(This) )
973 IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
974 (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
976 if(pContextMenu)
978 TRACE("-- pContextMenu\n");
979 hMenu = CreatePopupMenu();
981 if( hMenu )
983 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
984 if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
986 TRACE("-- explore mode\n");
987 fExplore = TRUE;
990 /* build the flags depending on what we can do with the selected item */
991 wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
993 /* let the ContextMenu merge its items in */
994 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
996 if (This->FolderSettings.fFlags & FWF_DESKTOP)
997 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
999 if( bDefault )
1001 TRACE("-- get menu default command\n");
1002 uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
1004 else
1006 TRACE("-- track popup\n");
1007 uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1010 if(uCommand > 0)
1012 TRACE("-- uCommand=%u\n", uCommand);
1013 if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
1015 TRACE("-- dlg: OnDefaultCommand\n");
1016 if (OnDefaultCommand(This) != S_OK)
1018 ShellView_OpenSelectedItems(This);
1021 else
1023 TRACE("-- explore -- invoke command\n");
1024 ZeroMemory(&cmi, sizeof(cmi));
1025 cmi.cbSize = sizeof(cmi);
1026 cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
1027 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1028 IContextMenu_InvokeCommand(pContextMenu, &cmi);
1031 DestroyMenu(hMenu);
1034 if (pContextMenu)
1035 IContextMenu_Release(pContextMenu);
1038 else /* background context menu */
1040 hMenu = CreatePopupMenu();
1042 pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
1043 IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1045 uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1046 DestroyMenu(hMenu);
1048 TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1050 ZeroMemory(&cmi, sizeof(cmi));
1051 cmi.cbSize = sizeof(cmi);
1052 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1053 cmi.hwnd = This->hWndParent;
1054 IContextMenu2_InvokeCommand(pCM, &cmi);
1056 IContextMenu2_Release(pCM);
1060 /**********************************************************
1061 * ##### message handling #####
1064 /**********************************************************
1065 * ShellView_OnSize()
1067 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1069 TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1071 /*resize the ListView to fit our window*/
1072 if(This->hWndList)
1074 MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1077 return S_OK;
1079 /**********************************************************
1080 * ShellView_OnDeactivate()
1082 * NOTES
1083 * internal
1085 static void ShellView_OnDeactivate(IShellViewImpl * This)
1087 TRACE("%p\n",This);
1089 if(This->uState != SVUIA_DEACTIVATE)
1091 if(This->hMenu)
1093 IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1094 IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1095 DestroyMenu(This->hMenu);
1096 This->hMenu = 0;
1099 This->uState = SVUIA_DEACTIVATE;
1103 /**********************************************************
1104 * ShellView_OnActivate()
1106 static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState)
1107 { OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} };
1108 MENUITEMINFOA mii;
1109 CHAR szText[MAX_PATH];
1111 TRACE("%p uState=%x\n",This,uState);
1113 /*don't do anything if the state isn't really changing */
1114 if(This->uState == uState)
1116 return S_OK;
1119 ShellView_OnDeactivate(This);
1121 /*only do This if we are active */
1122 if(uState != SVUIA_DEACTIVATE)
1124 /*merge the menus */
1125 This->hMenu = CreateMenu();
1127 if(This->hMenu)
1129 IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1130 TRACE("-- after fnInsertMenusSB\n");
1132 /*build the top level menu get the menu item's text*/
1133 strcpy(szText,"dummy 31");
1135 ZeroMemory(&mii, sizeof(mii));
1136 mii.cbSize = sizeof(mii);
1137 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1138 mii.fType = MFT_STRING;
1139 mii.fState = MFS_ENABLED;
1140 mii.dwTypeData = szText;
1141 mii.hSubMenu = ShellView_BuildFileMenu(This);
1143 /*insert our menu into the menu bar*/
1144 if(mii.hSubMenu)
1146 InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1149 /*get the view menu so we can merge with it*/
1150 ZeroMemory(&mii, sizeof(mii));
1151 mii.cbSize = sizeof(mii);
1152 mii.fMask = MIIM_SUBMENU;
1154 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1156 ShellView_MergeViewMenu(This, mii.hSubMenu);
1159 /*add the items that should only be added if we have the focus*/
1160 if(SVUIA_ACTIVATE_FOCUS == uState)
1162 /*get the file menu so we can merge with it */
1163 ZeroMemory(&mii, sizeof(mii));
1164 mii.cbSize = sizeof(mii);
1165 mii.fMask = MIIM_SUBMENU;
1167 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1169 ShellView_MergeFileMenu(This, mii.hSubMenu);
1172 TRACE("-- before fnSetMenuSB\n");
1173 IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1176 This->uState = uState;
1177 TRACE("--\n");
1178 return S_OK;
1181 /**********************************************************
1182 * ShellView_OnSetFocus()
1185 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1187 TRACE("%p\n",This);
1189 /* Tell the browser one of our windows has received the focus. This
1190 should always be done before merging menus (OnActivate merges the
1191 menus) if one of our windows has the focus.*/
1193 IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1194 ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1196 /* Set the focus to the listview */
1197 SetFocus(This->hWndList);
1199 /* Notify the ICommDlgBrowser interface */
1200 OnStateChange(This,CDBOSC_SETFOCUS);
1202 return 0;
1205 /**********************************************************
1206 * ShellView_OnKillFocus()
1208 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1210 TRACE("(%p) stub\n",This);
1212 ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1213 /* Notify the ICommDlgBrowser */
1214 OnStateChange(This,CDBOSC_KILLFOCUS);
1216 return 0;
1219 /**********************************************************
1220 * ShellView_OnCommand()
1222 * NOTES
1223 * the CmdID's are the ones from the context menu
1225 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1227 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1229 switch(dwCmdID)
1231 case FCIDM_SHVIEW_SMALLICON:
1232 This->FolderSettings.ViewMode = FVM_SMALLICON;
1233 SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1234 CheckToolbar(This);
1235 break;
1237 case FCIDM_SHVIEW_BIGICON:
1238 This->FolderSettings.ViewMode = FVM_ICON;
1239 SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1240 CheckToolbar(This);
1241 break;
1243 case FCIDM_SHVIEW_LISTVIEW:
1244 This->FolderSettings.ViewMode = FVM_LIST;
1245 SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1246 CheckToolbar(This);
1247 break;
1249 case FCIDM_SHVIEW_REPORTVIEW:
1250 This->FolderSettings.ViewMode = FVM_DETAILS;
1251 SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1252 CheckToolbar(This);
1253 break;
1255 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1256 case 0x30:
1257 case 0x31:
1258 case 0x32:
1259 case 0x33:
1260 This->ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30);
1261 This->ListViewSortInfo.bIsAscending = TRUE;
1262 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1263 SendMessageA(This->hWndList, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1264 break;
1266 default:
1267 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID);
1269 return 0;
1272 /**********************************************************
1273 * ShellView_OnNotify()
1276 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1277 { LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1278 NMLVDISPINFOW *lpdi = (NMLVDISPINFOW *)lpnmh;
1279 LPITEMIDLIST pidl;
1281 TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1283 switch(lpnmh->code)
1285 case NM_SETFOCUS:
1286 TRACE("-- NM_SETFOCUS %p\n",This);
1287 ShellView_OnSetFocus(This);
1288 break;
1290 case NM_KILLFOCUS:
1291 TRACE("-- NM_KILLFOCUS %p\n",This);
1292 ShellView_OnDeactivate(This);
1293 /* Notify the ICommDlgBrowser interface */
1294 OnStateChange(This,CDBOSC_KILLFOCUS);
1295 break;
1297 case NM_CUSTOMDRAW:
1298 TRACE("-- NM_CUSTOMDRAW %p\n",This);
1299 return CDRF_DODEFAULT;
1301 case NM_RELEASEDCAPTURE:
1302 TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1303 break;
1305 case NM_CLICK:
1306 TRACE("-- NM_CLICK %p\n",This);
1307 break;
1309 case NM_RCLICK:
1310 TRACE("-- NM_RCLICK %p\n",This);
1311 break;
1313 case NM_DBLCLK:
1314 TRACE("-- NM_DBLCLK %p\n",This);
1315 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1316 break;
1318 case NM_RETURN:
1319 TRACE("-- NM_DBLCLK %p\n",This);
1320 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1321 break;
1323 case HDN_ENDTRACKW:
1324 TRACE("-- HDN_ENDTRACKW %p\n",This);
1325 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1326 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1327 break;
1329 case LVN_DELETEITEM:
1330 TRACE("-- LVN_DELETEITEM %p\n",This);
1331 SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/
1332 break;
1334 case LVN_DELETEALLITEMS:
1335 TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1336 return FALSE;
1338 case LVN_INSERTITEM:
1339 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1340 break;
1342 case LVN_ITEMACTIVATE:
1343 TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1344 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1345 break;
1347 case LVN_COLUMNCLICK:
1348 This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1349 if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1351 This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1353 else
1355 This->ListViewSortInfo.bIsAscending = TRUE;
1357 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1359 SendMessageW(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1360 break;
1362 case LVN_GETDISPINFOA:
1363 case LVN_GETDISPINFOW:
1364 TRACE("-- LVN_GETDISPINFO %p\n",This);
1365 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1367 if(lpdi->item.mask & LVIF_TEXT) /* text requested */
1369 if (This->pSF2Parent)
1371 SHELLDETAILS sd;
1372 IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1373 if (lpnmh->code == LVN_GETDISPINFOA)
1375 /* shouldn't happen */
1376 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1377 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1378 TRACE("-- text=%s\n",lpdiA->item.pszText);
1380 else /* LVN_GETDISPINFOW */
1382 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1383 TRACE("-- text=%s\n",debugstr_w(lpdi->item.pszText));
1386 else
1388 FIXME("no SF2\n");
1391 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1393 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1395 break;
1397 case LVN_ITEMCHANGED:
1398 TRACE("-- LVN_ITEMCHANGED %p\n",This);
1399 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1400 break;
1402 case LVN_BEGINDRAG:
1403 case LVN_BEGINRDRAG:
1404 TRACE("-- LVN_BEGINDRAG\n");
1406 if (ShellView_GetSelections(This))
1408 IDataObject * pda;
1409 DWORD dwAttributes = SFGAO_CANLINK;
1410 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1412 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1414 IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource); /* own DropSource interface */
1416 if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1418 if (dwAttributes & SFGAO_CANLINK)
1420 dwEffect |= DROPEFFECT_LINK;
1424 if (pds)
1426 DWORD dwEffect;
1427 DoDragDrop(pda, pds, dwEffect, &dwEffect);
1429 IDataObject_Release(pda);
1432 break;
1434 case LVN_BEGINLABELEDITW:
1436 DWORD dwAttr = SFGAO_CANRENAME;
1437 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1439 TRACE("-- LVN_BEGINLABELEDITA %p\n",This);
1441 IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1442 if (SFGAO_CANRENAME & dwAttr)
1444 return FALSE;
1446 return TRUE;
1449 case LVN_ENDLABELEDITW:
1451 TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1452 if (lpdi->item.pszText)
1454 HRESULT hr;
1455 LVITEMW lvItem;
1457 lvItem.iItem = lpdi->item.iItem;
1458 lvItem.iSubItem = 0;
1459 lvItem.mask = LVIF_PARAM;
1460 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
1462 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1463 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidl);
1465 if(SUCCEEDED(hr) && pidl)
1467 lvItem.mask = LVIF_PARAM;
1468 lvItem.lParam = (LPARAM)pidl;
1469 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
1470 return TRUE;
1473 return FALSE;
1476 case LVN_KEYDOWN:
1478 /* MSG msg;
1479 msg.hwnd = This->hWnd;
1480 msg.message = WM_KEYDOWN;
1481 msg.wParam = plvKeyDown->wVKey;
1482 msg.lParam = 0;
1483 msg.time = 0;
1484 msg.pt = 0;*/
1486 LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1488 /* initiate a rename of the selected file or directory */
1489 if(plvKeyDown->wVKey == VK_F2)
1491 /* see how many files are selected */
1492 int i = ListView_GetSelectedCount(This->hWndList);
1494 /* get selected item */
1495 if(i == 1)
1497 /* get selected item */
1498 i = ListView_GetNextItem(This->hWndList, -1,
1499 LVNI_SELECTED);
1501 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1502 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
1505 #if 0
1506 TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1507 #endif
1508 else if(plvKeyDown->wVKey == VK_DELETE)
1510 UINT i;
1511 int item_index;
1512 LVITEMA item;
1513 LPITEMIDLIST* pItems;
1514 ISFHelper *psfhlp;
1516 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1517 (LPVOID*)&psfhlp);
1519 if (psfhlp == NULL)
1520 break;
1522 if(!(i = ListView_GetSelectedCount(This->hWndList)))
1523 break;
1525 /* allocate memory for the pidl array */
1526 pItems = HeapAlloc(GetProcessHeap(), 0,
1527 sizeof(LPITEMIDLIST) * i);
1529 /* retrieve all selected items */
1530 i = 0;
1531 item_index = -1;
1532 while(ListView_GetSelectedCount(This->hWndList) > i)
1534 /* get selected item */
1535 item_index = ListView_GetNextItem(This->hWndList,
1536 item_index, LVNI_SELECTED);
1537 item.iItem = item_index;
1538 item.mask = LVIF_PARAM;
1539 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &item);
1541 /* get item pidl */
1542 pItems[i] = (LPITEMIDLIST)item.lParam;
1544 i++;
1547 /* perform the item deletion */
1548 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1550 /* free pidl array memory */
1551 HeapFree(GetProcessHeap(), 0, pItems);
1554 /* Initiate a refresh */
1555 else if(plvKeyDown->wVKey == VK_F5)
1557 IShellView_Refresh((IShellView*)This);
1560 else
1561 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1563 break;
1565 default:
1566 TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1567 break;
1569 return 0;
1572 /**********************************************************
1573 * ShellView_OnChange()
1576 static LRESULT ShellView_OnChange(IShellViewImpl * This, const LPCITEMIDLIST * Pidls, LONG wEventId)
1579 TRACE("(%p)(%p,%p,0x%08x)\n", This, Pidls[0], Pidls[1], wEventId);
1580 switch(wEventId)
1582 case SHCNE_MKDIR:
1583 case SHCNE_CREATE:
1584 LV_AddItem(This, Pidls[0]);
1585 break;
1586 case SHCNE_RMDIR:
1587 case SHCNE_DELETE:
1588 LV_DeleteItem(This, Pidls[0]);
1589 break;
1590 case SHCNE_RENAMEFOLDER:
1591 case SHCNE_RENAMEITEM:
1592 LV_RenameItem(This, Pidls[0], Pidls[1]);
1593 break;
1594 case SHCNE_UPDATEITEM:
1595 break;
1597 return TRUE;
1599 /**********************************************************
1600 * ShellView_WndProc
1603 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1605 IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1606 LPCREATESTRUCTW lpcs;
1608 TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1610 switch (uMessage)
1612 case WM_NCCREATE:
1613 lpcs = (LPCREATESTRUCTW)lParam;
1614 pThis = (IShellViewImpl*)(lpcs->lpCreateParams);
1615 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1616 pThis->hWnd = hWnd; /*set the window handle*/
1617 break;
1619 case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1620 case WM_SETFOCUS: return ShellView_OnSetFocus(pThis);
1621 case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis);
1622 case WM_CREATE: return ShellView_OnCreate(pThis);
1623 case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1624 case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1625 case WM_COMMAND: return ShellView_OnCommand(pThis,
1626 GET_WM_COMMAND_ID(wParam, lParam),
1627 GET_WM_COMMAND_CMD(wParam, lParam),
1628 GET_WM_COMMAND_HWND(wParam, lParam));
1629 case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (const LPCITEMIDLIST*)wParam, (LONG)lParam);
1631 case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1632 return 0;
1634 case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
1635 break;
1637 case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0);
1639 case WM_DESTROY:
1640 RevokeDragDrop(pThis->hWnd);
1641 SHChangeNotifyDeregister(pThis->hNotify);
1642 break;
1644 case WM_ERASEBKGND:
1645 if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1646 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1647 return 1;
1648 break;
1651 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
1653 /**********************************************************
1656 * The INTERFACE of the IShellView object
1659 **********************************************************
1660 * IShellView_QueryInterface
1662 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj)
1664 IShellViewImpl *This = (IShellViewImpl *)iface;
1666 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1668 *ppvObj = NULL;
1670 if(IsEqualIID(riid, &IID_IUnknown))
1672 *ppvObj = This;
1674 else if(IsEqualIID(riid, &IID_IShellView))
1676 *ppvObj = (IShellView*)This;
1678 else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1680 *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget);
1682 else if(IsEqualIID(riid, &IID_IDropTarget))
1684 *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
1686 else if(IsEqualIID(riid, &IID_IDropSource))
1688 *ppvObj = (IDropSource*)&(This->lpvtblDropSource);
1690 else if(IsEqualIID(riid, &IID_IViewObject))
1692 *ppvObj = (IViewObject*)&(This->lpvtblViewObject);
1695 if(*ppvObj)
1697 IUnknown_AddRef( (IUnknown*)*ppvObj );
1698 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1699 return S_OK;
1701 TRACE("-- Interface: E_NOINTERFACE\n");
1702 return E_NOINTERFACE;
1705 /**********************************************************
1706 * IShellView_AddRef
1708 static ULONG WINAPI IShellView_fnAddRef(IShellView * iface)
1710 IShellViewImpl *This = (IShellViewImpl *)iface;
1711 ULONG refCount = InterlockedIncrement(&This->ref);
1713 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
1715 return refCount;
1717 /**********************************************************
1718 * IShellView_Release
1720 static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
1722 IShellViewImpl *This = (IShellViewImpl *)iface;
1723 ULONG refCount = InterlockedDecrement(&This->ref);
1725 TRACE("(%p)->(count=%i)\n", This, refCount + 1);
1727 if (!refCount)
1729 TRACE(" destroying IShellView(%p)\n",This);
1731 DestroyWindow(This->hWndList);
1733 if(This->pSFParent)
1734 IShellFolder_Release(This->pSFParent);
1736 if(This->pSF2Parent)
1737 IShellFolder2_Release(This->pSF2Parent);
1739 SHFree(This->apidl);
1741 if(This->pAdvSink)
1742 IAdviseSink_Release(This->pAdvSink);
1744 HeapFree(GetProcessHeap(),0,This);
1746 return refCount;
1749 /**********************************************************
1750 * ShellView_GetWindow
1752 static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd)
1754 IShellViewImpl *This = (IShellViewImpl *)iface;
1756 TRACE("(%p)\n",This);
1758 *phWnd = This->hWnd;
1760 return S_OK;
1763 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode)
1765 IShellViewImpl *This = (IShellViewImpl *)iface;
1767 FIXME("(%p) stub\n",This);
1769 return E_NOTIMPL;
1772 /**********************************************************
1773 * IShellView_TranslateAccelerator
1775 * FIXME:
1776 * use the accel functions
1778 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg)
1780 #if 0
1781 IShellViewImpl *This = (IShellViewImpl *)iface;
1783 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1784 #endif
1786 if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1788 TRACE("-- key=0x04%lx\n",lpmsg->wParam) ;
1790 return S_FALSE; /* not handled */
1793 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable)
1795 IShellViewImpl *This = (IShellViewImpl *)iface;
1797 FIXME("(%p) stub\n",This);
1799 return E_NOTIMPL;
1802 static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState)
1804 IShellViewImpl *This = (IShellViewImpl *)iface;
1807 CHAR szName[MAX_PATH];
1809 LRESULT lResult;
1810 int nPartArray[1] = {-1};
1812 TRACE("(%p)->(state=%x) stub\n",This, uState);
1814 /*don't do anything if the state isn't really changing*/
1815 if(This->uState == uState)
1817 return S_OK;
1820 /*OnActivate handles the menu merging and internal state*/
1821 ShellView_OnActivate(This, uState);
1823 /*only do This if we are active*/
1824 if(uState != SVUIA_DEACTIVATE)
1828 GetFolderPath is not a method of IShellFolder
1829 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1831 /* set the number of parts */
1832 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1833 (LPARAM)nPartArray, &lResult);
1835 /* set the text for the parts */
1837 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1838 0, (LPARAM)szName, &lResult);
1842 return S_OK;
1845 static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface)
1847 IShellViewImpl *This = (IShellViewImpl *)iface;
1849 TRACE("(%p)\n",This);
1851 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
1852 ShellView_FillList(This);
1854 return S_OK;
1857 static HRESULT WINAPI IShellView_fnCreateViewWindow(
1858 IShellView * iface,
1859 IShellView *lpPrevView,
1860 LPCFOLDERSETTINGS lpfs,
1861 IShellBrowser * psb,
1862 RECT * prcView,
1863 HWND *phWnd)
1865 IShellViewImpl *This = (IShellViewImpl *)iface;
1867 WNDCLASSW wc;
1868 *phWnd = 0;
1871 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd);
1872 TRACE("-- vmode=%x flags=%x left=%i top=%i right=%i bottom=%i\n",lpfs->ViewMode, lpfs->fFlags ,prcView->left,prcView->top, prcView->right, prcView->bottom);
1874 /*set up the member variables*/
1875 This->pShellBrowser = psb;
1876 This->FolderSettings = *lpfs;
1878 /*get our parent window*/
1879 IShellBrowser_AddRef(This->pShellBrowser);
1880 IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
1882 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1883 This->pCommDlgBrowser=NULL;
1884 if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser,
1885 (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser)))
1887 TRACE("-- CommDlgBrowser\n");
1890 /*if our window class has not been registered, then do so*/
1891 if(!GetClassInfoW(shell32_hInstance, SV_CLASS_NAME, &wc))
1893 ZeroMemory(&wc, sizeof(wc));
1894 wc.style = CS_HREDRAW | CS_VREDRAW;
1895 wc.lpfnWndProc = ShellView_WndProc;
1896 wc.cbClsExtra = 0;
1897 wc.cbWndExtra = 0;
1898 wc.hInstance = shell32_hInstance;
1899 wc.hIcon = 0;
1900 wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
1901 wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
1902 wc.lpszMenuName = NULL;
1903 wc.lpszClassName = SV_CLASS_NAME;
1905 if(!RegisterClassW(&wc))
1906 return E_FAIL;
1909 *phWnd = CreateWindowExW(0,
1910 SV_CLASS_NAME,
1911 NULL,
1912 WS_CHILD | WS_TABSTOP,
1913 prcView->left,
1914 prcView->top,
1915 prcView->right - prcView->left,
1916 prcView->bottom - prcView->top,
1917 This->hWndParent,
1919 shell32_hInstance,
1920 (LPVOID)This);
1922 CheckToolbar(This);
1924 if(!*phWnd) return E_FAIL;
1926 SetWindowPos(*phWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
1927 UpdateWindow(*phWnd);
1929 return S_OK;
1932 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
1934 IShellViewImpl *This = (IShellViewImpl *)iface;
1936 TRACE("(%p)\n",This);
1938 /*Make absolutely sure all our UI is cleaned up.*/
1939 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1941 if(This->hMenu)
1943 DestroyMenu(This->hMenu);
1946 DestroyWindow(This->hWnd);
1947 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1948 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1951 return S_OK;
1954 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs)
1956 IShellViewImpl *This = (IShellViewImpl *)iface;
1958 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1959 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1961 if (!lpfs) return E_INVALIDARG;
1963 *lpfs = This->FolderSettings;
1964 return NOERROR;
1967 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1969 IShellViewImpl *This = (IShellViewImpl *)iface;
1971 FIXME("(%p) stub\n",This);
1973 return E_NOTIMPL;
1976 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface)
1978 IShellViewImpl *This = (IShellViewImpl *)iface;
1980 FIXME("(%p) stub\n",This);
1982 return S_OK;
1985 static HRESULT WINAPI IShellView_fnSelectItem(
1986 IShellView * iface,
1987 LPCITEMIDLIST pidl,
1988 UINT uFlags)
1990 IShellViewImpl *This = (IShellViewImpl *)iface;
1991 int i;
1993 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
1995 i = LV_FindItemByPidl(This, pidl);
1997 if (i != -1)
1999 LVITEMW lvItem;
2001 if(uFlags & SVSI_ENSUREVISIBLE)
2002 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
2004 lvItem.mask = LVIF_STATE;
2005 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
2006 lvItem.iItem = 0;
2007 lvItem.iSubItem = 0;
2009 while(SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem))
2011 if (lvItem.iItem == i)
2013 if (uFlags & SVSI_SELECT)
2014 lvItem.state |= LVIS_SELECTED;
2015 else
2016 lvItem.state &= ~LVIS_SELECTED;
2018 if(uFlags & SVSI_FOCUSED)
2019 lvItem.state &= ~LVIS_FOCUSED;
2021 else
2023 if (uFlags & SVSI_DESELECTOTHERS)
2024 lvItem.state &= ~LVIS_SELECTED;
2026 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
2027 lvItem.iItem++;
2031 if(uFlags & SVSI_EDIT)
2032 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
2035 return S_OK;
2038 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
2040 IShellViewImpl *This = (IShellViewImpl *)iface;
2042 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2044 *ppvOut = NULL;
2046 switch(uItem)
2048 case SVGIO_BACKGROUND:
2049 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2050 break;
2052 case SVGIO_SELECTION:
2053 ShellView_GetSelections(This);
2054 IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2055 break;
2057 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2059 if(!*ppvOut) return E_OUTOFMEMORY;
2061 return S_OK;
2064 static const IShellViewVtbl svvt =
2066 IShellView_fnQueryInterface,
2067 IShellView_fnAddRef,
2068 IShellView_fnRelease,
2069 IShellView_fnGetWindow,
2070 IShellView_fnContextSensitiveHelp,
2071 IShellView_fnTranslateAccelerator,
2072 IShellView_fnEnableModeless,
2073 IShellView_fnUIActivate,
2074 IShellView_fnRefresh,
2075 IShellView_fnCreateViewWindow,
2076 IShellView_fnDestroyViewWindow,
2077 IShellView_fnGetCurrentInfo,
2078 IShellView_fnAddPropertySheetPages,
2079 IShellView_fnSaveViewState,
2080 IShellView_fnSelectItem,
2081 IShellView_fnGetItemObject
2085 /**********************************************************
2086 * ISVOleCmdTarget_QueryInterface (IUnknown)
2088 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2089 IOleCommandTarget * iface,
2090 REFIID iid,
2091 LPVOID* ppvObj)
2093 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2095 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2098 /**********************************************************
2099 * ISVOleCmdTarget_AddRef (IUnknown)
2101 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2102 IOleCommandTarget * iface)
2104 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2106 return IShellFolder_AddRef((IShellFolder*)This);
2109 /**********************************************************
2110 * ISVOleCmdTarget_Release (IUnknown)
2112 static ULONG WINAPI ISVOleCmdTarget_Release(
2113 IOleCommandTarget * iface)
2115 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2117 return IShellFolder_Release((IShellFolder*)This);
2120 /**********************************************************
2121 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2123 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2124 IOleCommandTarget *iface,
2125 const GUID* pguidCmdGroup,
2126 ULONG cCmds,
2127 OLECMD * prgCmds,
2128 OLECMDTEXT* pCmdText)
2130 UINT i;
2131 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2133 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2134 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2136 if (!prgCmds)
2137 return E_POINTER;
2138 for (i = 0; i < cCmds; i++)
2140 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2141 prgCmds[i].cmdf = 0;
2143 return OLECMDERR_E_UNKNOWNGROUP;
2146 /**********************************************************
2147 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2149 * nCmdID is the OLECMDID_* enumeration
2151 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2152 IOleCommandTarget *iface,
2153 const GUID* pguidCmdGroup,
2154 DWORD nCmdID,
2155 DWORD nCmdexecopt,
2156 VARIANT* pvaIn,
2157 VARIANT* pvaOut)
2159 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2161 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2162 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2164 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2165 (nCmdID == 0x29) &&
2166 (nCmdexecopt == 4) && pvaOut)
2167 return S_OK;
2168 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2169 (nCmdID == 9) &&
2170 (nCmdexecopt == 0))
2171 return 1;
2173 return OLECMDERR_E_UNKNOWNGROUP;
2176 static const IOleCommandTargetVtbl ctvt =
2178 ISVOleCmdTarget_QueryInterface,
2179 ISVOleCmdTarget_AddRef,
2180 ISVOleCmdTarget_Release,
2181 ISVOleCmdTarget_QueryStatus,
2182 ISVOleCmdTarget_Exec
2185 /**********************************************************
2186 * ISVDropTarget implementation
2189 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2190 IDropTarget *iface,
2191 REFIID riid,
2192 LPVOID *ppvObj)
2194 IShellViewImpl *This = impl_from_IDropTarget(iface);
2196 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2198 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2201 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2203 IShellViewImpl *This = impl_from_IDropTarget(iface);
2205 TRACE("(%p)->(count=%u)\n",This,This->ref);
2207 return IShellFolder_AddRef((IShellFolder*)This);
2210 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2212 IShellViewImpl *This = impl_from_IDropTarget(iface);
2214 TRACE("(%p)->(count=%u)\n",This,This->ref);
2216 return IShellFolder_Release((IShellFolder*)This);
2219 /******************************************************************************
2220 * drag_notify_subitem [Internal]
2222 * Figure out the shellfolder object, which is currently under the mouse cursor
2223 * and notify it via the IDropTarget interface.
2226 #define SCROLLAREAWIDTH 20
2228 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2229 DWORD *pdwEffect)
2231 LVHITTESTINFO htinfo;
2232 LVITEMW lvItem;
2233 LONG lResult;
2234 HRESULT hr;
2235 RECT clientRect;
2237 /* Map from global to client coordinates and query the index of the listview-item, which is
2238 * currently under the mouse cursor. */
2239 htinfo.pt.x = pt.x;
2240 htinfo.pt.y = pt.y;
2241 htinfo.flags = LVHT_ONITEM;
2242 ScreenToClient(This->hWndList, &htinfo.pt);
2243 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2245 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2246 GetClientRect(This->hWndList, &clientRect);
2247 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2248 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2249 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2251 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2252 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2253 if (htinfo.pt.x < SCROLLAREAWIDTH)
2254 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2255 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2256 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2257 if (htinfo.pt.y < SCROLLAREAWIDTH)
2258 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2259 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2260 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2262 } else {
2263 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2265 This->ptLastMousePos = htinfo.pt;
2267 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2268 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2269 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2271 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2272 if (This->pCurDropTarget) {
2273 IDropTarget_DragLeave(This->pCurDropTarget);
2274 IDropTarget_Release(This->pCurDropTarget);
2275 This->pCurDropTarget = NULL;
2278 This->iDragOverItem = lResult;
2279 if (lResult == -1) {
2280 /* We are not above one of the listview's subitems. Bind to the parent folder's
2281 * DropTarget interface. */
2282 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2283 (LPVOID*)&This->pCurDropTarget);
2284 } else {
2285 /* Query the relative PIDL of the shellfolder object represented by the currently
2286 * dragged over listview-item ... */
2287 lvItem.mask = LVIF_PARAM;
2288 lvItem.iItem = lResult;
2289 lvItem.iSubItem = 0;
2290 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
2292 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2293 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2294 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2297 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2298 if (FAILED(hr))
2299 return hr;
2301 /* Notify the item just entered via DragEnter. */
2302 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2305 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2306 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2308 IShellViewImpl *This = impl_from_IDropTarget(iface);
2310 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2311 This->pCurDataObject = pDataObject;
2312 IDataObject_AddRef(pDataObject);
2314 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2317 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2318 DWORD *pdwEffect)
2320 IShellViewImpl *This = impl_from_IDropTarget(iface);
2321 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2324 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2325 IShellViewImpl *This = impl_from_IDropTarget(iface);
2327 IDropTarget_DragLeave(This->pCurDropTarget);
2329 IDropTarget_Release(This->pCurDropTarget);
2330 IDataObject_Release(This->pCurDataObject);
2331 This->pCurDataObject = NULL;
2332 This->pCurDropTarget = NULL;
2333 This->iDragOverItem = 0;
2335 return S_OK;
2338 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2339 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2341 IShellViewImpl *This = impl_from_IDropTarget(iface);
2343 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2345 IDropTarget_Release(This->pCurDropTarget);
2346 IDataObject_Release(This->pCurDataObject);
2347 This->pCurDataObject = NULL;
2348 This->pCurDropTarget = NULL;
2349 This->iDragOverItem = 0;
2351 return S_OK;
2354 static const IDropTargetVtbl dtvt =
2356 ISVDropTarget_QueryInterface,
2357 ISVDropTarget_AddRef,
2358 ISVDropTarget_Release,
2359 ISVDropTarget_DragEnter,
2360 ISVDropTarget_DragOver,
2361 ISVDropTarget_DragLeave,
2362 ISVDropTarget_Drop
2365 /**********************************************************
2366 * ISVDropSource implementation
2369 static HRESULT WINAPI ISVDropSource_QueryInterface(
2370 IDropSource *iface,
2371 REFIID riid,
2372 LPVOID *ppvObj)
2374 IShellViewImpl *This = impl_from_IDropSource(iface);
2376 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2378 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2381 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2383 IShellViewImpl *This = impl_from_IDropSource(iface);
2385 TRACE("(%p)->(count=%u)\n",This,This->ref);
2387 return IShellFolder_AddRef((IShellFolder*)This);
2390 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2392 IShellViewImpl *This = impl_from_IDropSource(iface);
2394 TRACE("(%p)->(count=%u)\n",This,This->ref);
2396 return IShellFolder_Release((IShellFolder*)This);
2398 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2399 IDropSource *iface,
2400 BOOL fEscapePressed,
2401 DWORD grfKeyState)
2403 IShellViewImpl *This = impl_from_IDropSource(iface);
2404 TRACE("(%p)\n",This);
2406 if (fEscapePressed)
2407 return DRAGDROP_S_CANCEL;
2408 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2409 return DRAGDROP_S_DROP;
2410 else
2411 return NOERROR;
2414 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2415 IDropSource *iface,
2416 DWORD dwEffect)
2418 IShellViewImpl *This = impl_from_IDropSource(iface);
2419 TRACE("(%p)\n",This);
2421 return DRAGDROP_S_USEDEFAULTCURSORS;
2424 static const IDropSourceVtbl dsvt =
2426 ISVDropSource_QueryInterface,
2427 ISVDropSource_AddRef,
2428 ISVDropSource_Release,
2429 ISVDropSource_QueryContinueDrag,
2430 ISVDropSource_GiveFeedback
2432 /**********************************************************
2433 * ISVViewObject implementation
2436 static HRESULT WINAPI ISVViewObject_QueryInterface(
2437 IViewObject *iface,
2438 REFIID riid,
2439 LPVOID *ppvObj)
2441 IShellViewImpl *This = impl_from_IViewObject(iface);
2443 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2445 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2448 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2450 IShellViewImpl *This = impl_from_IViewObject(iface);
2452 TRACE("(%p)->(count=%u)\n",This,This->ref);
2454 return IShellFolder_AddRef((IShellFolder*)This);
2457 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2459 IShellViewImpl *This = impl_from_IViewObject(iface);
2461 TRACE("(%p)->(count=%u)\n",This,This->ref);
2463 return IShellFolder_Release((IShellFolder*)This);
2466 static HRESULT WINAPI ISVViewObject_Draw(
2467 IViewObject *iface,
2468 DWORD dwDrawAspect,
2469 LONG lindex,
2470 void* pvAspect,
2471 DVTARGETDEVICE* ptd,
2472 HDC hdcTargetDev,
2473 HDC hdcDraw,
2474 LPCRECTL lprcBounds,
2475 LPCRECTL lprcWBounds,
2476 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2477 ULONG_PTR dwContinue)
2480 IShellViewImpl *This = impl_from_IViewObject(iface);
2482 FIXME("Stub: This=%p\n",This);
2484 return E_NOTIMPL;
2486 static HRESULT WINAPI ISVViewObject_GetColorSet(
2487 IViewObject *iface,
2488 DWORD dwDrawAspect,
2489 LONG lindex,
2490 void *pvAspect,
2491 DVTARGETDEVICE* ptd,
2492 HDC hicTargetDevice,
2493 LOGPALETTE** ppColorSet)
2496 IShellViewImpl *This = impl_from_IViewObject(iface);
2498 FIXME("Stub: This=%p\n",This);
2500 return E_NOTIMPL;
2502 static HRESULT WINAPI ISVViewObject_Freeze(
2503 IViewObject *iface,
2504 DWORD dwDrawAspect,
2505 LONG lindex,
2506 void* pvAspect,
2507 DWORD* pdwFreeze)
2510 IShellViewImpl *This = impl_from_IViewObject(iface);
2512 FIXME("Stub: This=%p\n",This);
2514 return E_NOTIMPL;
2516 static HRESULT WINAPI ISVViewObject_Unfreeze(
2517 IViewObject *iface,
2518 DWORD dwFreeze)
2521 IShellViewImpl *This = impl_from_IViewObject(iface);
2523 FIXME("Stub: This=%p\n",This);
2525 return E_NOTIMPL;
2527 static HRESULT WINAPI ISVViewObject_SetAdvise(
2528 IViewObject *iface,
2529 DWORD aspects,
2530 DWORD advf,
2531 IAdviseSink* pAdvSink)
2534 IShellViewImpl *This = impl_from_IViewObject(iface);
2536 FIXME("partial stub: %p %08x %08x %p\n",
2537 This, aspects, advf, pAdvSink);
2539 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2540 This->pAdvSink = pAdvSink;
2541 This->dwAspects = aspects;
2542 This->dwAdvf = advf;
2544 return S_OK;
2547 static HRESULT WINAPI ISVViewObject_GetAdvise(
2548 IViewObject *iface,
2549 DWORD* pAspects,
2550 DWORD* pAdvf,
2551 IAdviseSink** ppAdvSink)
2554 IShellViewImpl *This = impl_from_IViewObject(iface);
2556 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2557 This, pAspects, pAdvf, ppAdvSink);
2559 if( ppAdvSink )
2561 IAdviseSink_AddRef( This->pAdvSink );
2562 *ppAdvSink = This->pAdvSink;
2564 if( pAspects )
2565 *pAspects = This->dwAspects;
2566 if( pAdvf )
2567 *pAdvf = This->dwAdvf;
2569 return S_OK;
2573 static const IViewObjectVtbl vovt =
2575 ISVViewObject_QueryInterface,
2576 ISVViewObject_AddRef,
2577 ISVViewObject_Release,
2578 ISVViewObject_Draw,
2579 ISVViewObject_GetColorSet,
2580 ISVViewObject_Freeze,
2581 ISVViewObject_Unfreeze,
2582 ISVViewObject_SetAdvise,
2583 ISVViewObject_GetAdvise