new 818051de2c8769029049ce3d36c6b856f47496c9
[wine/hacks.git] / dlls / shell32 / shlview.c
blob6dd27da30cf867e0059a657b8c58c2ce1590dcb9
1 /*
2 * ShellView
4 * Copyright 1998,1999 <juergen.schmied@debitel.net>
6 * This is the view visualizing the data provied by the shellfolder.
7 * No direct access to data from pidls should be done from here.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * FIXME: The order by part of the background context menu should be
24 * buily according to the columns shown.
26 * FIXME: Load/Save the view state from/into the stream provied by
27 * the ShellBrowser
29 * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
31 * FIXME: ShellView_FillList: consider sort orders
33 * FIXME: implement the drag and drop in the old (msg-based) way
35 * FIXME: when the ShellView_WndProc gets a WM_NCDESTROY should we do a
36 * Release() ???
39 #include "config.h"
40 #include "wine/port.h"
42 #include <stdarg.h>
43 #include <stdlib.h>
44 #include <string.h>
46 #define COBJMACROS
47 #define NONAMELESSUNION
48 #define NONAMELESSSTRUCT
50 #include "windef.h"
51 #include "winerror.h"
52 #include "winbase.h"
53 #include "winnls.h"
54 #include "objbase.h"
55 #include "servprov.h"
56 #include "shlguid.h"
57 #include "wingdi.h"
58 #include "winuser.h"
59 #include "shlobj.h"
60 #include "undocshell.h"
61 #include "shresdef.h"
62 #include "wine/debug.h"
64 #include "docobj.h"
65 #include "pidl.h"
66 #include "shell32_main.h"
67 #include "shellfolder.h"
69 WINE_DEFAULT_DEBUG_CHANNEL(shell);
71 typedef struct
72 { BOOL bIsAscending;
73 INT nHeaderID;
74 INT nLastHeaderID;
75 }LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;
77 typedef struct
79 const IShellViewVtbl* lpVtbl;
80 LONG ref;
81 const IOleCommandTargetVtbl* lpvtblOleCommandTarget;
82 const IDropTargetVtbl* lpvtblDropTarget;
83 const IDropSourceVtbl* lpvtblDropSource;
84 const IViewObjectVtbl* lpvtblViewObject;
85 IShellFolder* pSFParent;
86 IShellFolder2* pSF2Parent;
87 IShellBrowser* pShellBrowser;
88 ICommDlgBrowser* pCommDlgBrowser;
89 HWND hWnd; /* SHELLDLL_DefView */
90 HWND hWndList; /* ListView control */
91 HWND hWndParent;
92 FOLDERSETTINGS FolderSettings;
93 HMENU hMenu;
94 UINT uState;
95 UINT cidl;
96 LPITEMIDLIST *apidl;
97 LISTVIEW_SORT_INFO ListViewSortInfo;
98 ULONG hNotify; /* change notification handle */
99 HANDLE hAccel;
100 DWORD dwAspects;
101 DWORD dwAdvf;
102 IAdviseSink *pAdvSink;
103 IDropTarget* pCurDropTarget; /* The sub-item, which is currently dragged over */
104 IDataObject* pCurDataObject; /* The dragged data-object */
105 LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */
106 UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
107 POINT ptLastMousePos; /* Mouse position at last DragOver call */
108 } IShellViewImpl;
110 static const IShellViewVtbl svvt;
111 static const IOleCommandTargetVtbl ctvt;
112 static const IDropTargetVtbl dtvt;
113 static const IDropSourceVtbl dsvt;
114 static const IViewObjectVtbl vovt;
117 static inline IShellViewImpl *impl_from_IOleCommandTarget( IOleCommandTarget *iface )
119 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblOleCommandTarget));
122 static inline IShellViewImpl *impl_from_IDropTarget( IDropTarget *iface )
124 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropTarget));
127 static inline IShellViewImpl *impl_from_IDropSource( IDropSource *iface )
129 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropSource));
132 static inline IShellViewImpl *impl_from_IViewObject( IViewObject *iface )
134 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblViewObject));
137 /* ListView Header ID's */
138 #define LISTVIEW_COLUMN_NAME 0
139 #define LISTVIEW_COLUMN_SIZE 1
140 #define LISTVIEW_COLUMN_TYPE 2
141 #define LISTVIEW_COLUMN_TIME 3
142 #define LISTVIEW_COLUMN_ATTRIB 4
144 /*menu items */
145 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
146 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
147 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
149 #define ID_LISTVIEW 1
151 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
153 /*windowsx.h */
154 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
155 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
156 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
159 Items merged into the toolbar and the filemenu
161 typedef struct
162 { int idCommand;
163 int iImage;
164 int idButtonString;
165 int idMenuString;
166 BYTE bState;
167 BYTE bStyle;
168 } MYTOOLINFO, *LPMYTOOLINFO;
170 static const MYTOOLINFO Tools[] =
172 { FCIDM_SHVIEW_BIGICON, 0, 0, IDS_VIEW_LARGE, TBSTATE_ENABLED, BTNS_BUTTON },
173 { FCIDM_SHVIEW_SMALLICON, 0, 0, IDS_VIEW_SMALL, TBSTATE_ENABLED, BTNS_BUTTON },
174 { FCIDM_SHVIEW_LISTVIEW, 0, 0, IDS_VIEW_LIST, TBSTATE_ENABLED, BTNS_BUTTON },
175 { FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON },
176 { -1, 0, 0, 0, 0, 0}
179 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
181 /**********************************************************
182 * IShellView_Constructor
184 IShellView * IShellView_Constructor( IShellFolder * pFolder)
185 { IShellViewImpl * sv;
186 sv=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellViewImpl));
187 sv->ref=1;
188 sv->lpVtbl=&svvt;
189 sv->lpvtblOleCommandTarget=&ctvt;
190 sv->lpvtblDropTarget=&dtvt;
191 sv->lpvtblDropSource=&dsvt;
192 sv->lpvtblViewObject=&vovt;
194 sv->pSFParent = pFolder;
195 if(pFolder) IShellFolder_AddRef(pFolder);
196 IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent);
198 sv->pCurDropTarget = NULL;
199 sv->pCurDataObject = NULL;
200 sv->iDragOverItem = 0;
201 sv->cScrollDelay = 0;
202 sv->ptLastMousePos.x = 0;
203 sv->ptLastMousePos.y = 0;
205 TRACE("(%p)->(%p)\n",sv, pFolder);
206 return (IShellView *) sv;
209 /**********************************************************
211 * ##### helperfunctions for communication with ICommDlgBrowser #####
213 static BOOL IsInCommDlg(IShellViewImpl * This)
214 { return(This->pCommDlgBrowser != NULL);
217 static HRESULT IncludeObject(IShellViewImpl * This, LPCITEMIDLIST pidl)
219 HRESULT ret = S_OK;
221 if ( IsInCommDlg(This) )
223 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
224 ret = ICommDlgBrowser_IncludeObject(This->pCommDlgBrowser, (IShellView*)This, pidl);
225 TRACE("--0x%08x\n", ret);
227 return ret;
230 static HRESULT OnDefaultCommand(IShellViewImpl * This)
232 HRESULT ret = S_FALSE;
234 if (IsInCommDlg(This))
236 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
237 ret = ICommDlgBrowser_OnDefaultCommand(This->pCommDlgBrowser, (IShellView*)This);
238 TRACE("-- returns %08x\n", ret);
240 return ret;
243 static HRESULT OnStateChange(IShellViewImpl * This, UINT uFlags)
245 HRESULT ret = S_FALSE;
247 if (IsInCommDlg(This))
249 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
250 ret = ICommDlgBrowser_OnStateChange(This->pCommDlgBrowser, (IShellView*)This, uFlags);
251 TRACE("--\n");
253 return ret;
255 /**********************************************************
256 * set the toolbar of the filedialog buttons
258 * - activates the buttons from the shellbrowser according to
259 * the view state
261 static void CheckToolbar(IShellViewImpl * This)
263 LRESULT result;
265 TRACE("\n");
267 if (IsInCommDlg(This))
269 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
270 FCIDM_TB_SMALLICON, (This->FolderSettings.ViewMode==FVM_LIST)? TRUE : FALSE, &result);
271 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
272 FCIDM_TB_REPORTVIEW, (This->FolderSettings.ViewMode==FVM_DETAILS)? TRUE : FALSE, &result);
273 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
274 FCIDM_TB_SMALLICON, TRUE, &result);
275 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
276 FCIDM_TB_REPORTVIEW, TRUE, &result);
280 /**********************************************************
282 * ##### helperfunctions for initializing the view #####
284 /**********************************************************
285 * change the style of the listview control
287 static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove)
289 DWORD tmpstyle;
291 TRACE("(%p)\n", This);
293 tmpstyle = GetWindowLongA(This->hWndList, GWL_STYLE);
294 SetWindowLongA(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
297 /**********************************************************
298 * ShellView_CreateList()
300 * - creates the list view window
302 static BOOL ShellView_CreateList (IShellViewImpl * This)
303 { DWORD dwStyle, dwExStyle;
305 TRACE("%p\n",This);
307 dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
308 LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT | LVS_AUTOARRANGE;
309 dwExStyle = WS_EX_CLIENTEDGE;
311 switch (This->FolderSettings.ViewMode)
313 case FVM_ICON: dwStyle |= LVS_ICON; break;
314 case FVM_DETAILS: dwStyle |= LVS_REPORT; break;
315 case FVM_SMALLICON: dwStyle |= LVS_SMALLICON; break;
316 case FVM_LIST: dwStyle |= LVS_LIST; break;
317 default: dwStyle |= LVS_LIST; break;
320 if (This->FolderSettings.fFlags & FWF_AUTOARRANGE) dwStyle |= LVS_AUTOARRANGE;
321 if (This->FolderSettings.fFlags & FWF_DESKTOP)
322 This->FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
323 if (This->FolderSettings.fFlags & FWF_SINGLESEL) dwStyle |= LVS_SINGLESEL;
324 if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE)
325 dwExStyle &= ~WS_EX_CLIENTEDGE;
327 This->hWndList=CreateWindowExA( dwExStyle,
328 WC_LISTVIEWA,
329 NULL,
330 dwStyle,
331 0,0,0,0,
332 This->hWnd,
333 (HMENU)ID_LISTVIEW,
334 shell32_hInstance,
335 NULL);
337 if(!This->hWndList)
338 return FALSE;
340 This->ListViewSortInfo.bIsAscending = TRUE;
341 This->ListViewSortInfo.nHeaderID = -1;
342 This->ListViewSortInfo.nLastHeaderID = -1;
344 if (This->FolderSettings.fFlags & FWF_DESKTOP) {
346 * FIXME: look at the registry value
347 * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
348 * and activate drop shadows if necessary
350 if (0)
351 SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, CLR_NONE);
352 else
353 SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, GetSysColor(COLOR_DESKTOP));
355 SendMessageW(This->hWndList, LVM_SETTEXTCOLOR, 0, RGB(255,255,255));
358 /* UpdateShellSettings(); */
359 return TRUE;
362 /**********************************************************
363 * ShellView_InitList()
365 * - adds all needed columns to the shellview
367 static BOOL ShellView_InitList(IShellViewImpl * This)
369 LVCOLUMNW lvColumn;
370 SHELLDETAILS sd;
371 int i;
372 WCHAR szTemp[50];
374 TRACE("%p\n",This);
376 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
378 lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
379 lvColumn.pszText = szTemp;
381 if (This->pSF2Parent)
383 for (i=0; 1; i++)
385 if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd)))
386 break;
387 lvColumn.fmt = sd.fmt;
388 lvColumn.cx = sd.cxChar*8; /* chars->pixel */
389 StrRetToStrNW( szTemp, 50, &sd.str, NULL);
390 SendMessageW(This->hWndList, LVM_INSERTCOLUMNW, i, (LPARAM) &lvColumn);
393 else
395 FIXME("no SF2\n");
398 SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ShellSmallIconList);
399 SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)ShellBigIconList);
401 return TRUE;
403 /**********************************************************
404 * ShellView_CompareItems()
406 * NOTES
407 * internal, CALLBACK for DSA_Sort
409 static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
411 int ret;
412 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
414 if(!lpData) return 0;
416 ret = (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2));
417 TRACE("ret=%i\n",ret);
418 return ret;
421 /*************************************************************************
422 * ShellView_ListViewCompareItems
424 * Compare Function for the Listview (FileOpen Dialog)
426 * PARAMS
427 * lParam1 [I] the first ItemIdList to compare with
428 * lParam2 [I] the second ItemIdList to compare with
429 * lpData [I] The column ID for the header Ctrl to process
431 * RETURNS
432 * A negative value if the first item should precede the second,
433 * a positive value if the first item should follow the second,
434 * or zero if the two items are equivalent
436 * NOTES
437 * FIXME: function does what ShellView_CompareItems is supposed to do.
438 * unify it and figure out how to use the undocumented first parameter
439 * of IShellFolder_CompareIDs to do the job this function does and
440 * move this code to IShellFolder.
441 * make LISTVIEW_SORT_INFO obsolete
442 * the way this function works is only usable if we had only
443 * filesystemfolders (25/10/99 jsch)
445 static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
447 INT nDiff=0;
448 FILETIME fd1, fd2;
449 char strName1[MAX_PATH], strName2[MAX_PATH];
450 BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
451 LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1;
452 LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2;
453 LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData;
456 bIsFolder1 = _ILIsFolder(pItemIdList1);
457 bIsFolder2 = _ILIsFolder(pItemIdList2);
458 bIsBothFolder = bIsFolder1 && bIsFolder2;
460 /* When sorting between a File and a Folder, the Folder gets sorted first */
461 if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
463 nDiff = bIsFolder1 ? -1 : 1;
465 else
467 /* Sort by Time: Folders or Files can be sorted */
469 if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
471 _ILGetFileDateTime(pItemIdList1, &fd1);
472 _ILGetFileDateTime(pItemIdList2, &fd2);
473 nDiff = CompareFileTime(&fd2, &fd1);
475 /* Sort by Attribute: Folder or Files can be sorted */
476 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
478 _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH);
479 _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH);
480 nDiff = lstrcmpiA(strName1, strName2);
482 /* Sort by FileName: Folder or Files can be sorted */
483 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
485 /* Sort by Text */
486 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
487 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
488 nDiff = lstrcmpiA(strName1, strName2);
490 /* Sort by File Size, Only valid for Files */
491 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
493 nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0));
495 /* Sort by File Type, Only valid for Files */
496 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
498 /* Sort by Type */
499 _ILGetFileType(pItemIdList1, strName1, MAX_PATH);
500 _ILGetFileType(pItemIdList2, strName2, MAX_PATH);
501 nDiff = lstrcmpiA(strName1, strName2);
504 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
506 if(nDiff == 0)
508 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
509 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
510 nDiff = lstrcmpiA(strName1, strName2);
513 if(!pSortInfo->bIsAscending)
515 nDiff = -nDiff;
518 return nDiff;
522 /**********************************************************
523 * LV_FindItemByPidl()
525 static int LV_FindItemByPidl(
526 IShellViewImpl * This,
527 LPCITEMIDLIST pidl)
529 LVITEMA lvItem;
530 lvItem.iSubItem = 0;
531 lvItem.mask = LVIF_PARAM;
532 for(lvItem.iItem = 0;
533 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
534 lvItem.iItem++)
536 LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam;
537 HRESULT hr = IShellFolder_CompareIDs(This->pSFParent, 0, pidl, currentpidl);
538 if(SUCCEEDED(hr) && !HRESULT_CODE(hr))
540 return lvItem.iItem;
543 return -1;
546 /**********************************************************
547 * LV_AddItem()
549 static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
551 LVITEMA lvItem;
553 TRACE("(%p)(pidl=%p)\n", This, pidl);
555 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/
556 lvItem.iItem = ListView_GetItemCount(This->hWndList); /*add the item to the end of the list*/
557 lvItem.iSubItem = 0;
558 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/
559 lvItem.pszText = LPSTR_TEXTCALLBACKA; /*get text on a callback basis*/
560 lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/
561 return (-1==ListView_InsertItemA(This->hWndList, &lvItem))? FALSE: TRUE;
564 /**********************************************************
565 * LV_DeleteItem()
567 static BOOLEAN LV_DeleteItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
569 int nIndex;
571 TRACE("(%p)(pidl=%p)\n", This, pidl);
573 nIndex = LV_FindItemByPidl(This, ILFindLastID(pidl));
574 return (-1==ListView_DeleteItem(This->hWndList, nIndex))? FALSE: TRUE;
577 /**********************************************************
578 * LV_RenameItem()
580 static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew )
582 int nItem;
583 LVITEMA lvItem;
585 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew);
587 nItem = LV_FindItemByPidl(This, ILFindLastID(pidlOld));
588 if ( -1 != nItem )
590 lvItem.mask = LVIF_PARAM; /* only the pidl */
591 lvItem.iItem = nItem;
592 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
594 SHFree((LPITEMIDLIST)lvItem.lParam);
595 lvItem.mask = LVIF_PARAM;
596 lvItem.iItem = nItem;
597 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */
598 SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem);
599 SendMessageA(This->hWndList, LVM_UPDATE, nItem, 0);
600 return TRUE; /* FIXME: better handling */
602 return FALSE;
604 /**********************************************************
605 * ShellView_FillList()
607 * - gets the objectlist from the shellfolder
608 * - sorts the list
609 * - fills the list into the view
612 static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg )
614 LPITEMIDLIST pidl = ptr;
615 IShellViewImpl *This = arg;
616 /* in a commdlg This works as a filemask*/
617 if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl);
618 SHFree(pidl);
619 return TRUE;
622 static HRESULT ShellView_FillList(IShellViewImpl * This)
624 LPENUMIDLIST pEnumIDList;
625 LPITEMIDLIST pidl;
626 DWORD dwFetched;
627 HRESULT hRes;
628 HDPA hdpa;
630 TRACE("%p\n",This);
632 /* get the itemlist from the shfolder*/
633 hRes = IShellFolder_EnumObjects(This->pSFParent,This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
634 if (hRes != S_OK)
636 if (hRes==S_FALSE)
637 return(NOERROR);
638 return(hRes);
641 /* create a pointer array */
642 hdpa = DPA_Create(16);
643 if (!hdpa)
645 return(E_OUTOFMEMORY);
648 /* copy the items into the array*/
649 while((S_OK == IEnumIDList_Next(pEnumIDList,1, &pidl, &dwFetched)) && dwFetched)
651 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
653 SHFree(pidl);
657 /* sort the array */
658 DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent);
660 /*turn the listview's redrawing off*/
661 SendMessageA(This->hWndList, WM_SETREDRAW, FALSE, 0);
663 DPA_DestroyCallback( hdpa, fill_list, This );
665 /*turn the listview's redrawing back on and force it to draw*/
666 SendMessageA(This->hWndList, WM_SETREDRAW, TRUE, 0);
668 IEnumIDList_Release(pEnumIDList); /* destroy the list*/
670 return S_OK;
673 /**********************************************************
674 * ShellView_OnCreate()
676 static LRESULT ShellView_OnCreate(IShellViewImpl * This)
678 IDropTarget* pdt;
679 SHChangeNotifyEntry ntreg;
680 IPersistFolder2 * ppf2 = NULL;
682 TRACE("%p\n",This);
684 if(ShellView_CreateList(This))
686 if(ShellView_InitList(This))
688 ShellView_FillList(This);
692 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown*)&This->lpVtbl, &IID_IDropTarget, (LPVOID*)&pdt)))
694 RegisterDragDrop(This->hWnd, pdt);
695 IDropTarget_Release(pdt);
698 /* register for receiving notifications */
699 IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
700 if (ppf2)
702 IPersistFolder2_GetCurFolder(ppf2, (LPITEMIDLIST*)&ntreg.pidl);
703 ntreg.fRecursive = TRUE;
704 This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
705 SHFree((LPITEMIDLIST)ntreg.pidl);
706 IPersistFolder2_Release(ppf2);
709 This->hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel");
711 return S_OK;
714 /**********************************************************
715 * #### Handling of the menus ####
718 /**********************************************************
719 * ShellView_BuildFileMenu()
721 static HMENU ShellView_BuildFileMenu(IShellViewImpl * This)
722 { CHAR szText[MAX_PATH];
723 MENUITEMINFOA mii;
724 int nTools,i;
725 HMENU hSubMenu;
727 TRACE("(%p)\n",This);
729 hSubMenu = CreatePopupMenu();
730 if(hSubMenu)
731 { /*get the number of items in our global array*/
732 for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
734 /*add the menu items*/
735 for(i = 0; i < nTools; i++)
737 LoadStringA(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
739 ZeroMemory(&mii, sizeof(mii));
740 mii.cbSize = sizeof(mii);
741 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
743 if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
745 mii.fType = MFT_STRING;
746 mii.fState = MFS_ENABLED;
747 mii.dwTypeData = szText;
748 mii.wID = Tools[i].idCommand;
750 else
752 mii.fType = MFT_SEPARATOR;
754 /* tack This item onto the end of the menu */
755 InsertMenuItemA(hSubMenu, (UINT)-1, TRUE, &mii);
758 TRACE("-- return (menu=%p)\n",hSubMenu);
759 return hSubMenu;
761 /**********************************************************
762 * ShellView_MergeFileMenu()
764 static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu)
765 { TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu);
767 if(hSubMenu)
768 { /*insert This item at the beginning of the menu */
769 _InsertMenuItem(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
770 _InsertMenuItem(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, "dummy45", MFS_ENABLED);
773 TRACE("--\n");
776 /**********************************************************
777 * ShellView_MergeViewMenu()
780 static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu)
782 TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
784 if(hSubMenu)
785 { /*add a separator at the correct position in the menu*/
786 MENUITEMINFOA mii;
787 static char view[] = "View";
789 _InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
791 ZeroMemory(&mii, sizeof(mii));
792 mii.cbSize = sizeof(mii);
793 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
794 mii.fType = MFT_STRING;
795 mii.dwTypeData = view;
796 mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
797 InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
801 /**********************************************************
802 * ShellView_GetSelections()
804 * - fills the this->apidl list with the selected objects
806 * RETURNS
807 * number of selected items
809 static UINT ShellView_GetSelections(IShellViewImpl * This)
811 LVITEMA lvItem;
812 UINT i = 0;
814 SHFree(This->apidl);
816 This->cidl = ListView_GetSelectedCount(This->hWndList);
817 This->apidl = (LPITEMIDLIST*)SHAlloc(This->cidl * sizeof(LPITEMIDLIST));
819 TRACE("selected=%i\n", This->cidl);
821 if(This->apidl)
823 TRACE("-- Items selected =%u\n", This->cidl);
825 lvItem.mask = LVIF_STATE | LVIF_PARAM;
826 lvItem.stateMask = LVIS_SELECTED;
827 lvItem.iItem = 0;
828 lvItem.iSubItem = 0;
830 while(ListView_GetItemA(This->hWndList, &lvItem) && (i < This->cidl))
832 if(lvItem.state & LVIS_SELECTED)
834 This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
835 i++;
836 TRACE("-- selected Item found\n");
838 lvItem.iItem++;
841 return This->cidl;
845 /**********************************************************
846 * ShellView_OpenSelectedItems()
848 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
850 static UINT CF_IDLIST = 0;
851 HRESULT hr;
852 IDataObject* selection;
853 FORMATETC fetc;
854 STGMEDIUM stgm;
855 LPIDA pIDList;
856 LPCITEMIDLIST parent_pidl;
857 WCHAR parent_path[MAX_PATH];
858 LPCWSTR parent_dir = NULL;
859 SFGAOF attribs;
860 int i;
862 if (0 == ShellView_GetSelections(This))
864 return S_OK;
866 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
867 (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
868 0, (LPVOID *)&selection);
869 if (FAILED(hr))
870 return hr;
872 if (0 == CF_IDLIST)
874 CF_IDLIST = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
876 fetc.cfFormat = CF_IDLIST;
877 fetc.ptd = NULL;
878 fetc.dwAspect = DVASPECT_CONTENT;
879 fetc.lindex = -1;
880 fetc.tymed = TYMED_HGLOBAL;
882 hr = IDataObject_QueryGetData(selection, &fetc);
883 if (FAILED(hr))
884 return hr;
886 hr = IDataObject_GetData(selection, &fetc, &stgm);
887 if (FAILED(hr))
888 return hr;
890 pIDList = GlobalLock(stgm.u.hGlobal);
892 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
893 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &parent_pidl, &attribs);
894 if (SUCCEEDED(hr) && (attribs & SFGAO_FILESYSTEM) &&
895 SHGetPathFromIDListW(parent_pidl, parent_path))
897 parent_dir = parent_path;
900 for (i = pIDList->cidl; i > 0; --i)
902 LPCITEMIDLIST pidl;
904 pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
906 attribs = SFGAO_FOLDER;
907 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
909 if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
911 SHELLEXECUTEINFOW shexinfo;
913 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
914 shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */
915 shexinfo.hwnd = NULL;
916 shexinfo.lpVerb = NULL;
917 shexinfo.lpFile = NULL;
918 shexinfo.lpParameters = NULL;
919 shexinfo.lpDirectory = parent_dir;
920 shexinfo.nShow = SW_NORMAL;
921 shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
923 ShellExecuteExW(&shexinfo); /* Discard error/success info */
925 ILFree((LPITEMIDLIST)shexinfo.lpIDList);
929 GlobalUnlock(stgm.u.hGlobal);
930 ReleaseStgMedium(&stgm);
932 IDataObject_Release(selection);
934 return S_OK;
937 /**********************************************************
938 * ShellView_DoContextMenu()
940 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
941 { UINT uCommand;
942 DWORD wFlags;
943 HMENU hMenu;
944 BOOL fExplore = FALSE;
945 HWND hwndTree = 0;
946 LPCONTEXTMENU pContextMenu = NULL;
947 IContextMenu2 *pCM = NULL;
948 CMINVOKECOMMANDINFO cmi;
950 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
952 /* look, what's selected and create a context menu object of it*/
953 if( ShellView_GetSelections(This) )
955 IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
956 (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
958 if(pContextMenu)
960 TRACE("-- pContextMenu\n");
961 hMenu = CreatePopupMenu();
963 if( hMenu )
965 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
966 if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
968 TRACE("-- explore mode\n");
969 fExplore = TRUE;
972 /* build the flags depending on what we can do with the selected item */
973 wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
975 /* let the ContextMenu merge its items in */
976 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
978 if (This->FolderSettings.fFlags & FWF_DESKTOP)
979 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
981 if( bDefault )
983 TRACE("-- get menu default command\n");
984 uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
986 else
988 TRACE("-- track popup\n");
989 uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
992 if(uCommand > 0)
994 TRACE("-- uCommand=%u\n", uCommand);
995 if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
997 TRACE("-- dlg: OnDefaultCommand\n");
998 if (OnDefaultCommand(This) != S_OK)
1000 ShellView_OpenSelectedItems(This);
1003 else
1005 TRACE("-- explore -- invoke command\n");
1006 ZeroMemory(&cmi, sizeof(cmi));
1007 cmi.cbSize = sizeof(cmi);
1008 cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
1009 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1010 IContextMenu_InvokeCommand(pContextMenu, &cmi);
1013 DestroyMenu(hMenu);
1016 if (pContextMenu)
1017 IContextMenu_Release(pContextMenu);
1020 else /* background context menu */
1022 hMenu = CreatePopupMenu();
1024 pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
1025 IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1027 uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1028 DestroyMenu(hMenu);
1030 TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1032 ZeroMemory(&cmi, sizeof(cmi));
1033 cmi.cbSize = sizeof(cmi);
1034 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1035 cmi.hwnd = This->hWndParent;
1036 IContextMenu2_InvokeCommand(pCM, &cmi);
1038 IContextMenu2_Release(pCM);
1042 /**********************************************************
1043 * ##### message handling #####
1046 /**********************************************************
1047 * ShellView_OnSize()
1049 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1051 TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1053 /*resize the ListView to fit our window*/
1054 if(This->hWndList)
1056 MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1059 return S_OK;
1061 /**********************************************************
1062 * ShellView_OnDeactivate()
1064 * NOTES
1065 * internal
1067 static void ShellView_OnDeactivate(IShellViewImpl * This)
1069 TRACE("%p\n",This);
1071 if(This->uState != SVUIA_DEACTIVATE)
1073 if(This->hMenu)
1075 IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1076 IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1077 DestroyMenu(This->hMenu);
1078 This->hMenu = 0;
1081 This->uState = SVUIA_DEACTIVATE;
1085 /**********************************************************
1086 * ShellView_OnActivate()
1088 static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState)
1089 { OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} };
1090 MENUITEMINFOA mii;
1091 CHAR szText[MAX_PATH];
1093 TRACE("%p uState=%x\n",This,uState);
1095 /*don't do anything if the state isn't really changing */
1096 if(This->uState == uState)
1098 return S_OK;
1101 ShellView_OnDeactivate(This);
1103 /*only do This if we are active */
1104 if(uState != SVUIA_DEACTIVATE)
1106 /*merge the menus */
1107 This->hMenu = CreateMenu();
1109 if(This->hMenu)
1111 IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1112 TRACE("-- after fnInsertMenusSB\n");
1114 /*build the top level menu get the menu item's text*/
1115 strcpy(szText,"dummy 31");
1117 ZeroMemory(&mii, sizeof(mii));
1118 mii.cbSize = sizeof(mii);
1119 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1120 mii.fType = MFT_STRING;
1121 mii.fState = MFS_ENABLED;
1122 mii.dwTypeData = szText;
1123 mii.hSubMenu = ShellView_BuildFileMenu(This);
1125 /*insert our menu into the menu bar*/
1126 if(mii.hSubMenu)
1128 InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1131 /*get the view menu so we can merge with it*/
1132 ZeroMemory(&mii, sizeof(mii));
1133 mii.cbSize = sizeof(mii);
1134 mii.fMask = MIIM_SUBMENU;
1136 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1138 ShellView_MergeViewMenu(This, mii.hSubMenu);
1141 /*add the items that should only be added if we have the focus*/
1142 if(SVUIA_ACTIVATE_FOCUS == uState)
1144 /*get the file menu so we can merge with it */
1145 ZeroMemory(&mii, sizeof(mii));
1146 mii.cbSize = sizeof(mii);
1147 mii.fMask = MIIM_SUBMENU;
1149 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1151 ShellView_MergeFileMenu(This, mii.hSubMenu);
1154 TRACE("-- before fnSetMenuSB\n");
1155 IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1158 This->uState = uState;
1159 TRACE("--\n");
1160 return S_OK;
1163 /**********************************************************
1164 * ShellView_OnSetFocus()
1167 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1169 TRACE("%p\n",This);
1171 /* Tell the browser one of our windows has received the focus. This
1172 should always be done before merging menus (OnActivate merges the
1173 menus) if one of our windows has the focus.*/
1175 IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1176 ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1178 /* Set the focus to the listview */
1179 SetFocus(This->hWndList);
1181 /* Notify the ICommDlgBrowser interface */
1182 OnStateChange(This,CDBOSC_SETFOCUS);
1184 return 0;
1187 /**********************************************************
1188 * ShellView_OnKillFocus()
1190 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1192 TRACE("(%p) stub\n",This);
1194 ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1195 /* Notify the ICommDlgBrowser */
1196 OnStateChange(This,CDBOSC_KILLFOCUS);
1198 return 0;
1201 /**********************************************************
1202 * ShellView_OnCommand()
1204 * NOTES
1205 * the CmdID's are the ones from the context menu
1207 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1209 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1211 switch(dwCmdID)
1213 case FCIDM_SHVIEW_SMALLICON:
1214 This->FolderSettings.ViewMode = FVM_SMALLICON;
1215 SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1216 CheckToolbar(This);
1217 break;
1219 case FCIDM_SHVIEW_BIGICON:
1220 This->FolderSettings.ViewMode = FVM_ICON;
1221 SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1222 CheckToolbar(This);
1223 break;
1225 case FCIDM_SHVIEW_LISTVIEW:
1226 This->FolderSettings.ViewMode = FVM_LIST;
1227 SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1228 CheckToolbar(This);
1229 break;
1231 case FCIDM_SHVIEW_REPORTVIEW:
1232 This->FolderSettings.ViewMode = FVM_DETAILS;
1233 SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1234 CheckToolbar(This);
1235 break;
1237 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1238 case 0x30:
1239 case 0x31:
1240 case 0x32:
1241 case 0x33:
1242 This->ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30);
1243 This->ListViewSortInfo.bIsAscending = TRUE;
1244 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1245 SendMessageA(This->hWndList, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1246 break;
1248 default:
1249 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID);
1251 return 0;
1254 /**********************************************************
1255 * ShellView_OnNotify()
1258 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1259 { LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1260 NMLVDISPINFOA *lpdi = (NMLVDISPINFOA *)lpnmh;
1261 LPITEMIDLIST pidl;
1263 TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1265 switch(lpnmh->code)
1267 case NM_SETFOCUS:
1268 TRACE("-- NM_SETFOCUS %p\n",This);
1269 ShellView_OnSetFocus(This);
1270 break;
1272 case NM_KILLFOCUS:
1273 TRACE("-- NM_KILLFOCUS %p\n",This);
1274 ShellView_OnDeactivate(This);
1275 /* Notify the ICommDlgBrowser interface */
1276 OnStateChange(This,CDBOSC_KILLFOCUS);
1277 break;
1279 case NM_CUSTOMDRAW:
1280 TRACE("-- NM_CUSTOMDRAW %p\n",This);
1281 return CDRF_DODEFAULT;
1283 case NM_RELEASEDCAPTURE:
1284 TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1285 break;
1287 case NM_CLICK:
1288 TRACE("-- NM_CLICK %p\n",This);
1289 break;
1291 case NM_RCLICK:
1292 TRACE("-- NM_RCLICK %p\n",This);
1293 break;
1295 case NM_DBLCLK:
1296 TRACE("-- NM_DBLCLK %p\n",This);
1297 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1298 break;
1300 case NM_RETURN:
1301 TRACE("-- NM_DBLCLK %p\n",This);
1302 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1303 break;
1305 case HDN_ENDTRACKA:
1306 TRACE("-- HDN_ENDTRACKA %p\n",This);
1307 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1308 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1309 break;
1311 case LVN_DELETEITEM:
1312 TRACE("-- LVN_DELETEITEM %p\n",This);
1313 SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/
1314 break;
1316 case LVN_DELETEALLITEMS:
1317 TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1318 return FALSE;
1320 case LVN_INSERTITEM:
1321 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1322 break;
1324 case LVN_ITEMACTIVATE:
1325 TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1326 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1327 break;
1329 case LVN_COLUMNCLICK:
1330 This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1331 if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1333 This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1335 else
1337 This->ListViewSortInfo.bIsAscending = TRUE;
1339 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1341 SendMessageA(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1342 break;
1344 case LVN_GETDISPINFOA:
1345 case LVN_GETDISPINFOW:
1346 TRACE("-- LVN_GETDISPINFO %p\n",This);
1347 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1349 if(lpdi->item.mask & LVIF_TEXT) /* text requested */
1351 if (This->pSF2Parent)
1353 SHELLDETAILS sd;
1354 IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1355 if (lpnmh->code == LVN_GETDISPINFOA)
1357 StrRetToStrNA( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1358 TRACE("-- text=%s\n",lpdi->item.pszText);
1360 else /* LVN_GETDISPINFOW */
1362 StrRetToStrNW( ((NMLVDISPINFOW *)lpdi)->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1363 TRACE("-- text=%s\n",debugstr_w((WCHAR*)(lpdi->item.pszText)));
1366 else
1368 FIXME("no SF2\n");
1371 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1373 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1375 break;
1377 case LVN_ITEMCHANGED:
1378 TRACE("-- LVN_ITEMCHANGED %p\n",This);
1379 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1380 break;
1382 case LVN_BEGINDRAG:
1383 case LVN_BEGINRDRAG:
1384 TRACE("-- LVN_BEGINDRAG\n");
1386 if (ShellView_GetSelections(This))
1388 IDataObject * pda;
1389 DWORD dwAttributes = SFGAO_CANLINK;
1390 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1392 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1394 IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource); /* own DropSource interface */
1396 if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1398 if (dwAttributes & SFGAO_CANLINK)
1400 dwEffect |= DROPEFFECT_LINK;
1404 if (pds)
1406 DWORD dwEffect;
1407 DoDragDrop(pda, pds, dwEffect, &dwEffect);
1409 IDataObject_Release(pda);
1412 break;
1414 case LVN_BEGINLABELEDITA:
1416 DWORD dwAttr = SFGAO_CANRENAME;
1417 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1419 TRACE("-- LVN_BEGINLABELEDITA %p\n",This);
1421 IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1422 if (SFGAO_CANRENAME & dwAttr)
1424 return FALSE;
1426 return TRUE;
1429 case LVN_ENDLABELEDITA:
1431 TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1432 if (lpdi->item.pszText)
1434 HRESULT hr;
1435 WCHAR wszNewName[MAX_PATH];
1436 LVITEMA lvItem;
1438 lvItem.iItem = lpdi->item.iItem;
1439 lvItem.iSubItem = 0;
1440 lvItem.mask = LVIF_PARAM;
1441 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
1443 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1444 if (!MultiByteToWideChar( CP_ACP, 0, lpdi->item.pszText, -1, wszNewName, MAX_PATH ))
1445 wszNewName[MAX_PATH-1] = 0;
1446 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, wszNewName, SHGDN_INFOLDER, &pidl);
1448 if(SUCCEEDED(hr) && pidl)
1450 lvItem.mask = LVIF_PARAM;
1451 lvItem.lParam = (LPARAM)pidl;
1452 SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem);
1453 return TRUE;
1456 return FALSE;
1459 case LVN_KEYDOWN:
1461 /* MSG msg;
1462 msg.hwnd = This->hWnd;
1463 msg.message = WM_KEYDOWN;
1464 msg.wParam = plvKeyDown->wVKey;
1465 msg.lParam = 0;
1466 msg.time = 0;
1467 msg.pt = 0;*/
1469 LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1471 /* initiate a rename of the selected file or directory */
1472 if(plvKeyDown->wVKey == VK_F2)
1474 /* see how many files are selected */
1475 int i = ListView_GetSelectedCount(This->hWndList);
1477 /* get selected item */
1478 if(i == 1)
1480 /* get selected item */
1481 i = ListView_GetNextItem(This->hWndList, -1,
1482 LVNI_SELECTED);
1484 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1485 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
1488 #if 0
1489 TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1490 #endif
1491 else if(plvKeyDown->wVKey == VK_DELETE)
1493 UINT i;
1494 int item_index;
1495 LVITEMA item;
1496 LPITEMIDLIST* pItems;
1497 ISFHelper *psfhlp;
1499 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1500 (LPVOID*)&psfhlp);
1502 if (psfhlp == NULL)
1503 break;
1505 if(!(i = ListView_GetSelectedCount(This->hWndList)))
1506 break;
1508 /* allocate memory for the pidl array */
1509 pItems = HeapAlloc(GetProcessHeap(), 0,
1510 sizeof(LPITEMIDLIST) * i);
1512 /* retrieve all selected items */
1513 i = 0;
1514 item_index = -1;
1515 while(ListView_GetSelectedCount(This->hWndList) > i)
1517 /* get selected item */
1518 item_index = ListView_GetNextItem(This->hWndList,
1519 item_index, LVNI_SELECTED);
1520 item.iItem = item_index;
1521 item.mask = LVIF_PARAM;
1522 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &item);
1524 /* get item pidl */
1525 pItems[i] = (LPITEMIDLIST)item.lParam;
1527 i++;
1530 /* perform the item deletion */
1531 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1533 /* free pidl array memory */
1534 HeapFree(GetProcessHeap(), 0, pItems);
1537 /* Initiate a refresh */
1538 else if(plvKeyDown->wVKey == VK_F5)
1540 IShellView_Refresh((IShellView*)This);
1543 else
1544 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1546 break;
1548 default:
1549 TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1550 break;
1552 return 0;
1555 /**********************************************************
1556 * ShellView_OnChange()
1559 static LRESULT ShellView_OnChange(IShellViewImpl * This, LPITEMIDLIST * Pidls, LONG wEventId)
1562 TRACE("(%p)(%p,%p,0x%08x)\n", This, Pidls[0], Pidls[1], wEventId);
1563 switch(wEventId)
1565 case SHCNE_MKDIR:
1566 case SHCNE_CREATE:
1567 LV_AddItem(This, Pidls[0]);
1568 break;
1569 case SHCNE_RMDIR:
1570 case SHCNE_DELETE:
1571 LV_DeleteItem(This, Pidls[0]);
1572 break;
1573 case SHCNE_RENAMEFOLDER:
1574 case SHCNE_RENAMEITEM:
1575 LV_RenameItem(This, Pidls[0], Pidls[1]);
1576 break;
1577 case SHCNE_UPDATEITEM:
1578 break;
1580 return TRUE;
1582 /**********************************************************
1583 * ShellView_WndProc
1586 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1588 IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1589 LPCREATESTRUCTA lpcs;
1591 TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1593 switch (uMessage)
1595 case WM_NCCREATE:
1596 lpcs = (LPCREATESTRUCTA)lParam;
1597 pThis = (IShellViewImpl*)(lpcs->lpCreateParams);
1598 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1599 pThis->hWnd = hWnd; /*set the window handle*/
1600 break;
1602 case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1603 case WM_SETFOCUS: return ShellView_OnSetFocus(pThis);
1604 case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis);
1605 case WM_CREATE: return ShellView_OnCreate(pThis);
1606 case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1607 case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1608 case WM_COMMAND: return ShellView_OnCommand(pThis,
1609 GET_WM_COMMAND_ID(wParam, lParam),
1610 GET_WM_COMMAND_CMD(wParam, lParam),
1611 GET_WM_COMMAND_HWND(wParam, lParam));
1612 case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (LPITEMIDLIST*)wParam, (LONG)lParam);
1614 case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1615 return 0;
1617 case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
1618 break;
1620 case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0);
1622 case WM_DESTROY:
1623 RevokeDragDrop(pThis->hWnd);
1624 SHChangeNotifyDeregister(pThis->hNotify);
1625 break;
1627 case WM_ERASEBKGND:
1628 if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1629 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1630 return 1;
1631 break;
1634 return DefWindowProcA (hWnd, uMessage, wParam, lParam);
1636 /**********************************************************
1639 * The INTERFACE of the IShellView object
1642 **********************************************************
1643 * IShellView_QueryInterface
1645 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj)
1647 IShellViewImpl *This = (IShellViewImpl *)iface;
1649 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1651 *ppvObj = NULL;
1653 if(IsEqualIID(riid, &IID_IUnknown))
1655 *ppvObj = This;
1657 else if(IsEqualIID(riid, &IID_IShellView))
1659 *ppvObj = (IShellView*)This;
1661 else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1663 *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget);
1665 else if(IsEqualIID(riid, &IID_IDropTarget))
1667 *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
1669 else if(IsEqualIID(riid, &IID_IDropSource))
1671 *ppvObj = (IDropSource*)&(This->lpvtblDropSource);
1673 else if(IsEqualIID(riid, &IID_IViewObject))
1675 *ppvObj = (IViewObject*)&(This->lpvtblViewObject);
1678 if(*ppvObj)
1680 IUnknown_AddRef( (IUnknown*)*ppvObj );
1681 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1682 return S_OK;
1684 TRACE("-- Interface: E_NOINTERFACE\n");
1685 return E_NOINTERFACE;
1688 /**********************************************************
1689 * IShellView_AddRef
1691 static ULONG WINAPI IShellView_fnAddRef(IShellView * iface)
1693 IShellViewImpl *This = (IShellViewImpl *)iface;
1694 ULONG refCount = InterlockedIncrement(&This->ref);
1696 TRACE("(%p)->(count=%u)\n", This, refCount - 1);
1698 return refCount;
1700 /**********************************************************
1701 * IShellView_Release
1703 static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
1705 IShellViewImpl *This = (IShellViewImpl *)iface;
1706 ULONG refCount = InterlockedDecrement(&This->ref);
1708 TRACE("(%p)->(count=%i)\n", This, refCount + 1);
1710 if (!refCount)
1712 TRACE(" destroying IShellView(%p)\n",This);
1714 DestroyWindow(This->hWndList);
1716 if(This->pSFParent)
1717 IShellFolder_Release(This->pSFParent);
1719 if(This->pSF2Parent)
1720 IShellFolder2_Release(This->pSF2Parent);
1722 SHFree(This->apidl);
1724 if(This->pAdvSink)
1725 IAdviseSink_Release(This->pAdvSink);
1727 HeapFree(GetProcessHeap(),0,This);
1729 return refCount;
1732 /**********************************************************
1733 * ShellView_GetWindow
1735 static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd)
1737 IShellViewImpl *This = (IShellViewImpl *)iface;
1739 TRACE("(%p)\n",This);
1741 *phWnd = This->hWnd;
1743 return S_OK;
1746 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode)
1748 IShellViewImpl *This = (IShellViewImpl *)iface;
1750 FIXME("(%p) stub\n",This);
1752 return E_NOTIMPL;
1755 /**********************************************************
1756 * IShellView_TranslateAccelerator
1758 * FIXME:
1759 * use the accel functions
1761 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg)
1763 #if 0
1764 IShellViewImpl *This = (IShellViewImpl *)iface;
1766 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1767 #endif
1769 if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1771 TRACE("-- key=0x04%lx\n",lpmsg->wParam) ;
1773 return S_FALSE; /* not handled */
1776 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable)
1778 IShellViewImpl *This = (IShellViewImpl *)iface;
1780 FIXME("(%p) stub\n",This);
1782 return E_NOTIMPL;
1785 static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState)
1787 IShellViewImpl *This = (IShellViewImpl *)iface;
1790 CHAR szName[MAX_PATH];
1792 LRESULT lResult;
1793 int nPartArray[1] = {-1};
1795 TRACE("(%p)->(state=%x) stub\n",This, uState);
1797 /*don't do anything if the state isn't really changing*/
1798 if(This->uState == uState)
1800 return S_OK;
1803 /*OnActivate handles the menu merging and internal state*/
1804 ShellView_OnActivate(This, uState);
1806 /*only do This if we are active*/
1807 if(uState != SVUIA_DEACTIVATE)
1811 GetFolderPath is not a method of IShellFolder
1812 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1814 /* set the number of parts */
1815 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1816 (LPARAM)nPartArray, &lResult);
1818 /* set the text for the parts */
1820 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1821 0, (LPARAM)szName, &lResult);
1825 return S_OK;
1828 static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface)
1830 IShellViewImpl *This = (IShellViewImpl *)iface;
1832 TRACE("(%p)\n",This);
1834 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
1835 ShellView_FillList(This);
1837 return S_OK;
1840 static HRESULT WINAPI IShellView_fnCreateViewWindow(
1841 IShellView * iface,
1842 IShellView *lpPrevView,
1843 LPCFOLDERSETTINGS lpfs,
1844 IShellBrowser * psb,
1845 RECT * prcView,
1846 HWND *phWnd)
1848 IShellViewImpl *This = (IShellViewImpl *)iface;
1850 WNDCLASSA wc;
1851 *phWnd = 0;
1854 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd);
1855 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);
1857 /*set up the member variables*/
1858 This->pShellBrowser = psb;
1859 This->FolderSettings = *lpfs;
1861 /*get our parent window*/
1862 IShellBrowser_AddRef(This->pShellBrowser);
1863 IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
1865 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1866 This->pCommDlgBrowser=NULL;
1867 if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser,
1868 (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser)))
1870 TRACE("-- CommDlgBrowser\n");
1873 /*if our window class has not been registered, then do so*/
1874 if(!GetClassInfoA(shell32_hInstance, SV_CLASS_NAME, &wc))
1876 ZeroMemory(&wc, sizeof(wc));
1877 wc.style = CS_HREDRAW | CS_VREDRAW;
1878 wc.lpfnWndProc = ShellView_WndProc;
1879 wc.cbClsExtra = 0;
1880 wc.cbWndExtra = 0;
1881 wc.hInstance = shell32_hInstance;
1882 wc.hIcon = 0;
1883 wc.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
1884 wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
1885 wc.lpszMenuName = NULL;
1886 wc.lpszClassName = SV_CLASS_NAME;
1888 if(!RegisterClassA(&wc))
1889 return E_FAIL;
1892 *phWnd = CreateWindowExA(0,
1893 SV_CLASS_NAME,
1894 NULL,
1895 WS_CHILD | WS_TABSTOP,
1896 prcView->left,
1897 prcView->top,
1898 prcView->right - prcView->left,
1899 prcView->bottom - prcView->top,
1900 This->hWndParent,
1902 shell32_hInstance,
1903 (LPVOID)This);
1905 CheckToolbar(This);
1907 if(!*phWnd) return E_FAIL;
1909 SetWindowPos(*phWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
1910 UpdateWindow(*phWnd);
1912 return S_OK;
1915 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
1917 IShellViewImpl *This = (IShellViewImpl *)iface;
1919 TRACE("(%p)\n",This);
1921 /*Make absolutely sure all our UI is cleaned up.*/
1922 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1924 if(This->hMenu)
1926 DestroyMenu(This->hMenu);
1929 DestroyWindow(This->hWnd);
1930 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1931 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1934 return S_OK;
1937 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs)
1939 IShellViewImpl *This = (IShellViewImpl *)iface;
1941 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1942 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1944 if (!lpfs) return E_INVALIDARG;
1946 *lpfs = This->FolderSettings;
1947 return NOERROR;
1950 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1952 IShellViewImpl *This = (IShellViewImpl *)iface;
1954 FIXME("(%p) stub\n",This);
1956 return E_NOTIMPL;
1959 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface)
1961 IShellViewImpl *This = (IShellViewImpl *)iface;
1963 FIXME("(%p) stub\n",This);
1965 return S_OK;
1968 static HRESULT WINAPI IShellView_fnSelectItem(
1969 IShellView * iface,
1970 LPCITEMIDLIST pidl,
1971 UINT uFlags)
1973 IShellViewImpl *This = (IShellViewImpl *)iface;
1974 int i;
1976 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
1978 i = LV_FindItemByPidl(This, pidl);
1980 if (i != -1)
1982 LVITEMA lvItem;
1984 if(uFlags & SVSI_ENSUREVISIBLE)
1985 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1987 lvItem.mask = LVIF_STATE;
1988 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
1989 lvItem.iItem = 0;
1990 lvItem.iSubItem = 0;
1992 while(SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem))
1994 if (lvItem.iItem == i)
1996 if (uFlags & SVSI_SELECT)
1997 lvItem.state |= LVIS_SELECTED;
1998 else
1999 lvItem.state &= ~LVIS_SELECTED;
2001 if(uFlags & SVSI_FOCUSED)
2002 lvItem.state &= ~LVIS_FOCUSED;
2004 else
2006 if (uFlags & SVSI_DESELECTOTHERS)
2007 lvItem.state &= ~LVIS_SELECTED;
2009 SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem);
2010 lvItem.iItem++;
2014 if(uFlags & SVSI_EDIT)
2015 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
2018 return S_OK;
2021 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
2023 IShellViewImpl *This = (IShellViewImpl *)iface;
2025 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2027 *ppvOut = NULL;
2029 switch(uItem)
2031 case SVGIO_BACKGROUND:
2032 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2033 break;
2035 case SVGIO_SELECTION:
2036 ShellView_GetSelections(This);
2037 IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2038 break;
2040 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2042 if(!*ppvOut) return E_OUTOFMEMORY;
2044 return S_OK;
2047 static const IShellViewVtbl svvt =
2049 IShellView_fnQueryInterface,
2050 IShellView_fnAddRef,
2051 IShellView_fnRelease,
2052 IShellView_fnGetWindow,
2053 IShellView_fnContextSensitiveHelp,
2054 IShellView_fnTranslateAccelerator,
2055 IShellView_fnEnableModeless,
2056 IShellView_fnUIActivate,
2057 IShellView_fnRefresh,
2058 IShellView_fnCreateViewWindow,
2059 IShellView_fnDestroyViewWindow,
2060 IShellView_fnGetCurrentInfo,
2061 IShellView_fnAddPropertySheetPages,
2062 IShellView_fnSaveViewState,
2063 IShellView_fnSelectItem,
2064 IShellView_fnGetItemObject
2068 /**********************************************************
2069 * ISVOleCmdTarget_QueryInterface (IUnknown)
2071 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2072 IOleCommandTarget * iface,
2073 REFIID iid,
2074 LPVOID* ppvObj)
2076 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2078 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2081 /**********************************************************
2082 * ISVOleCmdTarget_AddRef (IUnknown)
2084 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2085 IOleCommandTarget * iface)
2087 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2089 return IShellFolder_AddRef((IShellFolder*)This);
2092 /**********************************************************
2093 * ISVOleCmdTarget_Release (IUnknown)
2095 static ULONG WINAPI ISVOleCmdTarget_Release(
2096 IOleCommandTarget * iface)
2098 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2100 return IShellFolder_Release((IShellFolder*)This);
2103 /**********************************************************
2104 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2106 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2107 IOleCommandTarget *iface,
2108 const GUID* pguidCmdGroup,
2109 ULONG cCmds,
2110 OLECMD * prgCmds,
2111 OLECMDTEXT* pCmdText)
2113 UINT i;
2114 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2116 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2117 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2119 if (!prgCmds)
2120 return E_POINTER;
2121 for (i = 0; i < cCmds; i++)
2123 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2124 prgCmds[i].cmdf = 0;
2126 return OLECMDERR_E_UNKNOWNGROUP;
2129 /**********************************************************
2130 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2132 * nCmdID is the OLECMDID_* enumeration
2134 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2135 IOleCommandTarget *iface,
2136 const GUID* pguidCmdGroup,
2137 DWORD nCmdID,
2138 DWORD nCmdexecopt,
2139 VARIANT* pvaIn,
2140 VARIANT* pvaOut)
2142 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2144 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2145 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2147 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2148 (nCmdID == 0x29) &&
2149 (nCmdexecopt == 4) && pvaOut)
2150 return S_OK;
2151 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2152 (nCmdID == 9) &&
2153 (nCmdexecopt == 0))
2154 return 1;
2156 return OLECMDERR_E_UNKNOWNGROUP;
2159 static const IOleCommandTargetVtbl ctvt =
2161 ISVOleCmdTarget_QueryInterface,
2162 ISVOleCmdTarget_AddRef,
2163 ISVOleCmdTarget_Release,
2164 ISVOleCmdTarget_QueryStatus,
2165 ISVOleCmdTarget_Exec
2168 /**********************************************************
2169 * ISVDropTarget implementation
2172 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2173 IDropTarget *iface,
2174 REFIID riid,
2175 LPVOID *ppvObj)
2177 IShellViewImpl *This = impl_from_IDropTarget(iface);
2179 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2181 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2184 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2186 IShellViewImpl *This = impl_from_IDropTarget(iface);
2188 TRACE("(%p)->(count=%u)\n",This,This->ref);
2190 return IShellFolder_AddRef((IShellFolder*)This);
2193 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2195 IShellViewImpl *This = impl_from_IDropTarget(iface);
2197 TRACE("(%p)->(count=%u)\n",This,This->ref);
2199 return IShellFolder_Release((IShellFolder*)This);
2202 /******************************************************************************
2203 * drag_notify_subitem [Internal]
2205 * Figure out the shellfolder object, which is currently under the mouse cursor
2206 * and notify it via the IDropTarget interface.
2209 #define SCROLLAREAWIDTH 20
2211 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2212 DWORD *pdwEffect)
2214 LVHITTESTINFO htinfo;
2215 LVITEMA lvItem;
2216 LONG lResult;
2217 HRESULT hr;
2218 RECT clientRect;
2220 /* Map from global to client coordinates and query the index of the listview-item, which is
2221 * currently under the mouse cursor. */
2222 htinfo.pt.x = pt.x;
2223 htinfo.pt.y = pt.y;
2224 htinfo.flags = LVHT_ONITEM;
2225 ScreenToClient(This->hWndList, &htinfo.pt);
2226 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2228 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2229 GetClientRect(This->hWndList, &clientRect);
2230 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2231 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2232 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2234 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2235 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2236 if (htinfo.pt.x < SCROLLAREAWIDTH)
2237 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2238 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2239 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2240 if (htinfo.pt.y < SCROLLAREAWIDTH)
2241 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2242 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2243 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2245 } else {
2246 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2248 This->ptLastMousePos = htinfo.pt;
2250 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2251 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2252 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2254 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2255 if (This->pCurDropTarget) {
2256 IDropTarget_DragLeave(This->pCurDropTarget);
2257 IDropTarget_Release(This->pCurDropTarget);
2258 This->pCurDropTarget = NULL;
2261 This->iDragOverItem = lResult;
2262 if (lResult == -1) {
2263 /* We are not above one of the listview's subitems. Bind to the parent folder's
2264 * DropTarget interface. */
2265 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2266 (LPVOID*)&This->pCurDropTarget);
2267 } else {
2268 /* Query the relative PIDL of the shellfolder object represented by the currently
2269 * dragged over listview-item ... */
2270 lvItem.mask = LVIF_PARAM;
2271 lvItem.iItem = lResult;
2272 lvItem.iSubItem = 0;
2273 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
2275 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2276 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2277 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2280 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2281 if (FAILED(hr))
2282 return hr;
2284 /* Notify the item just entered via DragEnter. */
2285 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2288 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2289 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2291 IShellViewImpl *This = impl_from_IDropTarget(iface);
2293 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2294 This->pCurDataObject = pDataObject;
2295 IDataObject_AddRef(pDataObject);
2297 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2300 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2301 DWORD *pdwEffect)
2303 IShellViewImpl *This = impl_from_IDropTarget(iface);
2304 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2307 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2308 IShellViewImpl *This = impl_from_IDropTarget(iface);
2310 IDropTarget_DragLeave(This->pCurDropTarget);
2312 IDropTarget_Release(This->pCurDropTarget);
2313 IDataObject_Release(This->pCurDataObject);
2314 This->pCurDataObject = NULL;
2315 This->pCurDropTarget = NULL;
2316 This->iDragOverItem = 0;
2318 return S_OK;
2321 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2322 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2324 IShellViewImpl *This = impl_from_IDropTarget(iface);
2326 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2328 IDropTarget_Release(This->pCurDropTarget);
2329 IDataObject_Release(This->pCurDataObject);
2330 This->pCurDataObject = NULL;
2331 This->pCurDropTarget = NULL;
2332 This->iDragOverItem = 0;
2334 return S_OK;
2337 static const IDropTargetVtbl dtvt =
2339 ISVDropTarget_QueryInterface,
2340 ISVDropTarget_AddRef,
2341 ISVDropTarget_Release,
2342 ISVDropTarget_DragEnter,
2343 ISVDropTarget_DragOver,
2344 ISVDropTarget_DragLeave,
2345 ISVDropTarget_Drop
2348 /**********************************************************
2349 * ISVDropSource implementation
2352 static HRESULT WINAPI ISVDropSource_QueryInterface(
2353 IDropSource *iface,
2354 REFIID riid,
2355 LPVOID *ppvObj)
2357 IShellViewImpl *This = impl_from_IDropSource(iface);
2359 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2361 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2364 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2366 IShellViewImpl *This = impl_from_IDropSource(iface);
2368 TRACE("(%p)->(count=%u)\n",This,This->ref);
2370 return IShellFolder_AddRef((IShellFolder*)This);
2373 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2375 IShellViewImpl *This = impl_from_IDropSource(iface);
2377 TRACE("(%p)->(count=%u)\n",This,This->ref);
2379 return IShellFolder_Release((IShellFolder*)This);
2381 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2382 IDropSource *iface,
2383 BOOL fEscapePressed,
2384 DWORD grfKeyState)
2386 IShellViewImpl *This = impl_from_IDropSource(iface);
2387 TRACE("(%p)\n",This);
2389 if (fEscapePressed)
2390 return DRAGDROP_S_CANCEL;
2391 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2392 return DRAGDROP_S_DROP;
2393 else
2394 return NOERROR;
2397 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2398 IDropSource *iface,
2399 DWORD dwEffect)
2401 IShellViewImpl *This = impl_from_IDropSource(iface);
2402 TRACE("(%p)\n",This);
2404 return DRAGDROP_S_USEDEFAULTCURSORS;
2407 static const IDropSourceVtbl dsvt =
2409 ISVDropSource_QueryInterface,
2410 ISVDropSource_AddRef,
2411 ISVDropSource_Release,
2412 ISVDropSource_QueryContinueDrag,
2413 ISVDropSource_GiveFeedback
2415 /**********************************************************
2416 * ISVViewObject implementation
2419 static HRESULT WINAPI ISVViewObject_QueryInterface(
2420 IViewObject *iface,
2421 REFIID riid,
2422 LPVOID *ppvObj)
2424 IShellViewImpl *This = impl_from_IViewObject(iface);
2426 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2428 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2431 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2433 IShellViewImpl *This = impl_from_IViewObject(iface);
2435 TRACE("(%p)->(count=%u)\n",This,This->ref);
2437 return IShellFolder_AddRef((IShellFolder*)This);
2440 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2442 IShellViewImpl *This = impl_from_IViewObject(iface);
2444 TRACE("(%p)->(count=%u)\n",This,This->ref);
2446 return IShellFolder_Release((IShellFolder*)This);
2449 static HRESULT WINAPI ISVViewObject_Draw(
2450 IViewObject *iface,
2451 DWORD dwDrawAspect,
2452 LONG lindex,
2453 void* pvAspect,
2454 DVTARGETDEVICE* ptd,
2455 HDC hdcTargetDev,
2456 HDC hdcDraw,
2457 LPCRECTL lprcBounds,
2458 LPCRECTL lprcWBounds,
2459 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2460 ULONG_PTR dwContinue)
2463 IShellViewImpl *This = impl_from_IViewObject(iface);
2465 FIXME("Stub: This=%p\n",This);
2467 return E_NOTIMPL;
2469 static HRESULT WINAPI ISVViewObject_GetColorSet(
2470 IViewObject *iface,
2471 DWORD dwDrawAspect,
2472 LONG lindex,
2473 void *pvAspect,
2474 DVTARGETDEVICE* ptd,
2475 HDC hicTargetDevice,
2476 LOGPALETTE** ppColorSet)
2479 IShellViewImpl *This = impl_from_IViewObject(iface);
2481 FIXME("Stub: This=%p\n",This);
2483 return E_NOTIMPL;
2485 static HRESULT WINAPI ISVViewObject_Freeze(
2486 IViewObject *iface,
2487 DWORD dwDrawAspect,
2488 LONG lindex,
2489 void* pvAspect,
2490 DWORD* pdwFreeze)
2493 IShellViewImpl *This = impl_from_IViewObject(iface);
2495 FIXME("Stub: This=%p\n",This);
2497 return E_NOTIMPL;
2499 static HRESULT WINAPI ISVViewObject_Unfreeze(
2500 IViewObject *iface,
2501 DWORD dwFreeze)
2504 IShellViewImpl *This = impl_from_IViewObject(iface);
2506 FIXME("Stub: This=%p\n",This);
2508 return E_NOTIMPL;
2510 static HRESULT WINAPI ISVViewObject_SetAdvise(
2511 IViewObject *iface,
2512 DWORD aspects,
2513 DWORD advf,
2514 IAdviseSink* pAdvSink)
2517 IShellViewImpl *This = impl_from_IViewObject(iface);
2519 FIXME("partial stub: %p %08x %08x %p\n",
2520 This, aspects, advf, pAdvSink);
2522 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2523 This->pAdvSink = pAdvSink;
2524 This->dwAspects = aspects;
2525 This->dwAdvf = advf;
2527 return S_OK;
2530 static HRESULT WINAPI ISVViewObject_GetAdvise(
2531 IViewObject *iface,
2532 DWORD* pAspects,
2533 DWORD* pAdvf,
2534 IAdviseSink** ppAdvSink)
2537 IShellViewImpl *This = impl_from_IViewObject(iface);
2539 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2540 This, pAspects, pAdvf, ppAdvSink);
2542 if( ppAdvSink )
2544 IAdviseSink_AddRef( This->pAdvSink );
2545 *ppAdvSink = This->pAdvSink;
2547 if( pAspects )
2548 *pAspects = This->dwAspects;
2549 if( pAdvf )
2550 *pAdvf = This->dwAdvf;
2552 return S_OK;
2556 static const IViewObjectVtbl vovt =
2558 ISVViewObject_QueryInterface,
2559 ISVViewObject_AddRef,
2560 ISVViewObject_Release,
2561 ISVViewObject_Draw,
2562 ISVViewObject_GetColorSet,
2563 ISVViewObject_Freeze,
2564 ISVViewObject_Unfreeze,
2565 ISVViewObject_SetAdvise,
2566 ISVViewObject_GetAdvise