push bd0608bf727e2241b2885edad5c5c753477ffd22
[wine/hacks.git] / dlls / shell32 / shlview.c
blob810c493a2679ff1d9668b76a29c350dbe8ad81ed
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 _InsertMenuItem(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
772 _InsertMenuItem(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, "dummy45", MFS_ENABLED);
775 TRACE("--\n");
778 /**********************************************************
779 * ShellView_MergeViewMenu()
782 static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu)
784 TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
786 if(hSubMenu)
787 { /*add a separator at the correct position in the menu*/
788 MENUITEMINFOA mii;
789 static char view[] = "View";
791 _InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
793 ZeroMemory(&mii, sizeof(mii));
794 mii.cbSize = sizeof(mii);
795 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
796 mii.fType = MFT_STRING;
797 mii.dwTypeData = view;
798 mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
799 InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
803 /**********************************************************
804 * ShellView_GetSelections()
806 * - fills the this->apidl list with the selected objects
808 * RETURNS
809 * number of selected items
811 static UINT ShellView_GetSelections(IShellViewImpl * This)
813 LVITEMW lvItem;
814 UINT i = 0;
816 SHFree(This->apidl);
818 This->cidl = ListView_GetSelectedCount(This->hWndList);
819 This->apidl = (LPITEMIDLIST*)SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
821 TRACE("selected=%i\n", This->cidl);
823 if(This->apidl)
825 TRACE("-- Items selected =%u\n", This->cidl);
827 lvItem.mask = LVIF_STATE | LVIF_PARAM;
828 lvItem.stateMask = LVIS_SELECTED;
829 lvItem.iItem = 0;
830 lvItem.iSubItem = 0;
832 while(ListView_GetItemW(This->hWndList, &lvItem) && (i < This->cidl))
834 if(lvItem.state & LVIS_SELECTED)
836 This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
837 i++;
838 TRACE("-- selected Item found\n");
840 lvItem.iItem++;
843 return This->cidl;
847 /**********************************************************
848 * ShellView_OpenSelectedItems()
850 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
852 static UINT CF_IDLIST = 0;
853 HRESULT hr;
854 IDataObject* selection;
855 FORMATETC fetc;
856 STGMEDIUM stgm;
857 LPIDA pIDList;
858 LPCITEMIDLIST parent_pidl;
859 WCHAR parent_path[MAX_PATH];
860 LPCWSTR parent_dir = NULL;
861 SFGAOF attribs;
862 int i;
864 if (0 == ShellView_GetSelections(This))
866 return S_OK;
868 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
869 (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
870 0, (LPVOID *)&selection);
871 if (FAILED(hr))
872 return hr;
874 if (0 == CF_IDLIST)
876 CF_IDLIST = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
878 fetc.cfFormat = CF_IDLIST;
879 fetc.ptd = NULL;
880 fetc.dwAspect = DVASPECT_CONTENT;
881 fetc.lindex = -1;
882 fetc.tymed = TYMED_HGLOBAL;
884 hr = IDataObject_QueryGetData(selection, &fetc);
885 if (FAILED(hr))
886 return hr;
888 hr = IDataObject_GetData(selection, &fetc, &stgm);
889 if (FAILED(hr))
890 return hr;
892 pIDList = GlobalLock(stgm.u.hGlobal);
894 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
895 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &parent_pidl, &attribs);
896 if (SUCCEEDED(hr) && (attribs & SFGAO_FILESYSTEM) &&
897 SHGetPathFromIDListW(parent_pidl, parent_path))
899 parent_dir = parent_path;
902 for (i = pIDList->cidl; i > 0; --i)
904 LPCITEMIDLIST pidl;
906 pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
908 attribs = SFGAO_FOLDER;
909 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
911 if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
913 SHELLEXECUTEINFOW shexinfo;
915 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
916 shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */
917 shexinfo.hwnd = NULL;
918 shexinfo.lpVerb = NULL;
919 shexinfo.lpFile = NULL;
920 shexinfo.lpParameters = NULL;
921 shexinfo.lpDirectory = parent_dir;
922 shexinfo.nShow = SW_NORMAL;
923 shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
925 ShellExecuteExW(&shexinfo); /* Discard error/success info */
927 ILFree((LPITEMIDLIST)shexinfo.lpIDList);
931 GlobalUnlock(stgm.u.hGlobal);
932 ReleaseStgMedium(&stgm);
934 IDataObject_Release(selection);
936 return S_OK;
939 /**********************************************************
940 * ShellView_DoContextMenu()
942 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
943 { UINT uCommand;
944 DWORD wFlags;
945 HMENU hMenu;
946 BOOL fExplore = FALSE;
947 HWND hwndTree = 0;
948 LPCONTEXTMENU pContextMenu = NULL;
949 IContextMenu2 *pCM = NULL;
950 CMINVOKECOMMANDINFO cmi;
952 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
954 /* look, what's selected and create a context menu object of it*/
955 if( ShellView_GetSelections(This) )
957 IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
958 (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
960 if(pContextMenu)
962 TRACE("-- pContextMenu\n");
963 hMenu = CreatePopupMenu();
965 if( hMenu )
967 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
968 if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
970 TRACE("-- explore mode\n");
971 fExplore = TRUE;
974 /* build the flags depending on what we can do with the selected item */
975 wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
977 /* let the ContextMenu merge its items in */
978 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
980 if (This->FolderSettings.fFlags & FWF_DESKTOP)
981 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
983 if( bDefault )
985 TRACE("-- get menu default command\n");
986 uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
988 else
990 TRACE("-- track popup\n");
991 uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
994 if(uCommand > 0)
996 TRACE("-- uCommand=%u\n", uCommand);
997 if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
999 TRACE("-- dlg: OnDefaultCommand\n");
1000 if (OnDefaultCommand(This) != S_OK)
1002 ShellView_OpenSelectedItems(This);
1005 else
1007 TRACE("-- explore -- invoke command\n");
1008 ZeroMemory(&cmi, sizeof(cmi));
1009 cmi.cbSize = sizeof(cmi);
1010 cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
1011 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1012 IContextMenu_InvokeCommand(pContextMenu, &cmi);
1015 DestroyMenu(hMenu);
1018 if (pContextMenu)
1019 IContextMenu_Release(pContextMenu);
1022 else /* background context menu */
1024 hMenu = CreatePopupMenu();
1026 pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
1027 IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1029 uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1030 DestroyMenu(hMenu);
1032 TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1034 ZeroMemory(&cmi, sizeof(cmi));
1035 cmi.cbSize = sizeof(cmi);
1036 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1037 cmi.hwnd = This->hWndParent;
1038 IContextMenu2_InvokeCommand(pCM, &cmi);
1040 IContextMenu2_Release(pCM);
1044 /**********************************************************
1045 * ##### message handling #####
1048 /**********************************************************
1049 * ShellView_OnSize()
1051 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1053 TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1055 /*resize the ListView to fit our window*/
1056 if(This->hWndList)
1058 MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1061 return S_OK;
1063 /**********************************************************
1064 * ShellView_OnDeactivate()
1066 * NOTES
1067 * internal
1069 static void ShellView_OnDeactivate(IShellViewImpl * This)
1071 TRACE("%p\n",This);
1073 if(This->uState != SVUIA_DEACTIVATE)
1075 if(This->hMenu)
1077 IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1078 IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1079 DestroyMenu(This->hMenu);
1080 This->hMenu = 0;
1083 This->uState = SVUIA_DEACTIVATE;
1087 /**********************************************************
1088 * ShellView_OnActivate()
1090 static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState)
1091 { OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} };
1092 MENUITEMINFOA mii;
1093 CHAR szText[MAX_PATH];
1095 TRACE("%p uState=%x\n",This,uState);
1097 /*don't do anything if the state isn't really changing */
1098 if(This->uState == uState)
1100 return S_OK;
1103 ShellView_OnDeactivate(This);
1105 /*only do This if we are active */
1106 if(uState != SVUIA_DEACTIVATE)
1108 /*merge the menus */
1109 This->hMenu = CreateMenu();
1111 if(This->hMenu)
1113 IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1114 TRACE("-- after fnInsertMenusSB\n");
1116 /*build the top level menu get the menu item's text*/
1117 strcpy(szText,"dummy 31");
1119 ZeroMemory(&mii, sizeof(mii));
1120 mii.cbSize = sizeof(mii);
1121 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1122 mii.fType = MFT_STRING;
1123 mii.fState = MFS_ENABLED;
1124 mii.dwTypeData = szText;
1125 mii.hSubMenu = ShellView_BuildFileMenu(This);
1127 /*insert our menu into the menu bar*/
1128 if(mii.hSubMenu)
1130 InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1133 /*get the view menu so we can merge with it*/
1134 ZeroMemory(&mii, sizeof(mii));
1135 mii.cbSize = sizeof(mii);
1136 mii.fMask = MIIM_SUBMENU;
1138 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1140 ShellView_MergeViewMenu(This, mii.hSubMenu);
1143 /*add the items that should only be added if we have the focus*/
1144 if(SVUIA_ACTIVATE_FOCUS == uState)
1146 /*get the file menu so we can merge with it */
1147 ZeroMemory(&mii, sizeof(mii));
1148 mii.cbSize = sizeof(mii);
1149 mii.fMask = MIIM_SUBMENU;
1151 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1153 ShellView_MergeFileMenu(This, mii.hSubMenu);
1156 TRACE("-- before fnSetMenuSB\n");
1157 IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1160 This->uState = uState;
1161 TRACE("--\n");
1162 return S_OK;
1165 /**********************************************************
1166 * ShellView_OnSetFocus()
1169 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1171 TRACE("%p\n",This);
1173 /* Tell the browser one of our windows has received the focus. This
1174 should always be done before merging menus (OnActivate merges the
1175 menus) if one of our windows has the focus.*/
1177 IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1178 ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1180 /* Set the focus to the listview */
1181 SetFocus(This->hWndList);
1183 /* Notify the ICommDlgBrowser interface */
1184 OnStateChange(This,CDBOSC_SETFOCUS);
1186 return 0;
1189 /**********************************************************
1190 * ShellView_OnKillFocus()
1192 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1194 TRACE("(%p) stub\n",This);
1196 ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1197 /* Notify the ICommDlgBrowser */
1198 OnStateChange(This,CDBOSC_KILLFOCUS);
1200 return 0;
1203 /**********************************************************
1204 * ShellView_OnCommand()
1206 * NOTES
1207 * the CmdID's are the ones from the context menu
1209 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1211 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1213 switch(dwCmdID)
1215 case FCIDM_SHVIEW_SMALLICON:
1216 This->FolderSettings.ViewMode = FVM_SMALLICON;
1217 SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1218 CheckToolbar(This);
1219 break;
1221 case FCIDM_SHVIEW_BIGICON:
1222 This->FolderSettings.ViewMode = FVM_ICON;
1223 SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1224 CheckToolbar(This);
1225 break;
1227 case FCIDM_SHVIEW_LISTVIEW:
1228 This->FolderSettings.ViewMode = FVM_LIST;
1229 SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1230 CheckToolbar(This);
1231 break;
1233 case FCIDM_SHVIEW_REPORTVIEW:
1234 This->FolderSettings.ViewMode = FVM_DETAILS;
1235 SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1236 CheckToolbar(This);
1237 break;
1239 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1240 case 0x30:
1241 case 0x31:
1242 case 0x32:
1243 case 0x33:
1244 This->ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30);
1245 This->ListViewSortInfo.bIsAscending = TRUE;
1246 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1247 SendMessageA(This->hWndList, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1248 break;
1250 default:
1251 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID);
1253 return 0;
1256 /**********************************************************
1257 * ShellView_OnNotify()
1260 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1261 { LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1262 NMLVDISPINFOW *lpdi = (NMLVDISPINFOW *)lpnmh;
1263 LPITEMIDLIST pidl;
1265 TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1267 switch(lpnmh->code)
1269 case NM_SETFOCUS:
1270 TRACE("-- NM_SETFOCUS %p\n",This);
1271 ShellView_OnSetFocus(This);
1272 break;
1274 case NM_KILLFOCUS:
1275 TRACE("-- NM_KILLFOCUS %p\n",This);
1276 ShellView_OnDeactivate(This);
1277 /* Notify the ICommDlgBrowser interface */
1278 OnStateChange(This,CDBOSC_KILLFOCUS);
1279 break;
1281 case NM_CUSTOMDRAW:
1282 TRACE("-- NM_CUSTOMDRAW %p\n",This);
1283 return CDRF_DODEFAULT;
1285 case NM_RELEASEDCAPTURE:
1286 TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1287 break;
1289 case NM_CLICK:
1290 TRACE("-- NM_CLICK %p\n",This);
1291 break;
1293 case NM_RCLICK:
1294 TRACE("-- NM_RCLICK %p\n",This);
1295 break;
1297 case NM_DBLCLK:
1298 TRACE("-- NM_DBLCLK %p\n",This);
1299 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1300 break;
1302 case NM_RETURN:
1303 TRACE("-- NM_DBLCLK %p\n",This);
1304 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1305 break;
1307 case HDN_ENDTRACKW:
1308 TRACE("-- HDN_ENDTRACKW %p\n",This);
1309 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1310 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1311 break;
1313 case LVN_DELETEITEM:
1314 TRACE("-- LVN_DELETEITEM %p\n",This);
1315 SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/
1316 break;
1318 case LVN_DELETEALLITEMS:
1319 TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1320 return FALSE;
1322 case LVN_INSERTITEM:
1323 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1324 break;
1326 case LVN_ITEMACTIVATE:
1327 TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1328 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1329 break;
1331 case LVN_COLUMNCLICK:
1332 This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1333 if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1335 This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1337 else
1339 This->ListViewSortInfo.bIsAscending = TRUE;
1341 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1343 SendMessageW(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1344 break;
1346 case LVN_GETDISPINFOA:
1347 case LVN_GETDISPINFOW:
1348 TRACE("-- LVN_GETDISPINFO %p\n",This);
1349 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1351 if(lpdi->item.mask & LVIF_TEXT) /* text requested */
1353 if (This->pSF2Parent)
1355 SHELLDETAILS sd;
1356 IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1357 if (lpnmh->code == LVN_GETDISPINFOA)
1359 /* shouldn't happen */
1360 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1361 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1362 TRACE("-- text=%s\n",lpdiA->item.pszText);
1364 else /* LVN_GETDISPINFOW */
1366 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1367 TRACE("-- text=%s\n",debugstr_w(lpdi->item.pszText));
1370 else
1372 FIXME("no SF2\n");
1375 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1377 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1379 break;
1381 case LVN_ITEMCHANGED:
1382 TRACE("-- LVN_ITEMCHANGED %p\n",This);
1383 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1384 break;
1386 case LVN_BEGINDRAG:
1387 case LVN_BEGINRDRAG:
1388 TRACE("-- LVN_BEGINDRAG\n");
1390 if (ShellView_GetSelections(This))
1392 IDataObject * pda;
1393 DWORD dwAttributes = SFGAO_CANLINK;
1394 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1396 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1398 IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource); /* own DropSource interface */
1400 if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1402 if (dwAttributes & SFGAO_CANLINK)
1404 dwEffect |= DROPEFFECT_LINK;
1408 if (pds)
1410 DWORD dwEffect;
1411 DoDragDrop(pda, pds, dwEffect, &dwEffect);
1413 IDataObject_Release(pda);
1416 break;
1418 case LVN_BEGINLABELEDITW:
1420 DWORD dwAttr = SFGAO_CANRENAME;
1421 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1423 TRACE("-- LVN_BEGINLABELEDITA %p\n",This);
1425 IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1426 if (SFGAO_CANRENAME & dwAttr)
1428 return FALSE;
1430 return TRUE;
1433 case LVN_ENDLABELEDITW:
1435 TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1436 if (lpdi->item.pszText)
1438 HRESULT hr;
1439 LVITEMW lvItem;
1441 lvItem.iItem = lpdi->item.iItem;
1442 lvItem.iSubItem = 0;
1443 lvItem.mask = LVIF_PARAM;
1444 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
1446 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1447 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidl);
1449 if(SUCCEEDED(hr) && pidl)
1451 lvItem.mask = LVIF_PARAM;
1452 lvItem.lParam = (LPARAM)pidl;
1453 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
1454 return TRUE;
1457 return FALSE;
1460 case LVN_KEYDOWN:
1462 /* MSG msg;
1463 msg.hwnd = This->hWnd;
1464 msg.message = WM_KEYDOWN;
1465 msg.wParam = plvKeyDown->wVKey;
1466 msg.lParam = 0;
1467 msg.time = 0;
1468 msg.pt = 0;*/
1470 LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1472 /* initiate a rename of the selected file or directory */
1473 if(plvKeyDown->wVKey == VK_F2)
1475 /* see how many files are selected */
1476 int i = ListView_GetSelectedCount(This->hWndList);
1478 /* get selected item */
1479 if(i == 1)
1481 /* get selected item */
1482 i = ListView_GetNextItem(This->hWndList, -1,
1483 LVNI_SELECTED);
1485 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1486 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
1489 #if 0
1490 TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1491 #endif
1492 else if(plvKeyDown->wVKey == VK_DELETE)
1494 UINT i;
1495 int item_index;
1496 LVITEMA item;
1497 LPITEMIDLIST* pItems;
1498 ISFHelper *psfhlp;
1500 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1501 (LPVOID*)&psfhlp);
1503 if (psfhlp == NULL)
1504 break;
1506 if(!(i = ListView_GetSelectedCount(This->hWndList)))
1507 break;
1509 /* allocate memory for the pidl array */
1510 pItems = HeapAlloc(GetProcessHeap(), 0,
1511 sizeof(LPITEMIDLIST) * i);
1513 /* retrieve all selected items */
1514 i = 0;
1515 item_index = -1;
1516 while(ListView_GetSelectedCount(This->hWndList) > i)
1518 /* get selected item */
1519 item_index = ListView_GetNextItem(This->hWndList,
1520 item_index, LVNI_SELECTED);
1521 item.iItem = item_index;
1522 item.mask = LVIF_PARAM;
1523 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &item);
1525 /* get item pidl */
1526 pItems[i] = (LPITEMIDLIST)item.lParam;
1528 i++;
1531 /* perform the item deletion */
1532 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1534 /* free pidl array memory */
1535 HeapFree(GetProcessHeap(), 0, pItems);
1538 /* Initiate a refresh */
1539 else if(plvKeyDown->wVKey == VK_F5)
1541 IShellView_Refresh((IShellView*)This);
1544 else
1545 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1547 break;
1549 default:
1550 TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1551 break;
1553 return 0;
1556 /**********************************************************
1557 * ShellView_OnChange()
1560 static LRESULT ShellView_OnChange(IShellViewImpl * This, const LPCITEMIDLIST * Pidls, LONG wEventId)
1563 TRACE("(%p)(%p,%p,0x%08x)\n", This, Pidls[0], Pidls[1], wEventId);
1564 switch(wEventId)
1566 case SHCNE_MKDIR:
1567 case SHCNE_CREATE:
1568 LV_AddItem(This, Pidls[0]);
1569 break;
1570 case SHCNE_RMDIR:
1571 case SHCNE_DELETE:
1572 LV_DeleteItem(This, Pidls[0]);
1573 break;
1574 case SHCNE_RENAMEFOLDER:
1575 case SHCNE_RENAMEITEM:
1576 LV_RenameItem(This, Pidls[0], Pidls[1]);
1577 break;
1578 case SHCNE_UPDATEITEM:
1579 break;
1581 return TRUE;
1583 /**********************************************************
1584 * ShellView_WndProc
1587 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1589 IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1590 LPCREATESTRUCTW lpcs;
1592 TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1594 switch (uMessage)
1596 case WM_NCCREATE:
1597 lpcs = (LPCREATESTRUCTW)lParam;
1598 pThis = (IShellViewImpl*)(lpcs->lpCreateParams);
1599 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1600 pThis->hWnd = hWnd; /*set the window handle*/
1601 break;
1603 case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1604 case WM_SETFOCUS: return ShellView_OnSetFocus(pThis);
1605 case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis);
1606 case WM_CREATE: return ShellView_OnCreate(pThis);
1607 case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1608 case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1609 case WM_COMMAND: return ShellView_OnCommand(pThis,
1610 GET_WM_COMMAND_ID(wParam, lParam),
1611 GET_WM_COMMAND_CMD(wParam, lParam),
1612 GET_WM_COMMAND_HWND(wParam, lParam));
1613 case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (const LPCITEMIDLIST*)wParam, (LONG)lParam);
1615 case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1616 return 0;
1618 case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
1619 break;
1621 case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0);
1623 case WM_DESTROY:
1624 RevokeDragDrop(pThis->hWnd);
1625 SHChangeNotifyDeregister(pThis->hNotify);
1626 break;
1628 case WM_ERASEBKGND:
1629 if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1630 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1631 return 1;
1632 break;
1635 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
1637 /**********************************************************
1640 * The INTERFACE of the IShellView object
1643 **********************************************************
1644 * IShellView_QueryInterface
1646 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj)
1648 IShellViewImpl *This = (IShellViewImpl *)iface;
1650 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1652 *ppvObj = NULL;
1654 if(IsEqualIID(riid, &IID_IUnknown))
1656 *ppvObj = This;
1658 else if(IsEqualIID(riid, &IID_IShellView))
1660 *ppvObj = (IShellView*)This;
1662 else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1664 *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget);
1666 else if(IsEqualIID(riid, &IID_IDropTarget))
1668 *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
1670 else if(IsEqualIID(riid, &IID_IDropSource))
1672 *ppvObj = (IDropSource*)&(This->lpvtblDropSource);
1674 else if(IsEqualIID(riid, &IID_IViewObject))
1676 *ppvObj = (IViewObject*)&(This->lpvtblViewObject);
1679 if(*ppvObj)
1681 IUnknown_AddRef( (IUnknown*)*ppvObj );
1682 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1683 return S_OK;
1685 TRACE("-- Interface: E_NOINTERFACE\n");
1686 return E_NOINTERFACE;
1689 /**********************************************************
1690 * IShellView_AddRef
1692 static ULONG WINAPI IShellView_fnAddRef(IShellView * iface)
1694 IShellViewImpl *This = (IShellViewImpl *)iface;
1695 ULONG refCount = InterlockedIncrement(&This->ref);
1697 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
1699 return refCount;
1701 /**********************************************************
1702 * IShellView_Release
1704 static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
1706 IShellViewImpl *This = (IShellViewImpl *)iface;
1707 ULONG refCount = InterlockedDecrement(&This->ref);
1709 TRACE("(%p)->(count=%i)\n", This, refCount + 1);
1711 if (!refCount)
1713 TRACE(" destroying IShellView(%p)\n",This);
1715 DestroyWindow(This->hWndList);
1717 if(This->pSFParent)
1718 IShellFolder_Release(This->pSFParent);
1720 if(This->pSF2Parent)
1721 IShellFolder2_Release(This->pSF2Parent);
1723 SHFree(This->apidl);
1725 if(This->pAdvSink)
1726 IAdviseSink_Release(This->pAdvSink);
1728 HeapFree(GetProcessHeap(),0,This);
1730 return refCount;
1733 /**********************************************************
1734 * ShellView_GetWindow
1736 static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd)
1738 IShellViewImpl *This = (IShellViewImpl *)iface;
1740 TRACE("(%p)\n",This);
1742 *phWnd = This->hWnd;
1744 return S_OK;
1747 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode)
1749 IShellViewImpl *This = (IShellViewImpl *)iface;
1751 FIXME("(%p) stub\n",This);
1753 return E_NOTIMPL;
1756 /**********************************************************
1757 * IShellView_TranslateAccelerator
1759 * FIXME:
1760 * use the accel functions
1762 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg)
1764 #if 0
1765 IShellViewImpl *This = (IShellViewImpl *)iface;
1767 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1768 #endif
1770 if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1772 TRACE("-- key=0x04%lx\n",lpmsg->wParam) ;
1774 return S_FALSE; /* not handled */
1777 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable)
1779 IShellViewImpl *This = (IShellViewImpl *)iface;
1781 FIXME("(%p) stub\n",This);
1783 return E_NOTIMPL;
1786 static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState)
1788 IShellViewImpl *This = (IShellViewImpl *)iface;
1791 CHAR szName[MAX_PATH];
1793 LRESULT lResult;
1794 int nPartArray[1] = {-1};
1796 TRACE("(%p)->(state=%x) stub\n",This, uState);
1798 /*don't do anything if the state isn't really changing*/
1799 if(This->uState == uState)
1801 return S_OK;
1804 /*OnActivate handles the menu merging and internal state*/
1805 ShellView_OnActivate(This, uState);
1807 /*only do This if we are active*/
1808 if(uState != SVUIA_DEACTIVATE)
1812 GetFolderPath is not a method of IShellFolder
1813 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1815 /* set the number of parts */
1816 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1817 (LPARAM)nPartArray, &lResult);
1819 /* set the text for the parts */
1821 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1822 0, (LPARAM)szName, &lResult);
1826 return S_OK;
1829 static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface)
1831 IShellViewImpl *This = (IShellViewImpl *)iface;
1833 TRACE("(%p)\n",This);
1835 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
1836 ShellView_FillList(This);
1838 return S_OK;
1841 static HRESULT WINAPI IShellView_fnCreateViewWindow(
1842 IShellView * iface,
1843 IShellView *lpPrevView,
1844 LPCFOLDERSETTINGS lpfs,
1845 IShellBrowser * psb,
1846 RECT * prcView,
1847 HWND *phWnd)
1849 IShellViewImpl *This = (IShellViewImpl *)iface;
1851 WNDCLASSW wc;
1852 *phWnd = 0;
1855 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd);
1856 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);
1858 /*set up the member variables*/
1859 This->pShellBrowser = psb;
1860 This->FolderSettings = *lpfs;
1862 /*get our parent window*/
1863 IShellBrowser_AddRef(This->pShellBrowser);
1864 IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
1866 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1867 This->pCommDlgBrowser=NULL;
1868 if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser,
1869 (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser)))
1871 TRACE("-- CommDlgBrowser\n");
1874 /*if our window class has not been registered, then do so*/
1875 if(!GetClassInfoW(shell32_hInstance, SV_CLASS_NAME, &wc))
1877 ZeroMemory(&wc, sizeof(wc));
1878 wc.style = CS_HREDRAW | CS_VREDRAW;
1879 wc.lpfnWndProc = ShellView_WndProc;
1880 wc.cbClsExtra = 0;
1881 wc.cbWndExtra = 0;
1882 wc.hInstance = shell32_hInstance;
1883 wc.hIcon = 0;
1884 wc.hCursor = LoadCursorW(0, (LPWSTR)IDC_ARROW);
1885 wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
1886 wc.lpszMenuName = NULL;
1887 wc.lpszClassName = SV_CLASS_NAME;
1889 if(!RegisterClassW(&wc))
1890 return E_FAIL;
1893 *phWnd = CreateWindowExW(0,
1894 SV_CLASS_NAME,
1895 NULL,
1896 WS_CHILD | WS_TABSTOP,
1897 prcView->left,
1898 prcView->top,
1899 prcView->right - prcView->left,
1900 prcView->bottom - prcView->top,
1901 This->hWndParent,
1903 shell32_hInstance,
1904 (LPVOID)This);
1906 CheckToolbar(This);
1908 if(!*phWnd) return E_FAIL;
1910 SetWindowPos(*phWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
1911 UpdateWindow(*phWnd);
1913 return S_OK;
1916 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
1918 IShellViewImpl *This = (IShellViewImpl *)iface;
1920 TRACE("(%p)\n",This);
1922 /*Make absolutely sure all our UI is cleaned up.*/
1923 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1925 if(This->hMenu)
1927 DestroyMenu(This->hMenu);
1930 DestroyWindow(This->hWnd);
1931 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1932 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1935 return S_OK;
1938 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs)
1940 IShellViewImpl *This = (IShellViewImpl *)iface;
1942 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1943 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1945 if (!lpfs) return E_INVALIDARG;
1947 *lpfs = This->FolderSettings;
1948 return NOERROR;
1951 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1953 IShellViewImpl *This = (IShellViewImpl *)iface;
1955 FIXME("(%p) stub\n",This);
1957 return E_NOTIMPL;
1960 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface)
1962 IShellViewImpl *This = (IShellViewImpl *)iface;
1964 FIXME("(%p) stub\n",This);
1966 return S_OK;
1969 static HRESULT WINAPI IShellView_fnSelectItem(
1970 IShellView * iface,
1971 LPCITEMIDLIST pidl,
1972 UINT uFlags)
1974 IShellViewImpl *This = (IShellViewImpl *)iface;
1975 int i;
1977 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
1979 i = LV_FindItemByPidl(This, pidl);
1981 if (i != -1)
1983 LVITEMW lvItem;
1985 if(uFlags & SVSI_ENSUREVISIBLE)
1986 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1988 lvItem.mask = LVIF_STATE;
1989 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
1990 lvItem.iItem = 0;
1991 lvItem.iSubItem = 0;
1993 while(SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem))
1995 if (lvItem.iItem == i)
1997 if (uFlags & SVSI_SELECT)
1998 lvItem.state |= LVIS_SELECTED;
1999 else
2000 lvItem.state &= ~LVIS_SELECTED;
2002 if(uFlags & SVSI_FOCUSED)
2003 lvItem.state &= ~LVIS_FOCUSED;
2005 else
2007 if (uFlags & SVSI_DESELECTOTHERS)
2008 lvItem.state &= ~LVIS_SELECTED;
2010 SendMessageW(This->hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
2011 lvItem.iItem++;
2015 if(uFlags & SVSI_EDIT)
2016 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
2019 return S_OK;
2022 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
2024 IShellViewImpl *This = (IShellViewImpl *)iface;
2026 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2028 *ppvOut = NULL;
2030 switch(uItem)
2032 case SVGIO_BACKGROUND:
2033 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2034 break;
2036 case SVGIO_SELECTION:
2037 ShellView_GetSelections(This);
2038 IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2039 break;
2041 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2043 if(!*ppvOut) return E_OUTOFMEMORY;
2045 return S_OK;
2048 static const IShellViewVtbl svvt =
2050 IShellView_fnQueryInterface,
2051 IShellView_fnAddRef,
2052 IShellView_fnRelease,
2053 IShellView_fnGetWindow,
2054 IShellView_fnContextSensitiveHelp,
2055 IShellView_fnTranslateAccelerator,
2056 IShellView_fnEnableModeless,
2057 IShellView_fnUIActivate,
2058 IShellView_fnRefresh,
2059 IShellView_fnCreateViewWindow,
2060 IShellView_fnDestroyViewWindow,
2061 IShellView_fnGetCurrentInfo,
2062 IShellView_fnAddPropertySheetPages,
2063 IShellView_fnSaveViewState,
2064 IShellView_fnSelectItem,
2065 IShellView_fnGetItemObject
2069 /**********************************************************
2070 * ISVOleCmdTarget_QueryInterface (IUnknown)
2072 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2073 IOleCommandTarget * iface,
2074 REFIID iid,
2075 LPVOID* ppvObj)
2077 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2079 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2082 /**********************************************************
2083 * ISVOleCmdTarget_AddRef (IUnknown)
2085 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2086 IOleCommandTarget * iface)
2088 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2090 return IShellFolder_AddRef((IShellFolder*)This);
2093 /**********************************************************
2094 * ISVOleCmdTarget_Release (IUnknown)
2096 static ULONG WINAPI ISVOleCmdTarget_Release(
2097 IOleCommandTarget * iface)
2099 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2101 return IShellFolder_Release((IShellFolder*)This);
2104 /**********************************************************
2105 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2107 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2108 IOleCommandTarget *iface,
2109 const GUID* pguidCmdGroup,
2110 ULONG cCmds,
2111 OLECMD * prgCmds,
2112 OLECMDTEXT* pCmdText)
2114 UINT i;
2115 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2117 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2118 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2120 if (!prgCmds)
2121 return E_POINTER;
2122 for (i = 0; i < cCmds; i++)
2124 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2125 prgCmds[i].cmdf = 0;
2127 return OLECMDERR_E_UNKNOWNGROUP;
2130 /**********************************************************
2131 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2133 * nCmdID is the OLECMDID_* enumeration
2135 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2136 IOleCommandTarget *iface,
2137 const GUID* pguidCmdGroup,
2138 DWORD nCmdID,
2139 DWORD nCmdexecopt,
2140 VARIANT* pvaIn,
2141 VARIANT* pvaOut)
2143 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2145 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2146 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2148 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2149 (nCmdID == 0x29) &&
2150 (nCmdexecopt == 4) && pvaOut)
2151 return S_OK;
2152 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2153 (nCmdID == 9) &&
2154 (nCmdexecopt == 0))
2155 return 1;
2157 return OLECMDERR_E_UNKNOWNGROUP;
2160 static const IOleCommandTargetVtbl ctvt =
2162 ISVOleCmdTarget_QueryInterface,
2163 ISVOleCmdTarget_AddRef,
2164 ISVOleCmdTarget_Release,
2165 ISVOleCmdTarget_QueryStatus,
2166 ISVOleCmdTarget_Exec
2169 /**********************************************************
2170 * ISVDropTarget implementation
2173 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2174 IDropTarget *iface,
2175 REFIID riid,
2176 LPVOID *ppvObj)
2178 IShellViewImpl *This = impl_from_IDropTarget(iface);
2180 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2182 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2185 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2187 IShellViewImpl *This = impl_from_IDropTarget(iface);
2189 TRACE("(%p)->(count=%u)\n",This,This->ref);
2191 return IShellFolder_AddRef((IShellFolder*)This);
2194 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2196 IShellViewImpl *This = impl_from_IDropTarget(iface);
2198 TRACE("(%p)->(count=%u)\n",This,This->ref);
2200 return IShellFolder_Release((IShellFolder*)This);
2203 /******************************************************************************
2204 * drag_notify_subitem [Internal]
2206 * Figure out the shellfolder object, which is currently under the mouse cursor
2207 * and notify it via the IDropTarget interface.
2210 #define SCROLLAREAWIDTH 20
2212 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2213 DWORD *pdwEffect)
2215 LVHITTESTINFO htinfo;
2216 LVITEMW lvItem;
2217 LONG lResult;
2218 HRESULT hr;
2219 RECT clientRect;
2221 /* Map from global to client coordinates and query the index of the listview-item, which is
2222 * currently under the mouse cursor. */
2223 htinfo.pt.x = pt.x;
2224 htinfo.pt.y = pt.y;
2225 htinfo.flags = LVHT_ONITEM;
2226 ScreenToClient(This->hWndList, &htinfo.pt);
2227 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2229 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2230 GetClientRect(This->hWndList, &clientRect);
2231 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2232 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2233 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2235 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2236 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2237 if (htinfo.pt.x < SCROLLAREAWIDTH)
2238 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2239 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2240 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2241 if (htinfo.pt.y < SCROLLAREAWIDTH)
2242 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2243 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2244 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2246 } else {
2247 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2249 This->ptLastMousePos = htinfo.pt;
2251 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2252 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2253 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2255 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2256 if (This->pCurDropTarget) {
2257 IDropTarget_DragLeave(This->pCurDropTarget);
2258 IDropTarget_Release(This->pCurDropTarget);
2259 This->pCurDropTarget = NULL;
2262 This->iDragOverItem = lResult;
2263 if (lResult == -1) {
2264 /* We are not above one of the listview's subitems. Bind to the parent folder's
2265 * DropTarget interface. */
2266 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2267 (LPVOID*)&This->pCurDropTarget);
2268 } else {
2269 /* Query the relative PIDL of the shellfolder object represented by the currently
2270 * dragged over listview-item ... */
2271 lvItem.mask = LVIF_PARAM;
2272 lvItem.iItem = lResult;
2273 lvItem.iSubItem = 0;
2274 SendMessageW(This->hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
2276 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2277 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2278 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2281 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2282 if (FAILED(hr))
2283 return hr;
2285 /* Notify the item just entered via DragEnter. */
2286 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2289 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2290 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2292 IShellViewImpl *This = impl_from_IDropTarget(iface);
2294 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2295 This->pCurDataObject = pDataObject;
2296 IDataObject_AddRef(pDataObject);
2298 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2301 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2302 DWORD *pdwEffect)
2304 IShellViewImpl *This = impl_from_IDropTarget(iface);
2305 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2308 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2309 IShellViewImpl *This = impl_from_IDropTarget(iface);
2311 IDropTarget_DragLeave(This->pCurDropTarget);
2313 IDropTarget_Release(This->pCurDropTarget);
2314 IDataObject_Release(This->pCurDataObject);
2315 This->pCurDataObject = NULL;
2316 This->pCurDropTarget = NULL;
2317 This->iDragOverItem = 0;
2319 return S_OK;
2322 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2323 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2325 IShellViewImpl *This = impl_from_IDropTarget(iface);
2327 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
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 const IDropTargetVtbl dtvt =
2340 ISVDropTarget_QueryInterface,
2341 ISVDropTarget_AddRef,
2342 ISVDropTarget_Release,
2343 ISVDropTarget_DragEnter,
2344 ISVDropTarget_DragOver,
2345 ISVDropTarget_DragLeave,
2346 ISVDropTarget_Drop
2349 /**********************************************************
2350 * ISVDropSource implementation
2353 static HRESULT WINAPI ISVDropSource_QueryInterface(
2354 IDropSource *iface,
2355 REFIID riid,
2356 LPVOID *ppvObj)
2358 IShellViewImpl *This = impl_from_IDropSource(iface);
2360 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2362 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2365 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2367 IShellViewImpl *This = impl_from_IDropSource(iface);
2369 TRACE("(%p)->(count=%u)\n",This,This->ref);
2371 return IShellFolder_AddRef((IShellFolder*)This);
2374 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2376 IShellViewImpl *This = impl_from_IDropSource(iface);
2378 TRACE("(%p)->(count=%u)\n",This,This->ref);
2380 return IShellFolder_Release((IShellFolder*)This);
2382 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2383 IDropSource *iface,
2384 BOOL fEscapePressed,
2385 DWORD grfKeyState)
2387 IShellViewImpl *This = impl_from_IDropSource(iface);
2388 TRACE("(%p)\n",This);
2390 if (fEscapePressed)
2391 return DRAGDROP_S_CANCEL;
2392 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2393 return DRAGDROP_S_DROP;
2394 else
2395 return NOERROR;
2398 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2399 IDropSource *iface,
2400 DWORD dwEffect)
2402 IShellViewImpl *This = impl_from_IDropSource(iface);
2403 TRACE("(%p)\n",This);
2405 return DRAGDROP_S_USEDEFAULTCURSORS;
2408 static const IDropSourceVtbl dsvt =
2410 ISVDropSource_QueryInterface,
2411 ISVDropSource_AddRef,
2412 ISVDropSource_Release,
2413 ISVDropSource_QueryContinueDrag,
2414 ISVDropSource_GiveFeedback
2416 /**********************************************************
2417 * ISVViewObject implementation
2420 static HRESULT WINAPI ISVViewObject_QueryInterface(
2421 IViewObject *iface,
2422 REFIID riid,
2423 LPVOID *ppvObj)
2425 IShellViewImpl *This = impl_from_IViewObject(iface);
2427 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2429 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2432 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2434 IShellViewImpl *This = impl_from_IViewObject(iface);
2436 TRACE("(%p)->(count=%u)\n",This,This->ref);
2438 return IShellFolder_AddRef((IShellFolder*)This);
2441 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2443 IShellViewImpl *This = impl_from_IViewObject(iface);
2445 TRACE("(%p)->(count=%u)\n",This,This->ref);
2447 return IShellFolder_Release((IShellFolder*)This);
2450 static HRESULT WINAPI ISVViewObject_Draw(
2451 IViewObject *iface,
2452 DWORD dwDrawAspect,
2453 LONG lindex,
2454 void* pvAspect,
2455 DVTARGETDEVICE* ptd,
2456 HDC hdcTargetDev,
2457 HDC hdcDraw,
2458 LPCRECTL lprcBounds,
2459 LPCRECTL lprcWBounds,
2460 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2461 ULONG_PTR dwContinue)
2464 IShellViewImpl *This = impl_from_IViewObject(iface);
2466 FIXME("Stub: This=%p\n",This);
2468 return E_NOTIMPL;
2470 static HRESULT WINAPI ISVViewObject_GetColorSet(
2471 IViewObject *iface,
2472 DWORD dwDrawAspect,
2473 LONG lindex,
2474 void *pvAspect,
2475 DVTARGETDEVICE* ptd,
2476 HDC hicTargetDevice,
2477 LOGPALETTE** ppColorSet)
2480 IShellViewImpl *This = impl_from_IViewObject(iface);
2482 FIXME("Stub: This=%p\n",This);
2484 return E_NOTIMPL;
2486 static HRESULT WINAPI ISVViewObject_Freeze(
2487 IViewObject *iface,
2488 DWORD dwDrawAspect,
2489 LONG lindex,
2490 void* pvAspect,
2491 DWORD* pdwFreeze)
2494 IShellViewImpl *This = impl_from_IViewObject(iface);
2496 FIXME("Stub: This=%p\n",This);
2498 return E_NOTIMPL;
2500 static HRESULT WINAPI ISVViewObject_Unfreeze(
2501 IViewObject *iface,
2502 DWORD dwFreeze)
2505 IShellViewImpl *This = impl_from_IViewObject(iface);
2507 FIXME("Stub: This=%p\n",This);
2509 return E_NOTIMPL;
2511 static HRESULT WINAPI ISVViewObject_SetAdvise(
2512 IViewObject *iface,
2513 DWORD aspects,
2514 DWORD advf,
2515 IAdviseSink* pAdvSink)
2518 IShellViewImpl *This = impl_from_IViewObject(iface);
2520 FIXME("partial stub: %p %08x %08x %p\n",
2521 This, aspects, advf, pAdvSink);
2523 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2524 This->pAdvSink = pAdvSink;
2525 This->dwAspects = aspects;
2526 This->dwAdvf = advf;
2528 return S_OK;
2531 static HRESULT WINAPI ISVViewObject_GetAdvise(
2532 IViewObject *iface,
2533 DWORD* pAspects,
2534 DWORD* pAdvf,
2535 IAdviseSink** ppAdvSink)
2538 IShellViewImpl *This = impl_from_IViewObject(iface);
2540 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2541 This, pAspects, pAdvf, ppAdvSink);
2543 if( ppAdvSink )
2545 IAdviseSink_AddRef( This->pAdvSink );
2546 *ppAdvSink = This->pAdvSink;
2548 if( pAspects )
2549 *pAspects = This->dwAspects;
2550 if( pAdvf )
2551 *pAdvf = This->dwAdvf;
2553 return S_OK;
2557 static const IViewObjectVtbl vovt =
2559 ISVViewObject_QueryInterface,
2560 ISVViewObject_AddRef,
2561 ISVViewObject_Release,
2562 ISVViewObject_Draw,
2563 ISVViewObject_GetColorSet,
2564 ISVViewObject_Freeze,
2565 ISVViewObject_Unfreeze,
2566 ISVViewObject_SetAdvise,
2567 ISVViewObject_GetAdvise