shell32: Don't use uninitialized item.mask in shlview.
[wine.git] / dlls / shell32 / shlview.c
blobbb07108825ff95c550c5226d0980ec3f717cf4e4
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * FIXME: The order by part of the background context menu should be
24 * buily according to the columns shown.
26 * FIXME: Load/Save the view state from/into the stream provied by
27 * the ShellBrowser
29 * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
31 * FIXME: ShellView_FillList: consider sort orders
33 * FIXME: implement the drag and drop in the old (msg-based) way
35 * FIXME: when the ShellView_WndProc gets a WM_NCDESTROY should we do a
36 * Release() ???
39 #include "config.h"
40 #include "wine/port.h"
42 #include <stdarg.h>
43 #include <stdlib.h>
44 #include <string.h>
46 #define COBJMACROS
47 #define NONAMELESSUNION
48 #define NONAMELESSSTRUCT
50 #include "windef.h"
51 #include "winerror.h"
52 #include "winbase.h"
53 #include "winnls.h"
54 #include "objbase.h"
55 #include "servprov.h"
56 #include "shlguid.h"
57 #include "wingdi.h"
58 #include "winuser.h"
59 #include "shlobj.h"
60 #include "undocshell.h"
61 #include "shresdef.h"
62 #include "wine/debug.h"
64 #include "docobj.h"
65 #include "pidl.h"
66 #include "shell32_main.h"
67 #include "shellfolder.h"
69 WINE_DEFAULT_DEBUG_CHANNEL(shell);
71 typedef struct
72 { BOOL bIsAscending;
73 INT nHeaderID;
74 INT nLastHeaderID;
75 }LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;
77 typedef struct
79 const IShellViewVtbl* lpVtbl;
80 LONG ref;
81 const IOleCommandTargetVtbl* lpvtblOleCommandTarget;
82 const IDropTargetVtbl* lpvtblDropTarget;
83 const IDropSourceVtbl* lpvtblDropSource;
84 const IViewObjectVtbl* lpvtblViewObject;
85 IShellFolder* pSFParent;
86 IShellFolder2* pSF2Parent;
87 IShellBrowser* pShellBrowser;
88 ICommDlgBrowser* pCommDlgBrowser;
89 HWND hWnd; /* SHELLDLL_DefView */
90 HWND hWndList; /* ListView control */
91 HWND hWndParent;
92 FOLDERSETTINGS FolderSettings;
93 HMENU hMenu;
94 UINT uState;
95 UINT cidl;
96 LPITEMIDLIST *apidl;
97 LISTVIEW_SORT_INFO ListViewSortInfo;
98 ULONG hNotify; /* change notification handle */
99 HANDLE hAccel;
100 DWORD dwAspects;
101 DWORD dwAdvf;
102 IAdviseSink *pAdvSink;
103 IDropTarget* pCurDropTarget; /* The sub-item, which is currently dragged over */
104 IDataObject* pCurDataObject; /* The dragged data-object */
105 LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */
106 UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
107 POINT ptLastMousePos; /* Mouse position at last DragOver call */
108 } IShellViewImpl;
110 static const IShellViewVtbl svvt;
111 static const IOleCommandTargetVtbl ctvt;
112 static const IDropTargetVtbl dtvt;
113 static const IDropSourceVtbl dsvt;
114 static const IViewObjectVtbl vovt;
117 static inline IShellViewImpl *impl_from_IOleCommandTarget( IOleCommandTarget *iface )
119 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblOleCommandTarget));
122 static inline IShellViewImpl *impl_from_IDropTarget( IDropTarget *iface )
124 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropTarget));
127 static inline IShellViewImpl *impl_from_IDropSource( IDropSource *iface )
129 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropSource));
132 static inline IShellViewImpl *impl_from_IViewObject( IViewObject *iface )
134 return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblViewObject));
137 /* ListView Header ID's */
138 #define LISTVIEW_COLUMN_NAME 0
139 #define LISTVIEW_COLUMN_SIZE 1
140 #define LISTVIEW_COLUMN_TYPE 2
141 #define LISTVIEW_COLUMN_TIME 3
142 #define LISTVIEW_COLUMN_ATTRIB 4
144 /*menu items */
145 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
146 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
147 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
149 #define ID_LISTVIEW 1
151 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
153 /*windowsx.h */
154 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
155 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
156 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
159 Items merged into the toolbar and and the filemenu
161 typedef struct
162 { int idCommand;
163 int iImage;
164 int idButtonString;
165 int idMenuString;
166 BYTE bState;
167 BYTE bStyle;
168 } MYTOOLINFO, *LPMYTOOLINFO;
170 MYTOOLINFO Tools[] =
172 { FCIDM_SHVIEW_BIGICON, 0, 0, IDS_VIEW_LARGE, TBSTATE_ENABLED, BTNS_BUTTON },
173 { FCIDM_SHVIEW_SMALLICON, 0, 0, IDS_VIEW_SMALL, TBSTATE_ENABLED, BTNS_BUTTON },
174 { FCIDM_SHVIEW_LISTVIEW, 0, 0, IDS_VIEW_LIST, TBSTATE_ENABLED, BTNS_BUTTON },
175 { FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON },
176 { -1, 0, 0, 0, 0, 0}
179 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
181 /**********************************************************
182 * IShellView_Constructor
184 IShellView * IShellView_Constructor( IShellFolder * pFolder)
185 { IShellViewImpl * sv;
186 sv=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellViewImpl));
187 sv->ref=1;
188 sv->lpVtbl=&svvt;
189 sv->lpvtblOleCommandTarget=&ctvt;
190 sv->lpvtblDropTarget=&dtvt;
191 sv->lpvtblDropSource=&dsvt;
192 sv->lpvtblViewObject=&vovt;
194 sv->pSFParent = pFolder;
195 if(pFolder) IShellFolder_AddRef(pFolder);
196 IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent);
198 sv->pCurDropTarget = NULL;
199 sv->pCurDataObject = NULL;
200 sv->iDragOverItem = 0;
201 sv->cScrollDelay = 0;
202 sv->ptLastMousePos.x = 0;
203 sv->ptLastMousePos.y = 0;
205 TRACE("(%p)->(%p)\n",sv, pFolder);
206 return (IShellView *) sv;
209 /**********************************************************
211 * ##### helperfunctions for communication with ICommDlgBrowser #####
213 static BOOL IsInCommDlg(IShellViewImpl * This)
214 { return(This->pCommDlgBrowser != NULL);
217 static HRESULT IncludeObject(IShellViewImpl * This, LPCITEMIDLIST pidl)
219 HRESULT ret = S_OK;
221 if ( IsInCommDlg(This) )
223 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
224 ret = ICommDlgBrowser_IncludeObject(This->pCommDlgBrowser, (IShellView*)This, pidl);
225 TRACE("--0x%08lx\n", ret);
227 return ret;
230 static HRESULT OnDefaultCommand(IShellViewImpl * This)
232 HRESULT ret = S_FALSE;
234 if (IsInCommDlg(This))
236 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
237 ret = ICommDlgBrowser_OnDefaultCommand(This->pCommDlgBrowser, (IShellView*)This);
238 TRACE("-- returns %08lx\n", ret);
240 return ret;
243 static HRESULT OnStateChange(IShellViewImpl * This, UINT uFlags)
245 HRESULT ret = S_FALSE;
247 if (IsInCommDlg(This))
249 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
250 ret = ICommDlgBrowser_OnStateChange(This->pCommDlgBrowser, (IShellView*)This, uFlags);
251 TRACE("--\n");
253 return ret;
255 /**********************************************************
256 * set the toolbar of the filedialog buttons
258 * - activates the buttons from the shellbrowser according to
259 * the view state
261 static void CheckToolbar(IShellViewImpl * This)
263 LRESULT result;
265 TRACE("\n");
267 if (IsInCommDlg(This))
269 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
270 FCIDM_TB_SMALLICON, (This->FolderSettings.ViewMode==FVM_LIST)? TRUE : FALSE, &result);
271 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
272 FCIDM_TB_REPORTVIEW, (This->FolderSettings.ViewMode==FVM_DETAILS)? TRUE : FALSE, &result);
273 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
274 FCIDM_TB_SMALLICON, TRUE, &result);
275 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
276 FCIDM_TB_REPORTVIEW, TRUE, &result);
280 /**********************************************************
282 * ##### helperfunctions for initializing the view #####
284 /**********************************************************
285 * change the style of the listview control
287 static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove)
289 DWORD tmpstyle;
291 TRACE("(%p)\n", This);
293 tmpstyle = GetWindowLongA(This->hWndList, GWL_STYLE);
294 SetWindowLongA(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
297 /**********************************************************
298 * ShellView_CreateList()
300 * - creates the list view window
302 static BOOL ShellView_CreateList (IShellViewImpl * This)
303 { DWORD dwStyle, dwExStyle;
305 TRACE("%p\n",This);
307 dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
308 LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT | LVS_AUTOARRANGE;
309 dwExStyle = WS_EX_CLIENTEDGE;
311 switch (This->FolderSettings.ViewMode)
313 case FVM_ICON: dwStyle |= LVS_ICON; break;
314 case FVM_DETAILS: dwStyle |= LVS_REPORT; break;
315 case FVM_SMALLICON: dwStyle |= LVS_SMALLICON; break;
316 case FVM_LIST: dwStyle |= LVS_LIST; break;
317 default: dwStyle |= LVS_LIST; break;
320 if (This->FolderSettings.fFlags & FWF_AUTOARRANGE) dwStyle |= LVS_AUTOARRANGE;
321 if (This->FolderSettings.fFlags & FWF_DESKTOP)
322 This->FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
323 if (This->FolderSettings.fFlags & FWF_SINGLESEL) dwStyle |= LVS_SINGLESEL;
324 if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE)
325 dwExStyle &= ~WS_EX_CLIENTEDGE;
327 This->hWndList=CreateWindowExA( dwExStyle,
328 WC_LISTVIEWA,
329 NULL,
330 dwStyle,
331 0,0,0,0,
332 This->hWnd,
333 (HMENU)ID_LISTVIEW,
334 shell32_hInstance,
335 NULL);
337 if(!This->hWndList)
338 return FALSE;
340 This->ListViewSortInfo.bIsAscending = TRUE;
341 This->ListViewSortInfo.nHeaderID = -1;
342 This->ListViewSortInfo.nLastHeaderID = -1;
344 if (This->FolderSettings.fFlags & FWF_DESKTOP) {
346 * FIXME: look at the registry value
347 * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
348 * and activate drop shadows if necessary
350 if (0)
351 SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, CLR_NONE);
352 else
353 SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, GetSysColor(COLOR_DESKTOP));
355 SendMessageW(This->hWndList, LVM_SETTEXTCOLOR, 0, RGB(255,255,255));
358 /* UpdateShellSettings(); */
359 return TRUE;
362 /**********************************************************
363 * ShellView_InitList()
365 * - adds all needed columns to the shellview
367 static BOOL ShellView_InitList(IShellViewImpl * This)
369 LVCOLUMNW lvColumn;
370 SHELLDETAILS sd;
371 int i;
372 WCHAR szTemp[50];
374 TRACE("%p\n",This);
376 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
378 lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
379 lvColumn.pszText = szTemp;
381 if (This->pSF2Parent)
383 for (i=0; 1; i++)
385 if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd)))
386 break;
387 lvColumn.fmt = sd.fmt;
388 lvColumn.cx = sd.cxChar*8; /* chars->pixel */
389 StrRetToStrNW( szTemp, 50, &sd.str, NULL);
390 SendMessageW(This->hWndList, LVM_INSERTCOLUMNW, i, (LPARAM) &lvColumn);
393 else
395 FIXME("no SF2\n");
398 SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ShellSmallIconList);
399 SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)ShellBigIconList);
401 return TRUE;
403 /**********************************************************
404 * ShellView_CompareItems()
406 * NOTES
407 * internal, CALLBACK for DSA_Sort
409 static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
411 int ret;
412 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
414 if(!lpData) return 0;
416 ret = (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2));
417 TRACE("ret=%i\n",ret);
418 return ret;
421 /*************************************************************************
422 * ShellView_ListViewCompareItems
424 * Compare Function for the Listview (FileOpen Dialog)
426 * PARAMS
427 * lParam1 [I] the first ItemIdList to compare with
428 * lParam2 [I] the second ItemIdList to compare with
429 * lpData [I] The column ID for the header Ctrl to process
431 * RETURNS
432 * A negative value if the first item should precede the second,
433 * a positive value if the first item should follow the second,
434 * or zero if the two items are equivalent
436 * NOTES
437 * FIXME: function does what ShellView_CompareItems is supposed to do.
438 * unify it and figure out how to use the undocumented first parameter
439 * of IShellFolder_CompareIDs to do the job this function does and
440 * move this code to IShellFolder.
441 * make LISTVIEW_SORT_INFO obsolete
442 * the way this function works is only usable if we had only
443 * filesystemfolders (25/10/99 jsch)
445 static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
447 INT nDiff=0;
448 FILETIME fd1, fd2;
449 char strName1[MAX_PATH], strName2[MAX_PATH];
450 BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
451 LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1;
452 LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2;
453 LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData;
456 bIsFolder1 = _ILIsFolder(pItemIdList1);
457 bIsFolder2 = _ILIsFolder(pItemIdList2);
458 bIsBothFolder = bIsFolder1 && bIsFolder2;
460 /* When sorting between a File and a Folder, the Folder gets sorted first */
461 if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
463 nDiff = bIsFolder1 ? -1 : 1;
465 else
467 /* Sort by Time: Folders or Files can be sorted */
469 if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
471 _ILGetFileDateTime(pItemIdList1, &fd1);
472 _ILGetFileDateTime(pItemIdList2, &fd2);
473 nDiff = CompareFileTime(&fd2, &fd1);
475 /* Sort by Attribute: Folder or Files can be sorted */
476 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
478 _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH);
479 _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH);
480 nDiff = lstrcmpiA(strName1, strName2);
482 /* Sort by FileName: Folder or Files can be sorted */
483 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
485 /* Sort by Text */
486 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
487 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
488 nDiff = lstrcmpiA(strName1, strName2);
490 /* Sort by File Size, Only valid for Files */
491 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
493 nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0));
495 /* Sort by File Type, Only valid for Files */
496 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
498 /* Sort by Type */
499 _ILGetFileType(pItemIdList1, strName1, MAX_PATH);
500 _ILGetFileType(pItemIdList2, strName2, MAX_PATH);
501 nDiff = lstrcmpiA(strName1, strName2);
504 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
506 if(nDiff == 0)
508 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
509 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
510 nDiff = lstrcmpiA(strName1, strName2);
513 if(!pSortInfo->bIsAscending)
515 nDiff = -nDiff;
518 return nDiff;
522 /**********************************************************
523 * LV_FindItemByPidl()
525 static int LV_FindItemByPidl(
526 IShellViewImpl * This,
527 LPCITEMIDLIST pidl)
529 LVITEMA lvItem;
530 ZeroMemory(&lvItem, sizeof(LVITEMA));
531 lvItem.mask = LVIF_PARAM;
532 for(lvItem.iItem = 0;
533 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
534 lvItem.iItem++)
536 LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam;
537 HRESULT hr = IShellFolder_CompareIDs(This->pSFParent, 0, pidl, currentpidl);
538 if(SUCCEEDED(hr) && !HRESULT_CODE(hr))
540 return lvItem.iItem;
543 return -1;
546 /**********************************************************
547 * LV_AddItem()
549 static BOOLEAN LV_AddItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
551 LVITEMA lvItem;
553 TRACE("(%p)(pidl=%p)\n", This, pidl);
555 ZeroMemory(&lvItem, sizeof(lvItem)); /* create the listview item*/
556 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/
557 lvItem.iItem = ListView_GetItemCount(This->hWndList); /*add the item to the end of the list*/
558 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/
559 lvItem.pszText = LPSTR_TEXTCALLBACKA; /*get text on a callback basis*/
560 lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/
561 return (-1==ListView_InsertItemA(This->hWndList, &lvItem))? FALSE: TRUE;
564 /**********************************************************
565 * LV_DeleteItem()
567 static BOOLEAN LV_DeleteItem(IShellViewImpl * This, LPCITEMIDLIST pidl)
569 int nIndex;
571 TRACE("(%p)(pidl=%p)\n", This, pidl);
573 nIndex = LV_FindItemByPidl(This, ILFindLastID(pidl));
574 return (-1==ListView_DeleteItem(This->hWndList, nIndex))? FALSE: TRUE;
577 /**********************************************************
578 * LV_RenameItem()
580 static BOOLEAN LV_RenameItem(IShellViewImpl * This, LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew )
582 int nItem;
583 LVITEMA lvItem;
585 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This, pidlOld, pidlNew);
587 nItem = LV_FindItemByPidl(This, ILFindLastID(pidlOld));
588 if ( -1 != nItem )
590 ZeroMemory(&lvItem, sizeof(lvItem)); /* create the listview item*/
591 lvItem.mask = LVIF_PARAM; /* only the pidl */
592 lvItem.iItem = nItem;
593 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
595 SHFree((LPITEMIDLIST)lvItem.lParam);
596 lvItem.mask = LVIF_PARAM;
597 lvItem.iItem = nItem;
598 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */
599 SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem);
600 SendMessageA(This->hWndList, LVM_UPDATE, nItem, 0);
601 return TRUE; /* FIXME: better handling */
603 return FALSE;
605 /**********************************************************
606 * ShellView_FillList()
608 * - gets the objectlist from the shellfolder
609 * - sorts the list
610 * - fills the list into the view
613 static INT CALLBACK fill_list( LPVOID ptr, LPVOID arg )
615 LPITEMIDLIST pidl = ptr;
616 IShellViewImpl *This = arg;
617 /* in a commdlg This works as a filemask*/
618 if ( IncludeObject(This, pidl)==S_OK ) LV_AddItem(This, pidl);
619 SHFree(pidl);
620 return TRUE;
623 static HRESULT ShellView_FillList(IShellViewImpl * This)
625 LPENUMIDLIST pEnumIDList;
626 LPITEMIDLIST pidl;
627 DWORD dwFetched;
628 HRESULT hRes;
629 HDPA hdpa;
631 TRACE("%p\n",This);
633 /* get the itemlist from the shfolder*/
634 hRes = IShellFolder_EnumObjects(This->pSFParent,This->hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
635 if (hRes != S_OK)
637 if (hRes==S_FALSE)
638 return(NOERROR);
639 return(hRes);
642 /* create a pointer array */
643 hdpa = DPA_Create(16);
644 if (!hdpa)
646 return(E_OUTOFMEMORY);
649 /* copy the items into the array*/
650 while((S_OK == IEnumIDList_Next(pEnumIDList,1, &pidl, &dwFetched)) && dwFetched)
652 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
654 SHFree(pidl);
658 /* sort the array */
659 DPA_Sort(hdpa, ShellView_CompareItems, (LPARAM)This->pSFParent);
661 /*turn the listview's redrawing off*/
662 SendMessageA(This->hWndList, WM_SETREDRAW, FALSE, 0);
664 DPA_DestroyCallback( hdpa, fill_list, This );
666 /*turn the listview's redrawing back on and force it to draw*/
667 SendMessageA(This->hWndList, WM_SETREDRAW, TRUE, 0);
669 IEnumIDList_Release(pEnumIDList); /* destroy the list*/
671 return S_OK;
674 /**********************************************************
675 * ShellView_OnCreate()
677 static LRESULT ShellView_OnCreate(IShellViewImpl * This)
679 IDropTarget* pdt;
680 SHChangeNotifyEntry ntreg;
681 IPersistFolder2 * ppf2 = NULL;
683 TRACE("%p\n",This);
685 if(ShellView_CreateList(This))
687 if(ShellView_InitList(This))
689 ShellView_FillList(This);
693 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown*)&This->lpVtbl, &IID_IDropTarget, (LPVOID*)&pdt)))
695 RegisterDragDrop(This->hWnd, pdt);
696 IDropTarget_Release(pdt);
699 /* register for receiving notifications */
700 IShellFolder_QueryInterface(This->pSFParent, &IID_IPersistFolder2, (LPVOID*)&ppf2);
701 if (ppf2)
703 IPersistFolder2_GetCurFolder(ppf2, (LPITEMIDLIST*)&ntreg.pidl);
704 ntreg.fRecursive = TRUE;
705 This->hNotify = SHChangeNotifyRegister(This->hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
706 SHFree((LPITEMIDLIST)ntreg.pidl);
707 IPersistFolder2_Release(ppf2);
710 This->hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel");
712 return S_OK;
715 /**********************************************************
716 * #### Handling of the menus ####
719 /**********************************************************
720 * ShellView_BuildFileMenu()
722 static HMENU ShellView_BuildFileMenu(IShellViewImpl * This)
723 { CHAR szText[MAX_PATH];
724 MENUITEMINFOA mii;
725 int nTools,i;
726 HMENU hSubMenu;
728 TRACE("(%p)\n",This);
730 hSubMenu = CreatePopupMenu();
731 if(hSubMenu)
732 { /*get the number of items in our global array*/
733 for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
735 /*add the menu items*/
736 for(i = 0; i < nTools; i++)
738 LoadStringA(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
740 ZeroMemory(&mii, sizeof(mii));
741 mii.cbSize = sizeof(mii);
742 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
744 if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
746 mii.fType = MFT_STRING;
747 mii.fState = MFS_ENABLED;
748 mii.dwTypeData = szText;
749 mii.wID = Tools[i].idCommand;
751 else
753 mii.fType = MFT_SEPARATOR;
755 /* tack This item onto the end of the menu */
756 InsertMenuItemA(hSubMenu, (UINT)-1, TRUE, &mii);
759 TRACE("-- return (menu=%p)\n",hSubMenu);
760 return hSubMenu;
762 /**********************************************************
763 * ShellView_MergeFileMenu()
765 static void ShellView_MergeFileMenu(IShellViewImpl * This, HMENU hSubMenu)
766 { TRACE("(%p)->(submenu=%p) stub\n",This,hSubMenu);
768 if(hSubMenu)
769 { /*insert This item at the beginning of the menu */
770 _InsertMenuItem(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
771 _InsertMenuItem(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, "dummy45", MFS_ENABLED);
774 TRACE("--\n");
777 /**********************************************************
778 * ShellView_MergeViewMenu()
781 static void ShellView_MergeViewMenu(IShellViewImpl * This, HMENU hSubMenu)
782 { MENUITEMINFOA mii;
784 TRACE("(%p)->(submenu=%p)\n",This,hSubMenu);
786 if(hSubMenu)
787 { /*add a separator at the correct position in the menu*/
788 _InsertMenuItem(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
790 ZeroMemory(&mii, sizeof(mii));
791 mii.cbSize = sizeof(mii);
792 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
793 mii.fType = MFT_STRING;
794 mii.dwTypeData = "View";
795 mii.hSubMenu = LoadMenuA(shell32_hInstance, "MENU_001");
796 InsertMenuItemA(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
800 /**********************************************************
801 * ShellView_GetSelections()
803 * - fills the this->apidl list with the selected objects
805 * RETURNS
806 * number of selected items
808 static UINT ShellView_GetSelections(IShellViewImpl * This)
810 LVITEMA lvItem;
811 UINT i = 0;
813 if (This->apidl)
815 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 ZeroMemory(&lvItem, sizeof(lvItem));
828 lvItem.mask = LVIF_STATE | LVIF_PARAM;
829 lvItem.stateMask = LVIS_SELECTED;
831 while(ListView_GetItemA(This->hWndList, &lvItem) && (i < This->cidl))
833 if(lvItem.state & LVIS_SELECTED)
835 This->apidl[i] = (LPITEMIDLIST)lvItem.lParam;
836 i++;
837 TRACE("-- selected Item found\n");
839 lvItem.iItem++;
842 return This->cidl;
846 /**********************************************************
847 * ShellView_OpenSelectedItems()
849 static HRESULT ShellView_OpenSelectedItems(IShellViewImpl * This)
851 static UINT CF_IDLIST = 0;
852 HRESULT hr;
853 IDataObject* selection;
854 FORMATETC fetc;
855 STGMEDIUM stgm;
856 LPIDA pIDList;
857 LPCITEMIDLIST parent_pidl;
858 int i;
860 if (0 == ShellView_GetSelections(This))
862 return S_OK;
864 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl,
865 (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,
866 0, (LPVOID *)&selection);
867 if (FAILED(hr))
868 return hr;
870 if (0 == CF_IDLIST)
872 CF_IDLIST = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
874 fetc.cfFormat = CF_IDLIST;
875 fetc.ptd = NULL;
876 fetc.dwAspect = DVASPECT_CONTENT;
877 fetc.lindex = -1;
878 fetc.tymed = TYMED_HGLOBAL;
880 hr = IDataObject_QueryGetData(selection, &fetc);
881 if (FAILED(hr))
882 return hr;
884 hr = IDataObject_GetData(selection, &fetc, &stgm);
885 if (FAILED(hr))
886 return hr;
888 pIDList = GlobalLock(stgm.u.hGlobal);
890 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
891 for (i = pIDList->cidl; i > 0; --i)
893 LPCITEMIDLIST pidl;
894 SFGAOF attribs;
896 pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
898 attribs = SFGAO_FOLDER;
899 hr = IShellFolder_GetAttributesOf(This->pSFParent, 1, &pidl, &attribs);
901 if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
903 SHELLEXECUTEINFOA shexinfo;
905 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOA);
906 shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */
907 shexinfo.hwnd = NULL;
908 shexinfo.lpVerb = NULL;
909 shexinfo.lpFile = NULL;
910 shexinfo.lpParameters = NULL;
911 shexinfo.lpDirectory = NULL;
912 shexinfo.nShow = SW_NORMAL;
913 shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
915 ShellExecuteExA(&shexinfo); /* Discard error/success info */
917 ILFree((LPITEMIDLIST)shexinfo.lpIDList);
921 GlobalUnlock(stgm.u.hGlobal);
922 ReleaseStgMedium(&stgm);
924 IDataObject_Release(selection);
926 return S_OK;
929 /**********************************************************
930 * ShellView_DoContextMenu()
932 static void ShellView_DoContextMenu(IShellViewImpl * This, WORD x, WORD y, BOOL bDefault)
933 { UINT uCommand;
934 DWORD wFlags;
935 HMENU hMenu;
936 BOOL fExplore = FALSE;
937 HWND hwndTree = 0;
938 LPCONTEXTMENU pContextMenu = NULL;
939 IContextMenu2 *pCM = NULL;
940 CMINVOKECOMMANDINFO cmi;
942 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This, x, y, bDefault);
944 /* look, what's selected and create a context menu object of it*/
945 if( ShellView_GetSelections(This) )
947 IShellFolder_GetUIObjectOf( This->pSFParent, This->hWndParent, This->cidl, (LPCITEMIDLIST*)This->apidl,
948 (REFIID)&IID_IContextMenu, NULL, (LPVOID *)&pContextMenu);
950 if(pContextMenu)
952 TRACE("-- pContextMenu\n");
953 hMenu = CreatePopupMenu();
955 if( hMenu )
957 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
958 if(SUCCEEDED(IShellBrowser_GetControlWindow(This->pShellBrowser,FCW_TREE, &hwndTree)) && hwndTree)
960 TRACE("-- explore mode\n");
961 fExplore = TRUE;
964 /* build the flags depending on what we can do with the selected item */
965 wFlags = CMF_NORMAL | (This->cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
967 /* let the ContextMenu merge its items in */
968 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
970 if (This->FolderSettings.fFlags & FWF_DESKTOP)
971 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
973 if( bDefault )
975 TRACE("-- get menu default command\n");
976 uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
978 else
980 TRACE("-- track popup\n");
981 uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
984 if(uCommand > 0)
986 TRACE("-- uCommand=%u\n", uCommand);
987 if (uCommand==FCIDM_SHVIEW_OPEN && IsInCommDlg(This))
989 TRACE("-- dlg: OnDefaultCommand\n");
990 if (OnDefaultCommand(This) != S_OK)
992 ShellView_OpenSelectedItems(This);
995 else
997 TRACE("-- explore -- invoke command\n");
998 ZeroMemory(&cmi, sizeof(cmi));
999 cmi.cbSize = sizeof(cmi);
1000 cmi.hwnd = This->hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
1001 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1002 IContextMenu_InvokeCommand(pContextMenu, &cmi);
1005 DestroyMenu(hMenu);
1008 if (pContextMenu)
1009 IContextMenu_Release(pContextMenu);
1012 else /* background context menu */
1014 hMenu = CreatePopupMenu();
1016 pCM = ISvBgCm_Constructor(This->pSFParent, FALSE);
1017 IContextMenu2_QueryContextMenu(pCM, hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1019 uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,This->hWnd,NULL);
1020 DestroyMenu(hMenu);
1022 TRACE("-- (%p)->(uCommand=0x%08x )\n",This, uCommand);
1024 ZeroMemory(&cmi, sizeof(cmi));
1025 cmi.cbSize = sizeof(cmi);
1026 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1027 cmi.hwnd = This->hWndParent;
1028 IContextMenu2_InvokeCommand(pCM, &cmi);
1030 IContextMenu2_Release(pCM);
1034 /**********************************************************
1035 * ##### message handling #####
1038 /**********************************************************
1039 * ShellView_OnSize()
1041 static LRESULT ShellView_OnSize(IShellViewImpl * This, WORD wWidth, WORD wHeight)
1043 TRACE("%p width=%u height=%u\n",This, wWidth,wHeight);
1045 /*resize the ListView to fit our window*/
1046 if(This->hWndList)
1048 MoveWindow(This->hWndList, 0, 0, wWidth, wHeight, TRUE);
1051 return S_OK;
1053 /**********************************************************
1054 * ShellView_OnDeactivate()
1056 * NOTES
1057 * internal
1059 static void ShellView_OnDeactivate(IShellViewImpl * This)
1061 TRACE("%p\n",This);
1063 if(This->uState != SVUIA_DEACTIVATE)
1065 if(This->hMenu)
1067 IShellBrowser_SetMenuSB(This->pShellBrowser,0, 0, 0);
1068 IShellBrowser_RemoveMenusSB(This->pShellBrowser,This->hMenu);
1069 DestroyMenu(This->hMenu);
1070 This->hMenu = 0;
1073 This->uState = SVUIA_DEACTIVATE;
1077 /**********************************************************
1078 * ShellView_OnActivate()
1080 static LRESULT ShellView_OnActivate(IShellViewImpl * This, UINT uState)
1081 { OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} };
1082 MENUITEMINFOA mii;
1083 CHAR szText[MAX_PATH];
1085 TRACE("%p uState=%x\n",This,uState);
1087 /*don't do anything if the state isn't really changing */
1088 if(This->uState == uState)
1090 return S_OK;
1093 ShellView_OnDeactivate(This);
1095 /*only do This if we are active */
1096 if(uState != SVUIA_DEACTIVATE)
1098 /*merge the menus */
1099 This->hMenu = CreateMenu();
1101 if(This->hMenu)
1103 IShellBrowser_InsertMenusSB(This->pShellBrowser, This->hMenu, &omw);
1104 TRACE("-- after fnInsertMenusSB\n");
1106 /*build the top level menu get the menu item's text*/
1107 strcpy(szText,"dummy 31");
1109 ZeroMemory(&mii, sizeof(mii));
1110 mii.cbSize = sizeof(mii);
1111 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1112 mii.fType = MFT_STRING;
1113 mii.fState = MFS_ENABLED;
1114 mii.dwTypeData = szText;
1115 mii.hSubMenu = ShellView_BuildFileMenu(This);
1117 /*insert our menu into the menu bar*/
1118 if(mii.hSubMenu)
1120 InsertMenuItemA(This->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1123 /*get the view menu so we can merge with it*/
1124 ZeroMemory(&mii, sizeof(mii));
1125 mii.cbSize = sizeof(mii);
1126 mii.fMask = MIIM_SUBMENU;
1128 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1130 ShellView_MergeViewMenu(This, mii.hSubMenu);
1133 /*add the items that should only be added if we have the focus*/
1134 if(SVUIA_ACTIVATE_FOCUS == uState)
1136 /*get the file menu so we can merge with it */
1137 ZeroMemory(&mii, sizeof(mii));
1138 mii.cbSize = sizeof(mii);
1139 mii.fMask = MIIM_SUBMENU;
1141 if(GetMenuItemInfoA(This->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1143 ShellView_MergeFileMenu(This, mii.hSubMenu);
1146 TRACE("-- before fnSetMenuSB\n");
1147 IShellBrowser_SetMenuSB(This->pShellBrowser, This->hMenu, 0, This->hWnd);
1150 This->uState = uState;
1151 TRACE("--\n");
1152 return S_OK;
1155 /**********************************************************
1156 * ShellView_OnSetFocus()
1159 static LRESULT ShellView_OnSetFocus(IShellViewImpl * This)
1161 TRACE("%p\n",This);
1163 /* Tell the browser one of our windows has received the focus. This
1164 should always be done before merging menus (OnActivate merges the
1165 menus) if one of our windows has the focus.*/
1167 IShellBrowser_OnViewWindowActive(This->pShellBrowser,(IShellView*) This);
1168 ShellView_OnActivate(This, SVUIA_ACTIVATE_FOCUS);
1170 /* Set the focus to the listview */
1171 SetFocus(This->hWndList);
1173 /* Notify the ICommDlgBrowser interface */
1174 OnStateChange(This,CDBOSC_SETFOCUS);
1176 return 0;
1179 /**********************************************************
1180 * ShellView_OnKillFocus()
1182 static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
1184 TRACE("(%p) stub\n",This);
1186 ShellView_OnActivate(This, SVUIA_ACTIVATE_NOFOCUS);
1187 /* Notify the ICommDlgBrowser */
1188 OnStateChange(This,CDBOSC_KILLFOCUS);
1190 return 0;
1193 /**********************************************************
1194 * ShellView_OnCommand()
1196 * NOTES
1197 * the CmdID's are the ones from the context menu
1199 static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
1201 TRACE("(%p)->(0x%08lx 0x%08lx %p) stub\n",This, dwCmdID, dwCmd, hwndCmd);
1203 switch(dwCmdID)
1205 case FCIDM_SHVIEW_SMALLICON:
1206 This->FolderSettings.ViewMode = FVM_SMALLICON;
1207 SetStyle (This, LVS_SMALLICON, LVS_TYPEMASK);
1208 CheckToolbar(This);
1209 break;
1211 case FCIDM_SHVIEW_BIGICON:
1212 This->FolderSettings.ViewMode = FVM_ICON;
1213 SetStyle (This, LVS_ICON, LVS_TYPEMASK);
1214 CheckToolbar(This);
1215 break;
1217 case FCIDM_SHVIEW_LISTVIEW:
1218 This->FolderSettings.ViewMode = FVM_LIST;
1219 SetStyle (This, LVS_LIST, LVS_TYPEMASK);
1220 CheckToolbar(This);
1221 break;
1223 case FCIDM_SHVIEW_REPORTVIEW:
1224 This->FolderSettings.ViewMode = FVM_DETAILS;
1225 SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
1226 CheckToolbar(This);
1227 break;
1229 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1230 case 0x30:
1231 case 0x31:
1232 case 0x32:
1233 case 0x33:
1234 This->ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30);
1235 This->ListViewSortInfo.bIsAscending = TRUE;
1236 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1237 SendMessageA(This->hWndList, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1238 break;
1240 default:
1241 TRACE("-- COMMAND 0x%04lx unhandled\n", dwCmdID);
1243 return 0;
1246 /**********************************************************
1247 * ShellView_OnNotify()
1250 static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
1251 { LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
1252 NMLVDISPINFOA *lpdi = (NMLVDISPINFOA *)lpnmh;
1253 LPITEMIDLIST pidl;
1255 TRACE("%p CtlID=%u lpnmh->code=%x\n",This,CtlID,lpnmh->code);
1257 switch(lpnmh->code)
1259 case NM_SETFOCUS:
1260 TRACE("-- NM_SETFOCUS %p\n",This);
1261 ShellView_OnSetFocus(This);
1262 break;
1264 case NM_KILLFOCUS:
1265 TRACE("-- NM_KILLFOCUS %p\n",This);
1266 ShellView_OnDeactivate(This);
1267 /* Notify the ICommDlgBrowser interface */
1268 OnStateChange(This,CDBOSC_KILLFOCUS);
1269 break;
1271 case NM_CUSTOMDRAW:
1272 TRACE("-- NM_CUSTOMDRAW %p\n",This);
1273 return CDRF_DODEFAULT;
1275 case NM_RELEASEDCAPTURE:
1276 TRACE("-- NM_RELEASEDCAPTURE %p\n",This);
1277 break;
1279 case NM_CLICK:
1280 TRACE("-- NM_CLICK %p\n",This);
1281 break;
1283 case NM_RCLICK:
1284 TRACE("-- NM_RCLICK %p\n",This);
1285 break;
1287 case NM_DBLCLK:
1288 TRACE("-- NM_DBLCLK %p\n",This);
1289 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1290 break;
1292 case NM_RETURN:
1293 TRACE("-- NM_DBLCLK %p\n",This);
1294 if (OnDefaultCommand(This) != S_OK) ShellView_OpenSelectedItems(This);
1295 break;
1297 case HDN_ENDTRACKA:
1298 TRACE("-- HDN_ENDTRACKA %p\n",This);
1299 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1300 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1301 break;
1303 case LVN_DELETEITEM:
1304 TRACE("-- LVN_DELETEITEM %p\n",This);
1305 SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/
1306 break;
1308 case LVN_DELETEALLITEMS:
1309 TRACE("-- LVN_DELETEALLITEMS %p\n",This);
1310 return FALSE;
1312 case LVN_INSERTITEM:
1313 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This);
1314 break;
1316 case LVN_ITEMACTIVATE:
1317 TRACE("-- LVN_ITEMACTIVATE %p\n",This);
1318 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1319 break;
1321 case LVN_COLUMNCLICK:
1322 This->ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1323 if(This->ListViewSortInfo.nLastHeaderID == This->ListViewSortInfo.nHeaderID)
1325 This->ListViewSortInfo.bIsAscending = !This->ListViewSortInfo.bIsAscending;
1327 else
1329 This->ListViewSortInfo.bIsAscending = TRUE;
1331 This->ListViewSortInfo.nLastHeaderID = This->ListViewSortInfo.nHeaderID;
1333 SendMessageA(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &This->ListViewSortInfo, (LPARAM)ShellView_ListViewCompareItems);
1334 break;
1336 case LVN_GETDISPINFOA:
1337 case LVN_GETDISPINFOW:
1338 TRACE("-- LVN_GETDISPINFO %p\n",This);
1339 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1341 if(lpdi->item.mask & LVIF_TEXT) /* text requested */
1343 if (This->pSF2Parent)
1345 SHELLDETAILS sd;
1346 IShellFolder2_GetDetailsOf(This->pSF2Parent, pidl, lpdi->item.iSubItem, &sd);
1347 if (lpnmh->code == LVN_GETDISPINFOA)
1349 StrRetToStrNA( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1350 TRACE("-- text=%s\n",lpdi->item.pszText);
1352 else /* LVN_GETDISPINFOW */
1354 StrRetToStrNW( ((NMLVDISPINFOW *)lpdi)->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1355 TRACE("-- text=%s\n",debugstr_w((WCHAR*)(lpdi->item.pszText)));
1358 else
1360 FIXME("no SF2\n");
1363 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1365 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(This->pSFParent, pidl, 0);
1367 break;
1369 case LVN_ITEMCHANGED:
1370 TRACE("-- LVN_ITEMCHANGED %p\n",This);
1371 OnStateChange(This, CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1372 break;
1374 case LVN_BEGINDRAG:
1375 case LVN_BEGINRDRAG:
1376 TRACE("-- LVN_BEGINDRAG\n");
1378 if (ShellView_GetSelections(This))
1380 IDataObject * pda;
1381 DWORD dwAttributes = SFGAO_CANLINK;
1382 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1384 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, &IID_IDataObject,0,(LPVOID *)&pda)))
1386 IDropSource * pds = (IDropSource*)&(This->lpvtblDropSource); /* own DropSource interface */
1388 if (SUCCEEDED(IShellFolder_GetAttributesOf(This->pSFParent, This->cidl, (LPCITEMIDLIST*)This->apidl, &dwAttributes)))
1390 if (dwAttributes & SFGAO_CANLINK)
1392 dwEffect |= DROPEFFECT_LINK;
1396 if (pds)
1398 DWORD dwEffect;
1399 DoDragDrop(pda, pds, dwEffect, &dwEffect);
1401 IDataObject_Release(pda);
1404 break;
1406 case LVN_BEGINLABELEDITA:
1408 DWORD dwAttr = SFGAO_CANRENAME;
1409 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1411 TRACE("-- LVN_BEGINLABELEDITA %p\n",This);
1413 IShellFolder_GetAttributesOf(This->pSFParent, 1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1414 if (SFGAO_CANRENAME & dwAttr)
1416 return FALSE;
1418 return TRUE;
1421 case LVN_ENDLABELEDITA:
1423 TRACE("-- LVN_ENDLABELEDITA %p\n",This);
1424 if (lpdi->item.pszText)
1426 HRESULT hr;
1427 WCHAR wszNewName[MAX_PATH];
1428 LVITEMA lvItem;
1430 ZeroMemory(&lvItem, sizeof(LVITEMA));
1431 lvItem.iItem = lpdi->item.iItem;
1432 lvItem.mask = LVIF_PARAM;
1433 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
1435 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1436 if (!MultiByteToWideChar( CP_ACP, 0, lpdi->item.pszText, -1, wszNewName, MAX_PATH ))
1437 wszNewName[MAX_PATH-1] = 0;
1438 hr = IShellFolder_SetNameOf(This->pSFParent, 0, pidl, wszNewName, SHGDN_INFOLDER, &pidl);
1440 if(SUCCEEDED(hr) && pidl)
1442 lvItem.mask = LVIF_PARAM;
1443 lvItem.lParam = (LPARAM)pidl;
1444 SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem);
1445 return TRUE;
1448 return FALSE;
1451 case LVN_KEYDOWN:
1453 /* MSG msg;
1454 msg.hwnd = This->hWnd;
1455 msg.message = WM_KEYDOWN;
1456 msg.wParam = plvKeyDown->wVKey;
1457 msg.lParam = 0;
1458 msg.time = 0;
1459 msg.pt = 0;*/
1461 LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1463 /* initiate a rename of the selected file or directory */
1464 if(plvKeyDown->wVKey == VK_F2)
1466 /* see how many files are selected */
1467 int i = ListView_GetSelectedCount(This->hWndList);
1469 /* get selected item */
1470 if(i == 1)
1472 /* get selected item */
1473 i = ListView_GetNextItem(This->hWndList, -1,
1474 LVNI_SELECTED);
1476 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1477 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
1480 #if 0
1481 TranslateAccelerator(This->hWnd, This->hAccel, &msg)
1482 #endif
1483 else if(plvKeyDown->wVKey == VK_DELETE)
1485 UINT i;
1486 int item_index;
1487 LVITEMA item;
1488 LPITEMIDLIST* pItems;
1489 ISFHelper *psfhlp;
1491 IShellFolder_QueryInterface(This->pSFParent, &IID_ISFHelper,
1492 (LPVOID*)&psfhlp);
1494 if (psfhlp == NULL)
1495 break;
1497 if(!(i = ListView_GetSelectedCount(This->hWndList)))
1498 break;
1500 /* allocate memory for the pidl array */
1501 pItems = HeapAlloc(GetProcessHeap(), 0,
1502 sizeof(LPITEMIDLIST) * i);
1504 /* retrieve all selected items */
1505 i = 0;
1506 item_index = -1;
1507 while(ListView_GetSelectedCount(This->hWndList) > i)
1509 /* get selected item */
1510 item_index = ListView_GetNextItem(This->hWndList,
1511 item_index, LVNI_SELECTED);
1512 item.iItem = item_index;
1513 item.mask = LVIF_PARAM;
1514 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &item);
1516 /* get item pidl */
1517 pItems[i] = (LPITEMIDLIST)item.lParam;
1519 i++;
1522 /* perform the item deletion */
1523 ISFHelper_DeleteItems(psfhlp, i, (LPCITEMIDLIST*)pItems);
1525 /* free pidl array memory */
1526 HeapFree(GetProcessHeap(), 0, pItems);
1529 /* Initiate a refresh */
1530 else if(plvKeyDown->wVKey == VK_F5)
1532 IShellView_Refresh((IShellView*)This);
1535 else
1536 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
1538 break;
1540 default:
1541 TRACE("-- %p WM_COMMAND %x unhandled\n", This, lpnmh->code);
1542 break;
1544 return 0;
1547 /**********************************************************
1548 * ShellView_OnChange()
1551 static LRESULT ShellView_OnChange(IShellViewImpl * This, LPITEMIDLIST * Pidls, LONG wEventId)
1554 TRACE("(%p)(%p,%p,0x%08lx)\n", This, Pidls[0], Pidls[1], wEventId);
1555 switch(wEventId)
1557 case SHCNE_MKDIR:
1558 case SHCNE_CREATE:
1559 LV_AddItem(This, Pidls[0]);
1560 break;
1561 case SHCNE_RMDIR:
1562 case SHCNE_DELETE:
1563 LV_DeleteItem(This, Pidls[0]);
1564 break;
1565 case SHCNE_RENAMEFOLDER:
1566 case SHCNE_RENAMEITEM:
1567 LV_RenameItem(This, Pidls[0], Pidls[1]);
1568 break;
1569 case SHCNE_UPDATEITEM:
1570 break;
1572 return TRUE;
1574 /**********************************************************
1575 * ShellView_WndProc
1578 static LRESULT CALLBACK ShellView_WndProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
1580 IShellViewImpl * pThis = (IShellViewImpl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
1581 LPCREATESTRUCTA lpcs;
1583 TRACE("(hwnd=%p msg=%x wparm=%x lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
1585 switch (uMessage)
1587 case WM_NCCREATE:
1588 lpcs = (LPCREATESTRUCTA)lParam;
1589 pThis = (IShellViewImpl*)(lpcs->lpCreateParams);
1590 SetWindowLongPtrW(hWnd, GWLP_USERDATA, (ULONG_PTR)pThis);
1591 pThis->hWnd = hWnd; /*set the window handle*/
1592 break;
1594 case WM_SIZE: return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
1595 case WM_SETFOCUS: return ShellView_OnSetFocus(pThis);
1596 case WM_KILLFOCUS: return ShellView_OnKillFocus(pThis);
1597 case WM_CREATE: return ShellView_OnCreate(pThis);
1598 case WM_ACTIVATE: return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
1599 case WM_NOTIFY: return ShellView_OnNotify(pThis,(UINT)wParam, (LPNMHDR)lParam);
1600 case WM_COMMAND: return ShellView_OnCommand(pThis,
1601 GET_WM_COMMAND_ID(wParam, lParam),
1602 GET_WM_COMMAND_CMD(wParam, lParam),
1603 GET_WM_COMMAND_HWND(wParam, lParam));
1604 case SHV_CHANGE_NOTIFY: return ShellView_OnChange(pThis, (LPITEMIDLIST*)wParam, (LONG)lParam);
1606 case WM_CONTEXTMENU: ShellView_DoContextMenu(pThis, LOWORD(lParam), HIWORD(lParam), FALSE);
1607 return 0;
1609 case WM_SHOWWINDOW: UpdateWindow(pThis->hWndList);
1610 break;
1612 case WM_GETDLGCODE: return SendMessageA(pThis->hWndList,uMessage,0,0);
1614 case WM_DESTROY:
1615 RevokeDragDrop(pThis->hWnd);
1616 SHChangeNotifyDeregister(pThis->hNotify);
1617 break;
1619 case WM_ERASEBKGND:
1620 if ((pThis->FolderSettings.fFlags & FWF_DESKTOP) ||
1621 (pThis->FolderSettings.fFlags & FWF_TRANSPARENT))
1622 return 1;
1623 break;
1626 return DefWindowProcA (hWnd, uMessage, wParam, lParam);
1628 /**********************************************************
1631 * The INTERFACE of the IShellView object
1634 **********************************************************
1635 * IShellView_QueryInterface
1637 static HRESULT WINAPI IShellView_fnQueryInterface(IShellView * iface,REFIID riid, LPVOID *ppvObj)
1639 IShellViewImpl *This = (IShellViewImpl *)iface;
1641 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1643 *ppvObj = NULL;
1645 if(IsEqualIID(riid, &IID_IUnknown))
1647 *ppvObj = This;
1649 else if(IsEqualIID(riid, &IID_IShellView))
1651 *ppvObj = (IShellView*)This;
1653 else if(IsEqualIID(riid, &IID_IOleCommandTarget))
1655 *ppvObj = (IOleCommandTarget*)&(This->lpvtblOleCommandTarget);
1657 else if(IsEqualIID(riid, &IID_IDropTarget))
1659 *ppvObj = (IDropTarget*)&(This->lpvtblDropTarget);
1661 else if(IsEqualIID(riid, &IID_IDropSource))
1663 *ppvObj = (IDropSource*)&(This->lpvtblDropSource);
1665 else if(IsEqualIID(riid, &IID_IViewObject))
1667 *ppvObj = (IViewObject*)&(This->lpvtblViewObject);
1670 if(*ppvObj)
1672 IUnknown_AddRef( (IUnknown*)*ppvObj );
1673 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1674 return S_OK;
1676 TRACE("-- Interface: E_NOINTERFACE\n");
1677 return E_NOINTERFACE;
1680 /**********************************************************
1681 * IShellView_AddRef
1683 static ULONG WINAPI IShellView_fnAddRef(IShellView * iface)
1685 IShellViewImpl *This = (IShellViewImpl *)iface;
1686 ULONG refCount = InterlockedIncrement(&This->ref);
1688 TRACE("(%p)->(count=%lu)\n", This, refCount - 1);
1690 return refCount;
1692 /**********************************************************
1693 * IShellView_Release
1695 static ULONG WINAPI IShellView_fnRelease(IShellView * iface)
1697 IShellViewImpl *This = (IShellViewImpl *)iface;
1698 ULONG refCount = InterlockedDecrement(&This->ref);
1700 TRACE("(%p)->(count=%li)\n", This, refCount + 1);
1702 if (!refCount)
1704 TRACE(" destroying IShellView(%p)\n",This);
1706 DestroyWindow(This->hWndList);
1708 if(This->pSFParent)
1709 IShellFolder_Release(This->pSFParent);
1711 if(This->pSF2Parent)
1712 IShellFolder2_Release(This->pSF2Parent);
1714 if(This->apidl)
1715 SHFree(This->apidl);
1717 if(This->pAdvSink)
1718 IAdviseSink_Release(This->pAdvSink);
1720 HeapFree(GetProcessHeap(),0,This);
1722 return refCount;
1725 /**********************************************************
1726 * ShellView_GetWindow
1728 static HRESULT WINAPI IShellView_fnGetWindow(IShellView * iface,HWND * phWnd)
1730 IShellViewImpl *This = (IShellViewImpl *)iface;
1732 TRACE("(%p)\n",This);
1734 *phWnd = This->hWnd;
1736 return S_OK;
1739 static HRESULT WINAPI IShellView_fnContextSensitiveHelp(IShellView * iface,BOOL fEnterMode)
1741 IShellViewImpl *This = (IShellViewImpl *)iface;
1743 FIXME("(%p) stub\n",This);
1745 return E_NOTIMPL;
1748 /**********************************************************
1749 * IShellView_TranslateAccelerator
1751 * FIXME:
1752 * use the accel functions
1754 static HRESULT WINAPI IShellView_fnTranslateAccelerator(IShellView * iface,LPMSG lpmsg)
1756 #if 0
1757 IShellViewImpl *This = (IShellViewImpl *)iface;
1759 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%lx wp=%x) stub\n",This,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
1760 #endif
1762 if ((lpmsg->message>=WM_KEYFIRST) && (lpmsg->message>=WM_KEYLAST))
1764 TRACE("-- key=0x04%x\n",lpmsg->wParam) ;
1766 return S_FALSE; /* not handled */
1769 static HRESULT WINAPI IShellView_fnEnableModeless(IShellView * iface,BOOL fEnable)
1771 IShellViewImpl *This = (IShellViewImpl *)iface;
1773 FIXME("(%p) stub\n",This);
1775 return E_NOTIMPL;
1778 static HRESULT WINAPI IShellView_fnUIActivate(IShellView * iface,UINT uState)
1780 IShellViewImpl *This = (IShellViewImpl *)iface;
1783 CHAR szName[MAX_PATH];
1785 LRESULT lResult;
1786 int nPartArray[1] = {-1};
1788 TRACE("(%p)->(state=%x) stub\n",This, uState);
1790 /*don't do anything if the state isn't really changing*/
1791 if(This->uState == uState)
1793 return S_OK;
1796 /*OnActivate handles the menu merging and internal state*/
1797 ShellView_OnActivate(This, uState);
1799 /*only do This if we are active*/
1800 if(uState != SVUIA_DEACTIVATE)
1804 GetFolderPath is not a method of IShellFolder
1805 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1807 /* set the number of parts */
1808 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETPARTS, 1,
1809 (LPARAM)nPartArray, &lResult);
1811 /* set the text for the parts */
1813 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1814 0, (LPARAM)szName, &lResult);
1818 return S_OK;
1821 static HRESULT WINAPI IShellView_fnRefresh(IShellView * iface)
1823 IShellViewImpl *This = (IShellViewImpl *)iface;
1825 TRACE("(%p)\n",This);
1827 SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
1828 ShellView_FillList(This);
1830 return S_OK;
1833 static HRESULT WINAPI IShellView_fnCreateViewWindow(
1834 IShellView * iface,
1835 IShellView *lpPrevView,
1836 LPCFOLDERSETTINGS lpfs,
1837 IShellBrowser * psb,
1838 RECT * prcView,
1839 HWND *phWnd)
1841 IShellViewImpl *This = (IShellViewImpl *)iface;
1843 WNDCLASSA wc;
1844 *phWnd = 0;
1847 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This, lpPrevView,lpfs, psb, prcView, phWnd);
1848 TRACE("-- vmode=%x flags=%x left=%li top=%li right=%li bottom=%li\n",lpfs->ViewMode, lpfs->fFlags ,prcView->left,prcView->top, prcView->right, prcView->bottom);
1850 /*set up the member variables*/
1851 This->pShellBrowser = psb;
1852 This->FolderSettings = *lpfs;
1854 /*get our parent window*/
1855 IShellBrowser_AddRef(This->pShellBrowser);
1856 IShellBrowser_GetWindow(This->pShellBrowser, &(This->hWndParent));
1858 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1859 This->pCommDlgBrowser=NULL;
1860 if ( SUCCEEDED (IShellBrowser_QueryInterface( This->pShellBrowser,
1861 (REFIID)&IID_ICommDlgBrowser, (LPVOID*) &This->pCommDlgBrowser)))
1863 TRACE("-- CommDlgBrowser\n");
1866 /*if our window class has not been registered, then do so*/
1867 if(!GetClassInfoA(shell32_hInstance, SV_CLASS_NAME, &wc))
1869 ZeroMemory(&wc, sizeof(wc));
1870 wc.style = CS_HREDRAW | CS_VREDRAW;
1871 wc.lpfnWndProc = ShellView_WndProc;
1872 wc.cbClsExtra = 0;
1873 wc.cbWndExtra = 0;
1874 wc.hInstance = shell32_hInstance;
1875 wc.hIcon = 0;
1876 wc.hCursor = LoadCursorA (0, (LPSTR)IDC_ARROW);
1877 wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
1878 wc.lpszMenuName = NULL;
1879 wc.lpszClassName = SV_CLASS_NAME;
1881 if(!RegisterClassA(&wc))
1882 return E_FAIL;
1885 *phWnd = CreateWindowExA(0,
1886 SV_CLASS_NAME,
1887 NULL,
1888 WS_CHILD | WS_TABSTOP,
1889 prcView->left,
1890 prcView->top,
1891 prcView->right - prcView->left,
1892 prcView->bottom - prcView->top,
1893 This->hWndParent,
1895 shell32_hInstance,
1896 (LPVOID)This);
1898 CheckToolbar(This);
1900 if(!*phWnd) return E_FAIL;
1902 SetWindowPos(*phWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
1903 UpdateWindow(*phWnd);
1905 return S_OK;
1908 static HRESULT WINAPI IShellView_fnDestroyViewWindow(IShellView * iface)
1910 IShellViewImpl *This = (IShellViewImpl *)iface;
1912 TRACE("(%p)\n",This);
1914 /*Make absolutely sure all our UI is cleaned up.*/
1915 IShellView_UIActivate((IShellView*)This, SVUIA_DEACTIVATE);
1917 if(This->hMenu)
1919 DestroyMenu(This->hMenu);
1922 DestroyWindow(This->hWnd);
1923 if(This->pShellBrowser) IShellBrowser_Release(This->pShellBrowser);
1924 if(This->pCommDlgBrowser) ICommDlgBrowser_Release(This->pCommDlgBrowser);
1927 return S_OK;
1930 static HRESULT WINAPI IShellView_fnGetCurrentInfo(IShellView * iface, LPFOLDERSETTINGS lpfs)
1932 IShellViewImpl *This = (IShellViewImpl *)iface;
1934 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This, lpfs,
1935 This->FolderSettings.ViewMode, This->FolderSettings.fFlags);
1937 if (!lpfs) return E_INVALIDARG;
1939 *lpfs = This->FolderSettings;
1940 return NOERROR;
1943 static HRESULT WINAPI IShellView_fnAddPropertySheetPages(IShellView * iface, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
1945 IShellViewImpl *This = (IShellViewImpl *)iface;
1947 FIXME("(%p) stub\n",This);
1949 return E_NOTIMPL;
1952 static HRESULT WINAPI IShellView_fnSaveViewState(IShellView * iface)
1954 IShellViewImpl *This = (IShellViewImpl *)iface;
1956 FIXME("(%p) stub\n",This);
1958 return S_OK;
1961 static HRESULT WINAPI IShellView_fnSelectItem(
1962 IShellView * iface,
1963 LPCITEMIDLIST pidl,
1964 UINT uFlags)
1966 IShellViewImpl *This = (IShellViewImpl *)iface;
1967 int i;
1969 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This, pidl, uFlags);
1971 i = LV_FindItemByPidl(This, pidl);
1973 if (i != -1)
1975 LVITEMA lvItem;
1977 if(uFlags & SVSI_ENSUREVISIBLE)
1978 SendMessageW(This->hWndList, LVM_ENSUREVISIBLE, i, 0);
1980 ZeroMemory(&lvItem, sizeof(LVITEMA));
1981 lvItem.mask = LVIF_STATE;
1982 lvItem.iItem = 0;
1984 while(SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem))
1986 if (lvItem.iItem == i)
1988 if (uFlags & SVSI_SELECT)
1989 lvItem.state |= LVIS_SELECTED;
1990 else
1991 lvItem.state &= ~LVIS_SELECTED;
1993 if(uFlags & SVSI_FOCUSED)
1994 lvItem.state &= ~LVIS_FOCUSED;
1996 else
1998 if (uFlags & SVSI_DESELECTOTHERS)
1999 lvItem.state &= ~LVIS_SELECTED;
2001 SendMessageA(This->hWndList, LVM_SETITEMA, 0, (LPARAM) &lvItem);
2002 lvItem.iItem++;
2006 if(uFlags & SVSI_EDIT)
2007 SendMessageW(This->hWndList, LVM_EDITLABELW, i, 0);
2010 return S_OK;
2013 static HRESULT WINAPI IShellView_fnGetItemObject(IShellView * iface, UINT uItem, REFIID riid, LPVOID *ppvOut)
2015 IShellViewImpl *This = (IShellViewImpl *)iface;
2017 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This, uItem, debugstr_guid(riid), ppvOut);
2019 *ppvOut = NULL;
2021 switch(uItem)
2023 case SVGIO_BACKGROUND:
2024 *ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2025 break;
2027 case SVGIO_SELECTION:
2028 ShellView_GetSelections(This);
2029 IShellFolder_GetUIObjectOf(This->pSFParent, This->hWnd, This->cidl, (LPCITEMIDLIST*)This->apidl, riid, 0, ppvOut);
2030 break;
2032 TRACE("-- (%p)->(interface=%p)\n",This, *ppvOut);
2034 if(!*ppvOut) return E_OUTOFMEMORY;
2036 return S_OK;
2039 static const IShellViewVtbl svvt =
2041 IShellView_fnQueryInterface,
2042 IShellView_fnAddRef,
2043 IShellView_fnRelease,
2044 IShellView_fnGetWindow,
2045 IShellView_fnContextSensitiveHelp,
2046 IShellView_fnTranslateAccelerator,
2047 IShellView_fnEnableModeless,
2048 IShellView_fnUIActivate,
2049 IShellView_fnRefresh,
2050 IShellView_fnCreateViewWindow,
2051 IShellView_fnDestroyViewWindow,
2052 IShellView_fnGetCurrentInfo,
2053 IShellView_fnAddPropertySheetPages,
2054 IShellView_fnSaveViewState,
2055 IShellView_fnSelectItem,
2056 IShellView_fnGetItemObject
2060 /**********************************************************
2061 * ISVOleCmdTarget_QueryInterface (IUnknown)
2063 static HRESULT WINAPI ISVOleCmdTarget_QueryInterface(
2064 IOleCommandTarget * iface,
2065 REFIID iid,
2066 LPVOID* ppvObj)
2068 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2070 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
2073 /**********************************************************
2074 * ISVOleCmdTarget_AddRef (IUnknown)
2076 static ULONG WINAPI ISVOleCmdTarget_AddRef(
2077 IOleCommandTarget * iface)
2079 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2081 return IShellFolder_AddRef((IShellFolder*)This);
2084 /**********************************************************
2085 * ISVOleCmdTarget_Release (IUnknown)
2087 static ULONG WINAPI ISVOleCmdTarget_Release(
2088 IOleCommandTarget * iface)
2090 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2092 return IShellFolder_Release((IShellFolder*)This);
2095 /**********************************************************
2096 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2098 static HRESULT WINAPI ISVOleCmdTarget_QueryStatus(
2099 IOleCommandTarget *iface,
2100 const GUID* pguidCmdGroup,
2101 ULONG cCmds,
2102 OLECMD * prgCmds,
2103 OLECMDTEXT* pCmdText)
2105 UINT i;
2106 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2108 FIXME("(%p)->(%p(%s) 0x%08lx %p %p\n",
2109 This, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2111 if (!prgCmds)
2112 return E_POINTER;
2113 for (i = 0; i < cCmds; i++)
2115 FIXME("\tprgCmds[%d].cmdID = %ld\n", i, prgCmds[i].cmdID);
2116 prgCmds[i].cmdf = 0;
2118 return OLECMDERR_E_UNKNOWNGROUP;
2121 /**********************************************************
2122 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2124 * nCmdID is the OLECMDID_* enumeration
2126 static HRESULT WINAPI ISVOleCmdTarget_Exec(
2127 IOleCommandTarget *iface,
2128 const GUID* pguidCmdGroup,
2129 DWORD nCmdID,
2130 DWORD nCmdexecopt,
2131 VARIANT* pvaIn,
2132 VARIANT* pvaOut)
2134 IShellViewImpl *This = impl_from_IOleCommandTarget(iface);
2136 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08lx Opt:0x%08lx %p %p)\n",
2137 This, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2139 if (IsEqualIID(pguidCmdGroup, &CGID_Explorer) &&
2140 (nCmdID == 0x29) &&
2141 (nCmdexecopt == 4) && pvaOut)
2142 return S_OK;
2143 if (IsEqualIID(pguidCmdGroup, &CGID_ShellDocView) &&
2144 (nCmdID == 9) &&
2145 (nCmdexecopt == 0))
2146 return 1;
2148 return OLECMDERR_E_UNKNOWNGROUP;
2151 static const IOleCommandTargetVtbl ctvt =
2153 ISVOleCmdTarget_QueryInterface,
2154 ISVOleCmdTarget_AddRef,
2155 ISVOleCmdTarget_Release,
2156 ISVOleCmdTarget_QueryStatus,
2157 ISVOleCmdTarget_Exec
2160 /**********************************************************
2161 * ISVDropTarget implementation
2164 static HRESULT WINAPI ISVDropTarget_QueryInterface(
2165 IDropTarget *iface,
2166 REFIID riid,
2167 LPVOID *ppvObj)
2169 IShellViewImpl *This = impl_from_IDropTarget(iface);
2171 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2173 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2176 static ULONG WINAPI ISVDropTarget_AddRef( IDropTarget *iface)
2178 IShellViewImpl *This = impl_from_IDropTarget(iface);
2180 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2182 return IShellFolder_AddRef((IShellFolder*)This);
2185 static ULONG WINAPI ISVDropTarget_Release( IDropTarget *iface)
2187 IShellViewImpl *This = impl_from_IDropTarget(iface);
2189 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2191 return IShellFolder_Release((IShellFolder*)This);
2194 /******************************************************************************
2195 * drag_notify_subitem [Internal]
2197 * Figure out the shellfolder object, which is currently under the mouse cursor
2198 * and notify it via the IDropTarget interface.
2201 #define SCROLLAREAWIDTH 20
2203 static HRESULT drag_notify_subitem(IShellViewImpl *This, DWORD grfKeyState, POINTL pt,
2204 DWORD *pdwEffect)
2206 LVHITTESTINFO htinfo;
2207 LVITEMA lvItem;
2208 LONG lResult;
2209 HRESULT hr;
2210 RECT clientRect;
2212 /* Map from global to client coordinates and query the index of the listview-item, which is
2213 * currently under the mouse cursor. */
2214 htinfo.pt.x = pt.x;
2215 htinfo.pt.y = pt.y;
2216 htinfo.flags = LVHT_ONITEM;
2217 ScreenToClient(This->hWndList, &htinfo.pt);
2218 lResult = SendMessageW(This->hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2220 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2221 GetClientRect(This->hWndList, &clientRect);
2222 if (htinfo.pt.x == This->ptLastMousePos.x && htinfo.pt.y == This->ptLastMousePos.y &&
2223 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2224 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2226 This->cScrollDelay = (This->cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2227 if (This->cScrollDelay == 0) { /* Mouse did hover another 250 ms over the scroll-area */
2228 if (htinfo.pt.x < SCROLLAREAWIDTH)
2229 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEUP, 0);
2230 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2231 SendMessageW(This->hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2232 if (htinfo.pt.y < SCROLLAREAWIDTH)
2233 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEUP, 0);
2234 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2235 SendMessageW(This->hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2237 } else {
2238 This->cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2240 This->ptLastMousePos = htinfo.pt;
2242 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2243 if (This->pCurDropTarget && lResult == This->iDragOverItem)
2244 return IDropTarget_DragOver(This->pCurDropTarget, grfKeyState, pt, pdwEffect);
2246 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2247 if (This->pCurDropTarget) {
2248 IDropTarget_DragLeave(This->pCurDropTarget);
2249 IDropTarget_Release(This->pCurDropTarget);
2250 This->pCurDropTarget = NULL;
2253 This->iDragOverItem = lResult;
2254 if (lResult == -1) {
2255 /* We are not above one of the listview's subitems. Bind to the parent folder's
2256 * DropTarget interface. */
2257 hr = IShellFolder_QueryInterface(This->pSFParent, &IID_IDropTarget,
2258 (LPVOID*)&This->pCurDropTarget);
2259 } else {
2260 /* Query the relative PIDL of the shellfolder object represented by the currently
2261 * dragged over listview-item ... */
2262 ZeroMemory(&lvItem, sizeof(lvItem));
2263 lvItem.mask = LVIF_PARAM;
2264 lvItem.iItem = lResult;
2265 SendMessageA(This->hWndList, LVM_GETITEMA, 0, (LPARAM) &lvItem);
2267 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2268 hr = IShellFolder_GetUIObjectOf(This->pSFParent, This->hWndList, 1,
2269 (LPCITEMIDLIST*)&lvItem.lParam, &IID_IDropTarget, NULL, (LPVOID*)&This->pCurDropTarget);
2272 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2273 if (FAILED(hr))
2274 return hr;
2276 /* Notify the item just entered via DragEnter. */
2277 return IDropTarget_DragEnter(This->pCurDropTarget, This->pCurDataObject, grfKeyState, pt, pdwEffect);
2280 static HRESULT WINAPI ISVDropTarget_DragEnter(IDropTarget *iface, IDataObject *pDataObject,
2281 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2283 IShellViewImpl *This = impl_from_IDropTarget(iface);
2285 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2286 This->pCurDataObject = pDataObject;
2287 IDataObject_AddRef(pDataObject);
2289 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2292 static HRESULT WINAPI ISVDropTarget_DragOver(IDropTarget *iface, DWORD grfKeyState, POINTL pt,
2293 DWORD *pdwEffect)
2295 IShellViewImpl *This = impl_from_IDropTarget(iface);
2296 return drag_notify_subitem(This, grfKeyState, pt, pdwEffect);
2299 static HRESULT WINAPI ISVDropTarget_DragLeave(IDropTarget *iface) {
2300 IShellViewImpl *This = impl_from_IDropTarget(iface);
2302 IDropTarget_DragLeave(This->pCurDropTarget);
2304 IDropTarget_Release(This->pCurDropTarget);
2305 IDataObject_Release(This->pCurDataObject);
2306 This->pCurDataObject = NULL;
2307 This->pCurDropTarget = NULL;
2308 This->iDragOverItem = 0;
2310 return S_OK;
2313 static HRESULT WINAPI ISVDropTarget_Drop(IDropTarget *iface, IDataObject* pDataObject,
2314 DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2316 IShellViewImpl *This = impl_from_IDropTarget(iface);
2318 IDropTarget_Drop(This->pCurDropTarget, pDataObject, grfKeyState, pt, pdwEffect);
2320 IDropTarget_Release(This->pCurDropTarget);
2321 IDataObject_Release(This->pCurDataObject);
2322 This->pCurDataObject = NULL;
2323 This->pCurDropTarget = NULL;
2324 This->iDragOverItem = 0;
2326 return S_OK;
2329 static const IDropTargetVtbl dtvt =
2331 ISVDropTarget_QueryInterface,
2332 ISVDropTarget_AddRef,
2333 ISVDropTarget_Release,
2334 ISVDropTarget_DragEnter,
2335 ISVDropTarget_DragOver,
2336 ISVDropTarget_DragLeave,
2337 ISVDropTarget_Drop
2340 /**********************************************************
2341 * ISVDropSource implementation
2344 static HRESULT WINAPI ISVDropSource_QueryInterface(
2345 IDropSource *iface,
2346 REFIID riid,
2347 LPVOID *ppvObj)
2349 IShellViewImpl *This = impl_from_IDropSource(iface);
2351 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2353 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2356 static ULONG WINAPI ISVDropSource_AddRef( IDropSource *iface)
2358 IShellViewImpl *This = impl_from_IDropSource(iface);
2360 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2362 return IShellFolder_AddRef((IShellFolder*)This);
2365 static ULONG WINAPI ISVDropSource_Release( IDropSource *iface)
2367 IShellViewImpl *This = impl_from_IDropSource(iface);
2369 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2371 return IShellFolder_Release((IShellFolder*)This);
2373 static HRESULT WINAPI ISVDropSource_QueryContinueDrag(
2374 IDropSource *iface,
2375 BOOL fEscapePressed,
2376 DWORD grfKeyState)
2378 IShellViewImpl *This = impl_from_IDropSource(iface);
2379 TRACE("(%p)\n",This);
2381 if (fEscapePressed)
2382 return DRAGDROP_S_CANCEL;
2383 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2384 return DRAGDROP_S_DROP;
2385 else
2386 return NOERROR;
2389 static HRESULT WINAPI ISVDropSource_GiveFeedback(
2390 IDropSource *iface,
2391 DWORD dwEffect)
2393 IShellViewImpl *This = impl_from_IDropSource(iface);
2394 TRACE("(%p)\n",This);
2396 return DRAGDROP_S_USEDEFAULTCURSORS;
2399 static const IDropSourceVtbl dsvt =
2401 ISVDropSource_QueryInterface,
2402 ISVDropSource_AddRef,
2403 ISVDropSource_Release,
2404 ISVDropSource_QueryContinueDrag,
2405 ISVDropSource_GiveFeedback
2407 /**********************************************************
2408 * ISVViewObject implementation
2411 static HRESULT WINAPI ISVViewObject_QueryInterface(
2412 IViewObject *iface,
2413 REFIID riid,
2414 LPVOID *ppvObj)
2416 IShellViewImpl *This = impl_from_IViewObject(iface);
2418 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
2420 return IShellFolder_QueryInterface((IShellFolder*)This, riid, ppvObj);
2423 static ULONG WINAPI ISVViewObject_AddRef( IViewObject *iface)
2425 IShellViewImpl *This = impl_from_IViewObject(iface);
2427 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2429 return IShellFolder_AddRef((IShellFolder*)This);
2432 static ULONG WINAPI ISVViewObject_Release( IViewObject *iface)
2434 IShellViewImpl *This = impl_from_IViewObject(iface);
2436 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2438 return IShellFolder_Release((IShellFolder*)This);
2441 static HRESULT WINAPI ISVViewObject_Draw(
2442 IViewObject *iface,
2443 DWORD dwDrawAspect,
2444 LONG lindex,
2445 void* pvAspect,
2446 DVTARGETDEVICE* ptd,
2447 HDC hdcTargetDev,
2448 HDC hdcDraw,
2449 LPCRECTL lprcBounds,
2450 LPCRECTL lprcWBounds,
2451 BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),
2452 ULONG_PTR dwContinue)
2455 IShellViewImpl *This = impl_from_IViewObject(iface);
2457 FIXME("Stub: This=%p\n",This);
2459 return E_NOTIMPL;
2461 static HRESULT WINAPI ISVViewObject_GetColorSet(
2462 IViewObject *iface,
2463 DWORD dwDrawAspect,
2464 LONG lindex,
2465 void *pvAspect,
2466 DVTARGETDEVICE* ptd,
2467 HDC hicTargetDevice,
2468 LOGPALETTE** ppColorSet)
2471 IShellViewImpl *This = impl_from_IViewObject(iface);
2473 FIXME("Stub: This=%p\n",This);
2475 return E_NOTIMPL;
2477 static HRESULT WINAPI ISVViewObject_Freeze(
2478 IViewObject *iface,
2479 DWORD dwDrawAspect,
2480 LONG lindex,
2481 void* pvAspect,
2482 DWORD* pdwFreeze)
2485 IShellViewImpl *This = impl_from_IViewObject(iface);
2487 FIXME("Stub: This=%p\n",This);
2489 return E_NOTIMPL;
2491 static HRESULT WINAPI ISVViewObject_Unfreeze(
2492 IViewObject *iface,
2493 DWORD dwFreeze)
2496 IShellViewImpl *This = impl_from_IViewObject(iface);
2498 FIXME("Stub: This=%p\n",This);
2500 return E_NOTIMPL;
2502 static HRESULT WINAPI ISVViewObject_SetAdvise(
2503 IViewObject *iface,
2504 DWORD aspects,
2505 DWORD advf,
2506 IAdviseSink* pAdvSink)
2509 IShellViewImpl *This = impl_from_IViewObject(iface);
2511 FIXME("partial stub: %p %08lx %08lx %p\n",
2512 This, aspects, advf, pAdvSink);
2514 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2515 This->pAdvSink = pAdvSink;
2516 This->dwAspects = aspects;
2517 This->dwAdvf = advf;
2519 return S_OK;
2522 static HRESULT WINAPI ISVViewObject_GetAdvise(
2523 IViewObject *iface,
2524 DWORD* pAspects,
2525 DWORD* pAdvf,
2526 IAdviseSink** ppAdvSink)
2529 IShellViewImpl *This = impl_from_IViewObject(iface);
2531 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2532 This, pAspects, pAdvf, ppAdvSink);
2534 if( ppAdvSink )
2536 IAdviseSink_AddRef( This->pAdvSink );
2537 *ppAdvSink = This->pAdvSink;
2539 if( pAspects )
2540 *pAspects = This->dwAspects;
2541 if( pAdvf )
2542 *pAdvf = This->dwAdvf;
2544 return S_OK;
2548 static const IViewObjectVtbl vovt =
2550 ISVViewObject_QueryInterface,
2551 ISVViewObject_AddRef,
2552 ISVViewObject_Release,
2553 ISVViewObject_Draw,
2554 ISVViewObject_GetColorSet,
2555 ISVViewObject_Freeze,
2556 ISVViewObject_Unfreeze,
2557 ISVViewObject_SetAdvise,
2558 ISVViewObject_GetAdvise