push a9ea98eed33411fd355fd4e8b78f7880f1dd09a3
[wine/hacks.git] / dlls / shell32 / shlview.c
blob832d49787c52a4493b430514bc7c0895dac85766
1 /*
2 * ShellView
4 * Copyright 1998,1999 <juergen.schmied@debitel.net>
6 * This is the view visualizing the data provided 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 * built according to the columns shown.
26 * FIXME: Load/Save the view state from/into the stream provided 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 = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
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 if(plvKeyDown->wVKey == VK_BACK)
1562 LPSHELLBROWSER lpSb;
1563 if((lpSb = (LPSHELLBROWSER)SendMessageW(This->hWndParent, CWM_GETISHELLBROWSER, 0, 0)))
1565 IShellBrowser_BrowseObject(lpSb, NULL, SBSP_PARENT);
1569 else
1570 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1572 break;
1574 default:
1575 TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1576 break;
1578 return 0;
1581 /**********************************************************
1582 * ShellView_OnChange()
1585 static LRESULT ShellView_OnChange(IShellViewImpl * This, const LPCITEMIDLIST * Pidls, LONG wEventId)
1588 TRACE("(%p)(%p,%p,0x%08x)\n", This, Pidls[0], Pidls[1], wEventId);
1589 switch(wEventId)
1591 case SHCNE_MKDIR:
1592 case SHCNE_CREATE:
1593 LV_AddItem(This, Pidls[0]);
1594 break;
1595 case SHCNE_RMDIR:
1596 case SHCNE_DELETE:
1597 LV_DeleteItem(This, Pidls[0]);
1598 break;
1599 case SHCNE_RENAMEFOLDER:
1600 case SHCNE_RENAMEITEM:
1601 LV_RenameItem(This, Pidls[0], Pidls[1]);
1602 break;
1603 case SHCNE_UPDATEITEM:
1604 break;
1606 return TRUE;
1608 /**********************************************************
1609 * ShellView_WndProc
1612 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1614 IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1615 LPCREATESTRUCTW lpcs;
1617 TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1619 switch (uMessage)
1621 case WM_NCCREATE:
1622 lpcs = (LPCREATESTRUCTW)lParam;
1623 pThis = (IShellViewImpl*)(lpcs->lpCreateParams);
1624 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1625 pThis->hWnd = hWnd; /*set the window handle*/
1626 break;
1628 case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1629 case WM_SETFOCUS: return ShellView_OnSetFocus(pThis);
1630 case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis);
1631 case WM_CREATE: return ShellView_OnCreate(pThis);
1632 case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1633 case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1634 case WM_COMMAND: return ShellView_OnCommand(pThis,
1635 GET_WM_COMMAND_ID(wParam, lParam),
1636 GET_WM_COMMAND_CMD(wParam, lParam),
1637 GET_WM_COMMAND_HWND(wParam, lParam));
1638 case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (const LPCITEMIDLIST*)wParam, (LONG)lParam);
1640 case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1641 return 0;
1643 case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
1644 break;
1646 case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0);
1648 case WM_DESTROY:
1649 RevokeDragDrop(pThis->hWnd);
1650 SHChangeNotifyDeregister(pThis->hNotify);
1651 break;
1653 case WM_ERASEBKGND:
1654 if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1655 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1656 return 1;
1657 break;
1660 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
1662 /**********************************************************
1665 * The INTERFACE of the IShellView object
1668 **********************************************************
1669 * IShellView_QueryInterface
1671 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj)
1673 IShellViewImpl *This = (IShellViewImpl *)iface;
1675 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1677 *ppvObj = NULL;
1679 if(IsEqualIID(riid, &IID_IUnknown))
1681 *ppvObj = This;
1683 else if(IsEqualIID(riid, &IID_IShellView))
1685 *ppvObj = (IShellView*)This;
1687 else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1689 *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget);
1691 else if(IsEqualIID(riid, &IID_IDropTarget))
1693 *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
1695 else if(IsEqualIID(riid, &IID_IDropSource))
1697 *ppvObj = (IDropSource*)&(This->lpvtblDropSource);
1699 else if(IsEqualIID(riid, &IID_IViewObject))
1701 *ppvObj = (IViewObject*)&(This->lpvtblViewObject);
1704 if(*ppvObj)
1706 IUnknown_AddRef( (IUnknown*)*ppvObj );
1707 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1708 return S_OK;
1710 TRACE("-- Interface: E_NOINTERFACE\n");
1711 return E_NOINTERFACE;
1714 /**********************************************************
1715 * IShellView_AddRef
1717 static ULONG WINAPI IShellView_fnAddRef(IShellView * iface)
1719 IShellViewImpl *This = (IShellViewImpl *)iface;
1720 ULONG refCount = InterlockedIncrement(&This->ref);
1722 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
1724 return refCount;
1726 /**********************************************************
1727 * IShellView_Release
1729 static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
1731 IShellViewImpl *This = (IShellViewImpl *)iface;
1732 ULONG refCount = InterlockedDecrement(&This->ref);
1734 TRACE("(%p)->(count=%i)\n", This, refCount + 1);
1736 if (!refCount)
1738 TRACE(" destroying IShellView(%p)\n",This);
1740 DestroyWindow(This->hWndList);
1742 if(This->pSFParent)
1743 IShellFolder_Release(This->pSFParent);
1745 if(This->pSF2Parent)
1746 IShellFolder2_Release(This->pSF2Parent);
1748 SHFree(This->apidl);
1750 if(This->pAdvSink)
1751 IAdviseSink_Release(This->pAdvSink);
1753 HeapFree(GetProcessHeap(),0,This);
1755 return refCount;
1758 /**********************************************************
1759 * ShellView_GetWindow
1761 static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd)
1763 IShellViewImpl *This = (IShellViewImpl *)iface;
1765 TRACE("(%p)\n",This);
1767 *phWnd = This->hWnd;
1769 return S_OK;
1772 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode)
1774 IShellViewImpl *This = (IShellViewImpl *)iface;
1776 FIXME("(%p) stub\n",This);
1778 return E_NOTIMPL;
1781 /**********************************************************
1782 * IShellView_TranslateAccelerator
1784 * FIXME:
1785 * use the accel functions
1787 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg)
1789 #if 0
1790 IShellViewImpl *This = (IShellViewImpl *)iface;
1792 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1793 #endif
1795 if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1797 TRACE("-- key=0x04%lx\n",lpmsg->wParam) ;
1799 return S_FALSE; /* not handled */
1802 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable)
1804 IShellViewImpl *This = (IShellViewImpl *)iface;
1806 FIXME("(%p) stub\n",This);
1808 return E_NOTIMPL;
1811 static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState)
1813 IShellViewImpl *This = (IShellViewImpl *)iface;
1816 CHAR szName[MAX_PATH];
1818 LRESULT lResult;
1819 int nPartArray[1] = {-1};
1821 TRACE("(%p)->(state=%x) stub\n",This, uState);
1823 /*don't do anything if the state isn't really changing*/
1824 if(This->uState == uState)
1826 return S_OK;
1829 /*OnActivate handles the menu merging and internal state*/
1830 ShellView_OnActivate(This, uState);
1832 /*only do This if we are active*/
1833 if(uState != SVUIA_DEACTIVATE)
1837 GetFolderPath is not a method of IShellFolder
1838 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1840 /* set the number of parts */
1841 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1842 (LPARAM)nPartArray, &lResult);
1844 /* set the text for the parts */
1846 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1847 0, (LPARAM)szName, &lResult);
1851 return S_OK;
1854 static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface)
1856 IShellViewImpl *This = (IShellViewImpl *)iface;
1858 TRACE("(%p)\n",This);
1860 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
1861 ShellView_FillList(This);
1863 return S_OK;
1866 static HRESULT WINAPI IShellView_fnCreateViewWindow(
1867 IShellView * iface,
1868 IShellView *lpPrevView,
1869 LPCFOLDERSETTINGS lpfs,
1870 IShellBrowser * psb,
1871 RECT * prcView,
1872 HWND *phWnd)
1874 IShellViewImpl *This = (IShellViewImpl *)iface;
1876 WNDCLASSW wc;
1877 *phWnd = 0;
1880 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd);
1881 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);
1883 /*set up the member variables*/
1884 This->pShellBrowser = psb;
1885 This->FolderSettings = *lpfs;
1887 /*get our parent window*/
1888 IShellBrowser_AddRef(This->pShellBrowser);
1889 IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
1891 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1892 This->pCommDlgBrowser=NULL;
1893 if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser,
1894 (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser)))
1896 TRACE("-- CommDlgBrowser\n");
1899 /*if our window class has not been registered, then do so*/
1900 if(!GetClassInfoW(shell32_hInstance, SV_CLASS_NAME, &wc))
1902 ZeroMemory(&wc, sizeof(wc));
1903 wc.style = CS_HREDRAW | CS_VREDRAW;
1904 wc.lpfnWndProc = ShellView_WndProc;
1905 wc.cbClsExtra = 0;
1906 wc.cbWndExtra = 0;
1907 wc.hInstance = shell32_hInstance;
1908 wc.hIcon = 0;
1909 wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
1910 wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
1911 wc.lpszMenuName = NULL;
1912 wc.lpszClassName = SV_CLASS_NAME;
1914 if(!RegisterClassW(&wc))
1915 return E_FAIL;
1918 *phWnd = CreateWindowExW(0,
1919 SV_CLASS_NAME,
1920 NULL,
1921 WS_CHILD | WS_TABSTOP,
1922 prcView->left,
1923 prcView->top,
1924 prcView->right - prcView->left,
1925 prcView->bottom - prcView->top,
1926 This->hWndParent,
1928 shell32_hInstance,
1929 (LPVOID)This);
1931 CheckToolbar(This);
1933 if(!*phWnd) return E_FAIL;
1935 SetWindowPos(*phWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
1936 UpdateWindow(*phWnd);
1938 return S_OK;
1941 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
1943 IShellViewImpl *This = (IShellViewImpl *)iface;
1945 TRACE("(%p)\n",This);
1947 /*Make absolutely sure all our UI is cleaned up.*/
1948 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1950 if(This->hMenu)
1952 DestroyMenu(This->hMenu);
1955 DestroyWindow(This->hWnd);
1956 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1957 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1960 return S_OK;
1963 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs)
1965 IShellViewImpl *This = (IShellViewImpl *)iface;
1967 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1968 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1970 if (!lpfs) return E_INVALIDARG;
1972 *lpfs = This->FolderSettings;
1973 return NOERROR;
1976 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1978 IShellViewImpl *This = (IShellViewImpl *)iface;
1980 FIXME("(%p) stub\n",This);
1982 return E_NOTIMPL;
1985 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface)
1987 IShellViewImpl *This = (IShellViewImpl *)iface;
1989 FIXME("(%p) stub\n",This);
1991 return S_OK;
1994 static HRESULT WINAPI IShellView_fnSelectItem(
1995 IShellView * iface,
1996 LPCITEMIDLIST pidl,
1997 UINT uFlags)
1999 IShellViewImpl *This = (IShellViewImpl *)iface;
2000 int i;
2002 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
2004 i = LV_FindItemByPidl(This, pidl);
2006 if (i != -1)
2008 LVITEMW lvItem;
2010 if(uFlags & SVSI_ENSUREVISIBLE)
2011 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
2013 lvItem.mask = LVIF_STATE;
2014 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
2015 lvItem.iItem = 0;
2016 lvItem.iSubItem = 0;
2018 while(SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem))
2020 if (lvItem.iItem == i)
2022 if (uFlags & SVSI_SELECT)
2023 lvItem.state |= LVIS_SELECTED;
2024 else
2025 lvItem.state &= ~LVIS_SELECTED;
2027 if(uFlags & SVSI_FOCUSED)
2028 lvItem.state &= ~LVIS_FOCUSED;
2030 else
2032 if (uFlags & SVSI_DESELECTOTHERS)
2033 lvItem.state &= ~LVIS_SELECTED;
2035 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
2036 lvItem.iItem++;
2040 if(uFlags & SVSI_EDIT)
2041 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
2044 return S_OK;
2047 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
2049 IShellViewImpl *This = (IShellViewImpl *)iface;
2051 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2053 *ppvOut = NULL;
2055 switch(uItem)
2057 case SVGIO_BACKGROUND:
2058 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2059 break;
2061 case SVGIO_SELECTION:
2062 ShellView_GetSelections(This);
2063 IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2064 break;
2066 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2068 if(!*ppvOut) return E_OUTOFMEMORY;
2070 return S_OK;
2073 static const IShellViewVtbl svvt =
2075 IShellView_fnQueryInterface,
2076 IShellView_fnAddRef,
2077 IShellView_fnRelease,
2078 IShellView_fnGetWindow,
2079 IShellView_fnContextSensitiveHelp,
2080 IShellView_fnTranslateAccelerator,
2081 IShellView_fnEnableModeless,
2082 IShellView_fnUIActivate,
2083 IShellView_fnRefresh,
2084 IShellView_fnCreateViewWindow,
2085 IShellView_fnDestroyViewWindow,
2086 IShellView_fnGetCurrentInfo,
2087 IShellView_fnAddPropertySheetPages,
2088 IShellView_fnSaveViewState,
2089 IShellView_fnSelectItem,
2090 IShellView_fnGetItemObject
2094 /**********************************************************
2095 * ISVOleCmdTarget_QueryInterface (IUnknown)
2097 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2098 IOleCommandTarget * iface,
2099 REFIID iid,
2100 LPVOID* ppvObj)
2102 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2104 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2107 /**********************************************************
2108 * ISVOleCmdTarget_AddRef (IUnknown)
2110 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2111 IOleCommandTarget * iface)
2113 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2115 return IShellFolder_AddRef((IShellFolder*)This);
2118 /**********************************************************
2119 * ISVOleCmdTarget_Release (IUnknown)
2121 static ULONG WINAPI ISVOleCmdTarget_Release(
2122 IOleCommandTarget * iface)
2124 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2126 return IShellFolder_Release((IShellFolder*)This);
2129 /**********************************************************
2130 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2132 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2133 IOleCommandTarget *iface,
2134 const GUID* pguidCmdGroup,
2135 ULONG cCmds,
2136 OLECMD * prgCmds,
2137 OLECMDTEXT* pCmdText)
2139 UINT i;
2140 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2142 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2143 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2145 if (!prgCmds)
2146 return E_POINTER;
2147 for (i = 0; i < cCmds; i++)
2149 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2150 prgCmds[i].cmdf = 0;
2152 return OLECMDERR_E_UNKNOWNGROUP;
2155 /**********************************************************
2156 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2158 * nCmdID is the OLECMDID_* enumeration
2160 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2161 IOleCommandTarget *iface,
2162 const GUID* pguidCmdGroup,
2163 DWORD nCmdID,
2164 DWORD nCmdexecopt,
2165 VARIANT* pvaIn,
2166 VARIANT* pvaOut)
2168 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2170 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2171 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2173 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2174 (nCmdID == 0x29) &&
2175 (nCmdexecopt == 4) && pvaOut)
2176 return S_OK;
2177 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2178 (nCmdID == 9) &&
2179 (nCmdexecopt == 0))
2180 return 1;
2182 return OLECMDERR_E_UNKNOWNGROUP;
2185 static const IOleCommandTargetVtbl ctvt =
2187 ISVOleCmdTarget_QueryInterface,
2188 ISVOleCmdTarget_AddRef,
2189 ISVOleCmdTarget_Release,
2190 ISVOleCmdTarget_QueryStatus,
2191 ISVOleCmdTarget_Exec
2194 /**********************************************************
2195 * ISVDropTarget implementation
2198 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2199 IDropTarget *iface,
2200 REFIID riid,
2201 LPVOID *ppvObj)
2203 IShellViewImpl *This = impl_from_IDropTarget(iface);
2205 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2207 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2210 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2212 IShellViewImpl *This = impl_from_IDropTarget(iface);
2214 TRACE("(%p)->(count=%u)\n",This,This->ref);
2216 return IShellFolder_AddRef((IShellFolder*)This);
2219 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2221 IShellViewImpl *This = impl_from_IDropTarget(iface);
2223 TRACE("(%p)->(count=%u)\n",This,This->ref);
2225 return IShellFolder_Release((IShellFolder*)This);
2228 /******************************************************************************
2229 * drag_notify_subitem [Internal]
2231 * Figure out the shellfolder object, which is currently under the mouse cursor
2232 * and notify it via the IDropTarget interface.
2235 #define SCROLLAREAWIDTH 20
2237 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2238 DWORD *pdwEffect)
2240 LVHITTESTINFO htinfo;
2241 LVITEMW lvItem;
2242 LONG lResult;
2243 HRESULT hr;
2244 RECT clientRect;
2246 /* Map from global to client coordinates and query the index of the listview-item, which is
2247 * currently under the mouse cursor. */
2248 htinfo.pt.x = pt.x;
2249 htinfo.pt.y = pt.y;
2250 htinfo.flags = LVHT_ONITEM;
2251 ScreenToClient(This->hWndList, &htinfo.pt);
2252 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2254 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2255 GetClientRect(This->hWndList, &clientRect);
2256 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2257 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2258 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2260 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2261 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2262 if (htinfo.pt.x < SCROLLAREAWIDTH)
2263 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2264 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2265 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2266 if (htinfo.pt.y < SCROLLAREAWIDTH)
2267 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2268 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2269 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2271 } else {
2272 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2274 This->ptLastMousePos = htinfo.pt;
2276 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2277 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2278 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2280 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2281 if (This->pCurDropTarget) {
2282 IDropTarget_DragLeave(This->pCurDropTarget);
2283 IDropTarget_Release(This->pCurDropTarget);
2284 This->pCurDropTarget = NULL;
2287 This->iDragOverItem = lResult;
2288 if (lResult == -1) {
2289 /* We are not above one of the listview's subitems. Bind to the parent folder's
2290 * DropTarget interface. */
2291 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2292 (LPVOID*)&This->pCurDropTarget);
2293 } else {
2294 /* Query the relative PIDL of the shellfolder object represented by the currently
2295 * dragged over listview-item ... */
2296 lvItem.mask = LVIF_PARAM;
2297 lvItem.iItem = lResult;
2298 lvItem.iSubItem = 0;
2299 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
2301 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2302 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2303 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2306 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2307 if (FAILED(hr))
2308 return hr;
2310 /* Notify the item just entered via DragEnter. */
2311 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2314 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2315 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2317 IShellViewImpl *This = impl_from_IDropTarget(iface);
2319 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2320 This->pCurDataObject = pDataObject;
2321 IDataObject_AddRef(pDataObject);
2323 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2326 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2327 DWORD *pdwEffect)
2329 IShellViewImpl *This = impl_from_IDropTarget(iface);
2330 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2333 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2334 IShellViewImpl *This = impl_from_IDropTarget(iface);
2336 IDropTarget_DragLeave(This->pCurDropTarget);
2338 IDropTarget_Release(This->pCurDropTarget);
2339 IDataObject_Release(This->pCurDataObject);
2340 This->pCurDataObject = NULL;
2341 This->pCurDropTarget = NULL;
2342 This->iDragOverItem = 0;
2344 return S_OK;
2347 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2348 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2350 IShellViewImpl *This = impl_from_IDropTarget(iface);
2352 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2354 IDropTarget_Release(This->pCurDropTarget);
2355 IDataObject_Release(This->pCurDataObject);
2356 This->pCurDataObject = NULL;
2357 This->pCurDropTarget = NULL;
2358 This->iDragOverItem = 0;
2360 return S_OK;
2363 static const IDropTargetVtbl dtvt =
2365 ISVDropTarget_QueryInterface,
2366 ISVDropTarget_AddRef,
2367 ISVDropTarget_Release,
2368 ISVDropTarget_DragEnter,
2369 ISVDropTarget_DragOver,
2370 ISVDropTarget_DragLeave,
2371 ISVDropTarget_Drop
2374 /**********************************************************
2375 * ISVDropSource implementation
2378 static HRESULT WINAPI ISVDropSource_QueryInterface(
2379 IDropSource *iface,
2380 REFIID riid,
2381 LPVOID *ppvObj)
2383 IShellViewImpl *This = impl_from_IDropSource(iface);
2385 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2387 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2390 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2392 IShellViewImpl *This = impl_from_IDropSource(iface);
2394 TRACE("(%p)->(count=%u)\n",This,This->ref);
2396 return IShellFolder_AddRef((IShellFolder*)This);
2399 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2401 IShellViewImpl *This = impl_from_IDropSource(iface);
2403 TRACE("(%p)->(count=%u)\n",This,This->ref);
2405 return IShellFolder_Release((IShellFolder*)This);
2407 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2408 IDropSource *iface,
2409 BOOL fEscapePressed,
2410 DWORD grfKeyState)
2412 IShellViewImpl *This = impl_from_IDropSource(iface);
2413 TRACE("(%p)\n",This);
2415 if (fEscapePressed)
2416 return DRAGDROP_S_CANCEL;
2417 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2418 return DRAGDROP_S_DROP;
2419 else
2420 return NOERROR;
2423 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2424 IDropSource *iface,
2425 DWORD dwEffect)
2427 IShellViewImpl *This = impl_from_IDropSource(iface);
2428 TRACE("(%p)\n",This);
2430 return DRAGDROP_S_USEDEFAULTCURSORS;
2433 static const IDropSourceVtbl dsvt =
2435 ISVDropSource_QueryInterface,
2436 ISVDropSource_AddRef,
2437 ISVDropSource_Release,
2438 ISVDropSource_QueryContinueDrag,
2439 ISVDropSource_GiveFeedback
2441 /**********************************************************
2442 * ISVViewObject implementation
2445 static HRESULT WINAPI ISVViewObject_QueryInterface(
2446 IViewObject *iface,
2447 REFIID riid,
2448 LPVOID *ppvObj)
2450 IShellViewImpl *This = impl_from_IViewObject(iface);
2452 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2454 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2457 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2459 IShellViewImpl *This = impl_from_IViewObject(iface);
2461 TRACE("(%p)->(count=%u)\n",This,This->ref);
2463 return IShellFolder_AddRef((IShellFolder*)This);
2466 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2468 IShellViewImpl *This = impl_from_IViewObject(iface);
2470 TRACE("(%p)->(count=%u)\n",This,This->ref);
2472 return IShellFolder_Release((IShellFolder*)This);
2475 static HRESULT WINAPI ISVViewObject_Draw(
2476 IViewObject *iface,
2477 DWORD dwDrawAspect,
2478 LONG lindex,
2479 void* pvAspect,
2480 DVTARGETDEVICE* ptd,
2481 HDC hdcTargetDev,
2482 HDC hdcDraw,
2483 LPCRECTL lprcBounds,
2484 LPCRECTL lprcWBounds,
2485 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2486 ULONG_PTR dwContinue)
2489 IShellViewImpl *This = impl_from_IViewObject(iface);
2491 FIXME("Stub: This=%p\n",This);
2493 return E_NOTIMPL;
2495 static HRESULT WINAPI ISVViewObject_GetColorSet(
2496 IViewObject *iface,
2497 DWORD dwDrawAspect,
2498 LONG lindex,
2499 void *pvAspect,
2500 DVTARGETDEVICE* ptd,
2501 HDC hicTargetDevice,
2502 LOGPALETTE** ppColorSet)
2505 IShellViewImpl *This = impl_from_IViewObject(iface);
2507 FIXME("Stub: This=%p\n",This);
2509 return E_NOTIMPL;
2511 static HRESULT WINAPI ISVViewObject_Freeze(
2512 IViewObject *iface,
2513 DWORD dwDrawAspect,
2514 LONG lindex,
2515 void* pvAspect,
2516 DWORD* pdwFreeze)
2519 IShellViewImpl *This = impl_from_IViewObject(iface);
2521 FIXME("Stub: This=%p\n",This);
2523 return E_NOTIMPL;
2525 static HRESULT WINAPI ISVViewObject_Unfreeze(
2526 IViewObject *iface,
2527 DWORD dwFreeze)
2530 IShellViewImpl *This = impl_from_IViewObject(iface);
2532 FIXME("Stub: This=%p\n",This);
2534 return E_NOTIMPL;
2536 static HRESULT WINAPI ISVViewObject_SetAdvise(
2537 IViewObject *iface,
2538 DWORD aspects,
2539 DWORD advf,
2540 IAdviseSink* pAdvSink)
2543 IShellViewImpl *This = impl_from_IViewObject(iface);
2545 FIXME("partial stub: %p %08x %08x %p\n",
2546 This, aspects, advf, pAdvSink);
2548 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2549 This->pAdvSink = pAdvSink;
2550 This->dwAspects = aspects;
2551 This->dwAdvf = advf;
2553 return S_OK;
2556 static HRESULT WINAPI ISVViewObject_GetAdvise(
2557 IViewObject *iface,
2558 DWORD* pAspects,
2559 DWORD* pAdvf,
2560 IAdviseSink** ppAdvSink)
2563 IShellViewImpl *This = impl_from_IViewObject(iface);
2565 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2566 This, pAspects, pAdvf, ppAdvSink);
2568 if( ppAdvSink )
2570 IAdviseSink_AddRef( This->pAdvSink );
2571 *ppAdvSink = This->pAdvSink;
2573 if( pAspects )
2574 *pAspects = This->dwAspects;
2575 if( pAdvf )
2576 *pAdvf = This->dwAdvf;
2578 return S_OK;
2582 static const IViewObjectVtbl vovt =
2584 ISVViewObject_QueryInterface,
2585 ISVViewObject_AddRef,
2586 ISVViewObject_Release,
2587 ISVViewObject_Draw,
2588 ISVViewObject_GetColorSet,
2589 ISVViewObject_Freeze,
2590 ISVViewObject_Unfreeze,
2591 ISVViewObject_SetAdvise,
2592 ISVViewObject_GetAdvise