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
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
40 #include "wine/port.h"
47 #define NONAMELESSUNION
48 #define NONAMELESSSTRUCT
60 #include "undocshell.h"
62 #include "wine/debug.h"
66 #include "shell32_main.h"
67 #include "shellfolder.h"
69 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
73 static const WCHAR SV_CLASS_NAME
[] = {'S','H','E','L','L','D','L','L','_','D','e','f','V','i','e','w',0};
79 }LISTVIEW_SORT_INFO
, *LPLISTVIEW_SORT_INFO
;
83 const IShellViewVtbl
* lpVtbl
;
85 const IOleCommandTargetVtbl
* lpvtblOleCommandTarget
;
86 const IDropTargetVtbl
* lpvtblDropTarget
;
87 const IDropSourceVtbl
* lpvtblDropSource
;
88 const IViewObjectVtbl
* lpvtblViewObject
;
89 IShellFolder
* pSFParent
;
90 IShellFolder2
* pSF2Parent
;
91 IShellBrowser
* pShellBrowser
;
92 ICommDlgBrowser
* pCommDlgBrowser
;
93 HWND hWnd
; /* SHELLDLL_DefView */
94 HWND hWndList
; /* ListView control */
96 FOLDERSETTINGS FolderSettings
;
101 LISTVIEW_SORT_INFO ListViewSortInfo
;
102 ULONG hNotify
; /* change notification handle */
106 IAdviseSink
*pAdvSink
;
107 IDropTarget
* pCurDropTarget
; /* The sub-item, which is currently dragged over */
108 IDataObject
* pCurDataObject
; /* The dragged data-object */
109 LONG iDragOverItem
; /* Dragged over item's index, iff pCurDropTarget != NULL */
110 UINT cScrollDelay
; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
111 POINT ptLastMousePos
; /* Mouse position at last DragOver call */
115 static const IShellViewVtbl svvt
;
116 static const IOleCommandTargetVtbl ctvt
;
117 static const IDropTargetVtbl dtvt
;
118 static const IDropSourceVtbl dsvt
;
119 static const IViewObjectVtbl vovt
;
122 static inline IShellViewImpl
*impl_from_IOleCommandTarget( IOleCommandTarget
*iface
)
124 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblOleCommandTarget
));
127 static inline IShellViewImpl
*impl_from_IDropTarget( IDropTarget
*iface
)
129 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblDropTarget
));
132 static inline IShellViewImpl
*impl_from_IDropSource( IDropSource
*iface
)
134 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblDropSource
));
137 static inline IShellViewImpl
*impl_from_IViewObject( IViewObject
*iface
)
139 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblViewObject
));
142 /* ListView Header ID's */
143 #define LISTVIEW_COLUMN_NAME 0
144 #define LISTVIEW_COLUMN_SIZE 1
145 #define LISTVIEW_COLUMN_TYPE 2
146 #define LISTVIEW_COLUMN_TIME 3
147 #define LISTVIEW_COLUMN_ATTRIB 4
150 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
151 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
152 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
154 #define ID_LISTVIEW 1
156 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
159 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
160 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
161 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
164 Items merged into the toolbar and the filemenu
173 } MYTOOLINFO
, *LPMYTOOLINFO
;
175 static const MYTOOLINFO Tools
[] =
177 { FCIDM_SHVIEW_BIGICON
, 0, 0, IDS_VIEW_LARGE
, TBSTATE_ENABLED
, BTNS_BUTTON
},
178 { FCIDM_SHVIEW_SMALLICON
, 0, 0, IDS_VIEW_SMALL
, TBSTATE_ENABLED
, BTNS_BUTTON
},
179 { FCIDM_SHVIEW_LISTVIEW
, 0, 0, IDS_VIEW_LIST
, TBSTATE_ENABLED
, BTNS_BUTTON
},
180 { FCIDM_SHVIEW_REPORTVIEW
, 0, 0, IDS_VIEW_DETAILS
, TBSTATE_ENABLED
, BTNS_BUTTON
},
184 typedef void (CALLBACK
*PFNSHGETSETTINGSPROC
)(LPSHELLFLAGSTATE lpsfs
, DWORD dwMask
);
186 /**********************************************************
187 * IShellView_Constructor
189 IShellView
* IShellView_Constructor( IShellFolder
* pFolder
)
190 { IShellViewImpl
* sv
;
191 sv
=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IShellViewImpl
));
194 sv
->lpvtblOleCommandTarget
=&ctvt
;
195 sv
->lpvtblDropTarget
=&dtvt
;
196 sv
->lpvtblDropSource
=&dsvt
;
197 sv
->lpvtblViewObject
=&vovt
;
199 sv
->pSFParent
= pFolder
;
200 if(pFolder
) IShellFolder_AddRef(pFolder
);
201 IShellFolder_QueryInterface(sv
->pSFParent
, &IID_IShellFolder2
, (LPVOID
*)&sv
->pSF2Parent
);
203 sv
->pCurDropTarget
= NULL
;
204 sv
->pCurDataObject
= NULL
;
205 sv
->iDragOverItem
= 0;
206 sv
->cScrollDelay
= 0;
207 sv
->ptLastMousePos
.x
= 0;
208 sv
->ptLastMousePos
.y
= 0;
210 TRACE("(%p)->(%p)\n",sv
, pFolder
);
211 return (IShellView
*) sv
;
214 /**********************************************************
216 * ##### helperfunctions for communication with ICommDlgBrowser #####
218 static BOOL
IsInCommDlg(IShellViewImpl
* This
)
219 { return(This
->pCommDlgBrowser
!= NULL
);
222 static HRESULT
IncludeObject(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
226 if ( IsInCommDlg(This
) )
228 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl
);
229 ret
= ICommDlgBrowser_IncludeObject(This
->pCommDlgBrowser
, (IShellView
*)This
, pidl
);
230 TRACE("--0x%08x\n", ret
);
235 static HRESULT
OnDefaultCommand(IShellViewImpl
* This
)
237 HRESULT ret
= S_FALSE
;
239 if (IsInCommDlg(This
))
241 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
242 ret
= ICommDlgBrowser_OnDefaultCommand(This
->pCommDlgBrowser
, (IShellView
*)This
);
243 TRACE("-- returns %08x\n", ret
);
248 static HRESULT
OnStateChange(IShellViewImpl
* This
, UINT uFlags
)
250 HRESULT ret
= S_FALSE
;
252 if (IsInCommDlg(This
))
254 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags
);
255 ret
= ICommDlgBrowser_OnStateChange(This
->pCommDlgBrowser
, (IShellView
*)This
, uFlags
);
260 /**********************************************************
261 * set the toolbar of the filedialog buttons
263 * - activates the buttons from the shellbrowser according to
266 static void CheckToolbar(IShellViewImpl
* This
)
272 if (IsInCommDlg(This
))
274 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_CHECKBUTTON
,
275 FCIDM_TB_SMALLICON
, (This
->FolderSettings
.ViewMode
==FVM_LIST
)? TRUE
: FALSE
, &result
);
276 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_CHECKBUTTON
,
277 FCIDM_TB_REPORTVIEW
, (This
->FolderSettings
.ViewMode
==FVM_DETAILS
)? TRUE
: FALSE
, &result
);
278 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_ENABLEBUTTON
,
279 FCIDM_TB_SMALLICON
, TRUE
, &result
);
280 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_ENABLEBUTTON
,
281 FCIDM_TB_REPORTVIEW
, TRUE
, &result
);
285 /**********************************************************
287 * ##### helperfunctions for initializing the view #####
289 /**********************************************************
290 * change the style of the listview control
292 static void SetStyle(IShellViewImpl
* This
, DWORD dwAdd
, DWORD dwRemove
)
296 TRACE("(%p)\n", This
);
298 tmpstyle
= GetWindowLongW(This
->hWndList
, GWL_STYLE
);
299 SetWindowLongW(This
->hWndList
, GWL_STYLE
, dwAdd
| (tmpstyle
& ~dwRemove
));
302 /**********************************************************
303 * ShellView_CreateList()
305 * - creates the list view window
307 static BOOL
ShellView_CreateList (IShellViewImpl
* This
)
308 { DWORD dwStyle
, dwExStyle
;
312 dwStyle
= WS_TABSTOP
| WS_VISIBLE
| WS_CHILDWINDOW
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
313 LVS_SHAREIMAGELISTS
| LVS_EDITLABELS
| LVS_ALIGNLEFT
| LVS_AUTOARRANGE
;
314 dwExStyle
= WS_EX_CLIENTEDGE
;
316 switch (This
->FolderSettings
.ViewMode
)
318 case FVM_ICON
: dwStyle
|= LVS_ICON
; break;
319 case FVM_DETAILS
: dwStyle
|= LVS_REPORT
; break;
320 case FVM_SMALLICON
: dwStyle
|= LVS_SMALLICON
; break;
321 case FVM_LIST
: dwStyle
|= LVS_LIST
; break;
322 default: dwStyle
|= LVS_LIST
; break;
325 if (This
->FolderSettings
.fFlags
& FWF_AUTOARRANGE
) dwStyle
|= LVS_AUTOARRANGE
;
326 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
)
327 This
->FolderSettings
.fFlags
|= FWF_NOCLIENTEDGE
| FWF_NOSCROLL
;
328 if (This
->FolderSettings
.fFlags
& FWF_SINGLESEL
) dwStyle
|= LVS_SINGLESEL
;
329 if (This
->FolderSettings
.fFlags
& FWF_NOCLIENTEDGE
)
330 dwExStyle
&= ~WS_EX_CLIENTEDGE
;
332 This
->hWndList
=CreateWindowExW( dwExStyle
,
345 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
346 This
->ListViewSortInfo
.nHeaderID
= -1;
347 This
->ListViewSortInfo
.nLastHeaderID
= -1;
349 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
) {
351 * FIXME: look at the registry value
352 * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
353 * and activate drop shadows if necessary
356 SendMessageW(This
->hWndList
, LVM_SETTEXTBKCOLOR
, 0, CLR_NONE
);
358 SendMessageW(This
->hWndList
, LVM_SETTEXTBKCOLOR
, 0, GetSysColor(COLOR_DESKTOP
));
360 SendMessageW(This
->hWndList
, LVM_SETTEXTCOLOR
, 0, RGB(255,255,255));
363 /* UpdateShellSettings(); */
367 /**********************************************************
368 * ShellView_InitList()
370 * - adds all needed columns to the shellview
372 static BOOL
ShellView_InitList(IShellViewImpl
* This
)
381 SendMessageW(This
->hWndList
, LVM_DELETEALLITEMS
, 0, 0);
383 lvColumn
.mask
= LVCF_FMT
| LVCF_WIDTH
| LVCF_TEXT
;
384 lvColumn
.pszText
= szTemp
;
386 if (This
->pSF2Parent
)
390 if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This
->pSF2Parent
, NULL
, i
, &sd
)))
392 lvColumn
.fmt
= sd
.fmt
;
393 lvColumn
.cx
= sd
.cxChar
*8; /* chars->pixel */
394 StrRetToStrNW( szTemp
, 50, &sd
.str
, NULL
);
395 SendMessageW(This
->hWndList
, LVM_INSERTCOLUMNW
, i
, (LPARAM
) &lvColumn
);
403 SendMessageW(This
->hWndList
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)ShellSmallIconList
);
404 SendMessageW(This
->hWndList
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)ShellBigIconList
);
408 /**********************************************************
409 * ShellView_CompareItems()
412 * internal, CALLBACK for DSA_Sort
414 static INT CALLBACK
ShellView_CompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
)
417 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1
, lParam2
, (LPVOID
) lpData
);
419 if(!lpData
) return 0;
421 ret
= (SHORT
) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER
)lpData
, 0, (LPITEMIDLIST
)lParam1
, (LPITEMIDLIST
)lParam2
));
422 TRACE("ret=%i\n",ret
);
426 /*************************************************************************
427 * ShellView_ListViewCompareItems
429 * Compare Function for the Listview (FileOpen Dialog)
432 * lParam1 [I] the first ItemIdList to compare with
433 * lParam2 [I] the second ItemIdList to compare with
434 * lpData [I] The column ID for the header Ctrl to process
437 * A negative value if the first item should precede the second,
438 * a positive value if the first item should follow the second,
439 * or zero if the two items are equivalent
442 * FIXME: function does what ShellView_CompareItems is supposed to do.
443 * unify it and figure out how to use the undocumented first parameter
444 * of IShellFolder_CompareIDs to do the job this function does and
445 * move this code to IShellFolder.
446 * make LISTVIEW_SORT_INFO obsolete
447 * the way this function works is only usable if we had only
448 * filesystemfolders (25/10/99 jsch)
450 static INT CALLBACK
ShellView_ListViewCompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
)
454 char strName1
[MAX_PATH
], strName2
[MAX_PATH
];
455 BOOL bIsFolder1
, bIsFolder2
,bIsBothFolder
;
456 LPITEMIDLIST pItemIdList1
= (LPITEMIDLIST
) lParam1
;
457 LPITEMIDLIST pItemIdList2
= (LPITEMIDLIST
) lParam2
;
458 LISTVIEW_SORT_INFO
*pSortInfo
= (LPLISTVIEW_SORT_INFO
) lpData
;
461 bIsFolder1
= _ILIsFolder(pItemIdList1
);
462 bIsFolder2
= _ILIsFolder(pItemIdList2
);
463 bIsBothFolder
= bIsFolder1
&& bIsFolder2
;
465 /* When sorting between a File and a Folder, the Folder gets sorted first */
466 if( (bIsFolder1
|| bIsFolder2
) && !bIsBothFolder
)
468 nDiff
= bIsFolder1
? -1 : 1;
472 /* Sort by Time: Folders or Files can be sorted */
474 if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_TIME
)
476 _ILGetFileDateTime(pItemIdList1
, &fd1
);
477 _ILGetFileDateTime(pItemIdList2
, &fd2
);
478 nDiff
= CompareFileTime(&fd2
, &fd1
);
480 /* Sort by Attribute: Folder or Files can be sorted */
481 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_ATTRIB
)
483 _ILGetFileAttributes(pItemIdList1
, strName1
, MAX_PATH
);
484 _ILGetFileAttributes(pItemIdList2
, strName2
, MAX_PATH
);
485 nDiff
= lstrcmpiA(strName1
, strName2
);
487 /* Sort by FileName: Folder or Files can be sorted */
488 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_NAME
|| bIsBothFolder
)
491 _ILSimpleGetText(pItemIdList1
, strName1
, MAX_PATH
);
492 _ILSimpleGetText(pItemIdList2
, strName2
, MAX_PATH
);
493 nDiff
= lstrcmpiA(strName1
, strName2
);
495 /* Sort by File Size, Only valid for Files */
496 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_SIZE
)
498 nDiff
= (INT
)(_ILGetFileSize(pItemIdList1
, NULL
, 0) - _ILGetFileSize(pItemIdList2
, NULL
, 0));
500 /* Sort by File Type, Only valid for Files */
501 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_TYPE
)
504 _ILGetFileType(pItemIdList1
, strName1
, MAX_PATH
);
505 _ILGetFileType(pItemIdList2
, strName2
, MAX_PATH
);
506 nDiff
= lstrcmpiA(strName1
, strName2
);
509 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
513 _ILSimpleGetText(pItemIdList1
, strName1
, MAX_PATH
);
514 _ILSimpleGetText(pItemIdList2
, strName2
, MAX_PATH
);
515 nDiff
= lstrcmpiA(strName1
, strName2
);
518 if(!pSortInfo
->bIsAscending
)
527 /**********************************************************
528 * LV_FindItemByPidl()
530 static int LV_FindItemByPidl(
531 IShellViewImpl
* This
,
536 lvItem
.mask
= LVIF_PARAM
;
537 for(lvItem
.iItem
= 0;
538 SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
541 LPITEMIDLIST currentpidl
= (LPITEMIDLIST
) lvItem
.lParam
;
542 HRESULT hr
= IShellFolder_CompareIDs(This
->pSFParent
, 0, pidl
, currentpidl
);
543 if(SUCCEEDED(hr
) && !HRESULT_CODE(hr
))
551 /**********************************************************
554 static BOOLEAN
LV_AddItem(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
558 TRACE("(%p)(pidl=%p)\n", This
, pidl
);
560 lvItem
.mask
= LVIF_TEXT
| LVIF_IMAGE
| LVIF_PARAM
; /*set the mask*/
561 lvItem
.iItem
= ListView_GetItemCount(This
->hWndList
); /*add the item to the end of the list*/
563 lvItem
.lParam
= (LPARAM
) ILClone(ILFindLastID(pidl
)); /*set the item's data*/
564 lvItem
.pszText
= LPSTR_TEXTCALLBACKW
; /*get text on a callback basis*/
565 lvItem
.iImage
= I_IMAGECALLBACK
; /*get the image on a callback basis*/
566 return (-1==ListView_InsertItemW(This
->hWndList
, &lvItem
))? FALSE
: TRUE
;
569 /**********************************************************
572 static BOOLEAN
LV_DeleteItem(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
576 TRACE("(%p)(pidl=%p)\n", This
, pidl
);
578 nIndex
= LV_FindItemByPidl(This
, ILFindLastID(pidl
));
579 return (-1==ListView_DeleteItem(This
->hWndList
, nIndex
))? FALSE
: TRUE
;
582 /**********************************************************
585 static BOOLEAN
LV_RenameItem(IShellViewImpl
* This
, LPCITEMIDLIST pidlOld
, LPCITEMIDLIST pidlNew
)
590 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This
, pidlOld
, pidlNew
);
592 nItem
= LV_FindItemByPidl(This
, ILFindLastID(pidlOld
));
595 lvItem
.mask
= LVIF_PARAM
; /* only the pidl */
596 lvItem
.iItem
= nItem
;
597 SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
599 SHFree((LPITEMIDLIST
)lvItem
.lParam
);
600 lvItem
.mask
= LVIF_PARAM
;
601 lvItem
.iItem
= nItem
;
602 lvItem
.lParam
= (LPARAM
) ILClone(ILFindLastID(pidlNew
)); /* set the item's data */
603 SendMessageW(This
->hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
604 SendMessageW(This
->hWndList
, LVM_UPDATE
, nItem
, 0);
605 return TRUE
; /* FIXME: better handling */
609 /**********************************************************
610 * ShellView_FillList()
612 * - gets the objectlist from the shellfolder
614 * - fills the list into the view
617 static INT CALLBACK
fill_list( LPVOID ptr
, LPVOID arg
)
619 LPITEMIDLIST pidl
= ptr
;
620 IShellViewImpl
*This
= arg
;
621 /* in a commdlg This works as a filemask*/
622 if ( IncludeObject(This
, pidl
)==S_OK
) LV_AddItem(This
, pidl
);
627 static HRESULT
ShellView_FillList(IShellViewImpl
* This
)
629 LPENUMIDLIST pEnumIDList
;
637 /* get the itemlist from the shfolder*/
638 hRes
= IShellFolder_EnumObjects(This
->pSFParent
,This
->hWnd
, SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
, &pEnumIDList
);
646 /* create a pointer array */
647 hdpa
= DPA_Create(16);
650 return(E_OUTOFMEMORY
);
653 /* copy the items into the array*/
654 while((S_OK
== IEnumIDList_Next(pEnumIDList
,1, &pidl
, &dwFetched
)) && dwFetched
)
656 if (DPA_InsertPtr(hdpa
, 0x7fff, pidl
) == -1)
663 DPA_Sort(hdpa
, ShellView_CompareItems
, (LPARAM
)This
->pSFParent
);
665 /*turn the listview's redrawing off*/
666 SendMessageA(This
->hWndList
, WM_SETREDRAW
, FALSE
, 0);
668 DPA_DestroyCallback( hdpa
, fill_list
, This
);
670 /*turn the listview's redrawing back on and force it to draw*/
671 SendMessageA(This
->hWndList
, WM_SETREDRAW
, TRUE
, 0);
673 IEnumIDList_Release(pEnumIDList
); /* destroy the list*/
678 /**********************************************************
679 * ShellView_OnCreate()
681 static LRESULT
ShellView_OnCreate(IShellViewImpl
* This
)
684 SHChangeNotifyEntry ntreg
;
685 IPersistFolder2
* ppf2
= NULL
;
689 if(ShellView_CreateList(This
))
691 if(ShellView_InitList(This
))
693 ShellView_FillList(This
);
697 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown
*)&This
->lpVtbl
, &IID_IDropTarget
, (LPVOID
*)&pdt
)))
699 RegisterDragDrop(This
->hWnd
, pdt
);
700 IDropTarget_Release(pdt
);
703 /* register for receiving notifications */
704 IShellFolder_QueryInterface(This
->pSFParent
, &IID_IPersistFolder2
, (LPVOID
*)&ppf2
);
707 IPersistFolder2_GetCurFolder(ppf2
, (LPITEMIDLIST
*)&ntreg
.pidl
);
708 ntreg
.fRecursive
= TRUE
;
709 This
->hNotify
= SHChangeNotifyRegister(This
->hWnd
, SHCNF_IDLIST
, SHCNE_ALLEVENTS
, SHV_CHANGE_NOTIFY
, 1, &ntreg
);
710 SHFree((LPITEMIDLIST
)ntreg
.pidl
);
711 IPersistFolder2_Release(ppf2
);
714 This
->hAccel
= LoadAcceleratorsA(shell32_hInstance
, "shv_accel");
719 /**********************************************************
720 * #### Handling of the menus ####
723 /**********************************************************
724 * ShellView_BuildFileMenu()
726 static HMENU
ShellView_BuildFileMenu(IShellViewImpl
* This
)
727 { WCHAR szText
[MAX_PATH
];
732 TRACE("(%p)\n",This
);
734 hSubMenu
= CreatePopupMenu();
736 { /*get the number of items in our global array*/
737 for(nTools
= 0; Tools
[nTools
].idCommand
!= -1; nTools
++){}
739 /*add the menu items*/
740 for(i
= 0; i
< nTools
; i
++)
742 LoadStringW(shell32_hInstance
, Tools
[i
].idMenuString
, szText
, MAX_PATH
);
744 ZeroMemory(&mii
, sizeof(mii
));
745 mii
.cbSize
= sizeof(mii
);
746 mii
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
748 if(BTNS_SEP
!= Tools
[i
].bStyle
) /* no separator*/
750 mii
.fType
= MFT_STRING
;
751 mii
.fState
= MFS_ENABLED
;
752 mii
.dwTypeData
= szText
;
753 mii
.wID
= Tools
[i
].idCommand
;
757 mii
.fType
= MFT_SEPARATOR
;
759 /* tack This item onto the end of the menu */
760 InsertMenuItemW(hSubMenu
, (UINT
)-1, TRUE
, &mii
);
763 TRACE("-- return (menu=%p)\n",hSubMenu
);
766 /**********************************************************
767 * ShellView_MergeFileMenu()
769 static void ShellView_MergeFileMenu(IShellViewImpl
* This
, HMENU hSubMenu
)
770 { TRACE("(%p)->(submenu=%p) stub\n",This
,hSubMenu
);
773 { /*insert This item at the beginning of the menu */
774 _InsertMenuItem(hSubMenu
, 0, TRUE
, 0, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
775 _InsertMenuItem(hSubMenu
, 0, TRUE
, IDM_MYFILEITEM
, MFT_STRING
, "dummy45", MFS_ENABLED
);
781 /**********************************************************
782 * ShellView_MergeViewMenu()
785 static void ShellView_MergeViewMenu(IShellViewImpl
* This
, HMENU hSubMenu
)
787 TRACE("(%p)->(submenu=%p)\n",This
,hSubMenu
);
790 { /*add a separator at the correct position in the menu*/
792 static char view
[] = "View";
794 _InsertMenuItem(hSubMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
, FALSE
, 0, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
796 ZeroMemory(&mii
, sizeof(mii
));
797 mii
.cbSize
= sizeof(mii
);
798 mii
.fMask
= MIIM_SUBMENU
| MIIM_TYPE
| MIIM_DATA
;
799 mii
.fType
= MFT_STRING
;
800 mii
.dwTypeData
= view
;
801 mii
.hSubMenu
= LoadMenuA(shell32_hInstance
, "MENU_001");
802 InsertMenuItemA(hSubMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
, FALSE
, &mii
);
806 /**********************************************************
807 * ShellView_GetSelections()
809 * - fills the this->apidl list with the selected objects
812 * number of selected items
814 static UINT
ShellView_GetSelections(IShellViewImpl
* This
)
821 This
->cidl
= ListView_GetSelectedCount(This
->hWndList
);
822 This
->apidl
= (LPITEMIDLIST
*)SHAlloc(This
->cidl
* sizeof(LPITEMIDLIST
));
824 TRACE("selected=%i\n", This
->cidl
);
828 TRACE("-- Items selected =%u\n", This
->cidl
);
830 lvItem
.mask
= LVIF_STATE
| LVIF_PARAM
;
831 lvItem
.stateMask
= LVIS_SELECTED
;
835 while(ListView_GetItemW(This
->hWndList
, &lvItem
) && (i
< This
->cidl
))
837 if(lvItem
.state
& LVIS_SELECTED
)
839 This
->apidl
[i
] = (LPITEMIDLIST
)lvItem
.lParam
;
841 TRACE("-- selected Item found\n");
850 /**********************************************************
851 * ShellView_OpenSelectedItems()
853 static HRESULT
ShellView_OpenSelectedItems(IShellViewImpl
* This
)
855 static UINT CF_IDLIST
= 0;
857 IDataObject
* selection
;
861 LPCITEMIDLIST parent_pidl
;
862 WCHAR parent_path
[MAX_PATH
];
863 LPCWSTR parent_dir
= NULL
;
867 if (0 == ShellView_GetSelections(This
))
871 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
,
872 (LPCITEMIDLIST
*)This
->apidl
, &IID_IDataObject
,
873 0, (LPVOID
*)&selection
);
879 CF_IDLIST
= RegisterClipboardFormatA(CFSTR_SHELLIDLIST
);
881 fetc
.cfFormat
= CF_IDLIST
;
883 fetc
.dwAspect
= DVASPECT_CONTENT
;
885 fetc
.tymed
= TYMED_HGLOBAL
;
887 hr
= IDataObject_QueryGetData(selection
, &fetc
);
891 hr
= IDataObject_GetData(selection
, &fetc
, &stgm
);
895 pIDList
= GlobalLock(stgm
.u
.hGlobal
);
897 parent_pidl
= (LPCITEMIDLIST
) ((LPBYTE
)pIDList
+pIDList
->aoffset
[0]);
898 hr
= IShellFolder_GetAttributesOf(This
->pSFParent
, 1, &parent_pidl
, &attribs
);
899 if (SUCCEEDED(hr
) && (attribs
& SFGAO_FILESYSTEM
) &&
900 SHGetPathFromIDListW(parent_pidl
, parent_path
))
902 parent_dir
= parent_path
;
905 for (i
= pIDList
->cidl
; i
> 0; --i
)
909 pidl
= (LPCITEMIDLIST
)((LPBYTE
)pIDList
+pIDList
->aoffset
[i
]);
911 attribs
= SFGAO_FOLDER
;
912 hr
= IShellFolder_GetAttributesOf(This
->pSFParent
, 1, &pidl
, &attribs
);
914 if (SUCCEEDED(hr
) && ! (attribs
& SFGAO_FOLDER
))
916 SHELLEXECUTEINFOW shexinfo
;
918 shexinfo
.cbSize
= sizeof(SHELLEXECUTEINFOW
);
919 shexinfo
.fMask
= SEE_MASK_INVOKEIDLIST
; /* SEE_MASK_IDLIST is also possible. */
920 shexinfo
.hwnd
= NULL
;
921 shexinfo
.lpVerb
= NULL
;
922 shexinfo
.lpFile
= NULL
;
923 shexinfo
.lpParameters
= NULL
;
924 shexinfo
.lpDirectory
= parent_dir
;
925 shexinfo
.nShow
= SW_NORMAL
;
926 shexinfo
.lpIDList
= ILCombine(parent_pidl
, pidl
);
928 ShellExecuteExW(&shexinfo
); /* Discard error/success info */
930 ILFree((LPITEMIDLIST
)shexinfo
.lpIDList
);
934 GlobalUnlock(stgm
.u
.hGlobal
);
935 ReleaseStgMedium(&stgm
);
937 IDataObject_Release(selection
);
942 /**********************************************************
943 * ShellView_DoContextMenu()
945 static void ShellView_DoContextMenu(IShellViewImpl
* This
, WORD x
, WORD y
, BOOL bDefault
)
949 BOOL fExplore
= FALSE
;
951 CMINVOKECOMMANDINFO cmi
;
953 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This
, x
, y
, bDefault
);
955 /* look, what's selected and create a context menu object of it*/
956 if( ShellView_GetSelections(This
) )
958 IShellFolder_GetUIObjectOf( This
->pSFParent
, This
->hWndParent
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
,
959 (REFIID
)&IID_IContextMenu
, NULL
, (LPVOID
*)&This
->pCM
);
963 TRACE("-- pContextMenu\n");
964 hMenu
= CreatePopupMenu();
968 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
969 if(SUCCEEDED(IShellBrowser_GetControlWindow(This
->pShellBrowser
,FCW_TREE
, &hwndTree
)) && hwndTree
)
971 TRACE("-- explore mode\n");
975 /* build the flags depending on what we can do with the selected item */
976 wFlags
= CMF_NORMAL
| (This
->cidl
!= 1 ? 0 : CMF_CANRENAME
) | (fExplore
? CMF_EXPLORE
: 0);
978 /* let the ContextMenu merge its items in */
979 if (SUCCEEDED(IContextMenu_QueryContextMenu( This
->pCM
, hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, wFlags
)))
981 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
)
982 SetMenuDefaultItem(hMenu
, FCIDM_SHVIEW_OPEN
, MF_BYCOMMAND
);
986 TRACE("-- get menu default command\n");
987 uCommand
= GetMenuDefaultItem(hMenu
, FALSE
, GMDI_GOINTOPOPUPS
);
991 TRACE("-- track popup\n");
992 uCommand
= TrackPopupMenu( hMenu
,TPM_LEFTALIGN
| TPM_RETURNCMD
,x
,y
,0,This
->hWnd
,NULL
);
997 TRACE("-- uCommand=%u\n", uCommand
);
998 if (uCommand
==FCIDM_SHVIEW_OPEN
&& IsInCommDlg(This
))
1000 TRACE("-- dlg: OnDefaultCommand\n");
1001 if (OnDefaultCommand(This
) != S_OK
)
1003 ShellView_OpenSelectedItems(This
);
1008 TRACE("-- explore -- invoke command\n");
1009 ZeroMemory(&cmi
, sizeof(cmi
));
1010 cmi
.cbSize
= sizeof(cmi
);
1011 cmi
.hwnd
= This
->hWndParent
; /* this window has to answer CWM_GETISHELLBROWSER */
1012 cmi
.lpVerb
= (LPCSTR
)MAKEINTRESOURCEA(uCommand
);
1013 IContextMenu_InvokeCommand(This
->pCM
, &cmi
);
1021 IContextMenu_Release(This
->pCM
);
1026 else /* background context menu */
1028 hMenu
= CreatePopupMenu();
1030 This
->pCM
= ISvBgCm_Constructor(This
->pSFParent
, FALSE
);
1031 IContextMenu2_QueryContextMenu(This
->pCM
, hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, 0);
1033 uCommand
= TrackPopupMenu( hMenu
, TPM_LEFTALIGN
| TPM_RETURNCMD
,x
,y
,0,This
->hWnd
,NULL
);
1036 TRACE("-- (%p)->(uCommand=0x%08x )\n",This
, uCommand
);
1038 ZeroMemory(&cmi
, sizeof(cmi
));
1039 cmi
.cbSize
= sizeof(cmi
);
1040 cmi
.lpVerb
= (LPCSTR
)MAKEINTRESOURCEA(uCommand
);
1041 cmi
.hwnd
= This
->hWndParent
;
1042 IContextMenu2_InvokeCommand(This
->pCM
, &cmi
);
1044 IContextMenu2_Release(This
->pCM
);
1049 /**********************************************************
1050 * ##### message handling #####
1053 /**********************************************************
1054 * ShellView_OnSize()
1056 static LRESULT
ShellView_OnSize(IShellViewImpl
* This
, WORD wWidth
, WORD wHeight
)
1058 TRACE("%p width=%u height=%u\n",This
, wWidth
,wHeight
);
1060 /*resize the ListView to fit our window*/
1063 MoveWindow(This
->hWndList
, 0, 0, wWidth
, wHeight
, TRUE
);
1068 /**********************************************************
1069 * ShellView_OnDeactivate()
1074 static void ShellView_OnDeactivate(IShellViewImpl
* This
)
1078 if(This
->uState
!= SVUIA_DEACTIVATE
)
1082 IShellBrowser_SetMenuSB(This
->pShellBrowser
,0, 0, 0);
1083 IShellBrowser_RemoveMenusSB(This
->pShellBrowser
,This
->hMenu
);
1084 DestroyMenu(This
->hMenu
);
1088 This
->uState
= SVUIA_DEACTIVATE
;
1092 /**********************************************************
1093 * ShellView_OnActivate()
1095 static LRESULT
ShellView_OnActivate(IShellViewImpl
* This
, UINT uState
)
1096 { OLEMENUGROUPWIDTHS omw
= { {0, 0, 0, 0, 0, 0} };
1098 CHAR szText
[MAX_PATH
];
1100 TRACE("%p uState=%x\n",This
,uState
);
1102 /*don't do anything if the state isn't really changing */
1103 if(This
->uState
== uState
)
1108 ShellView_OnDeactivate(This
);
1110 /*only do This if we are active */
1111 if(uState
!= SVUIA_DEACTIVATE
)
1113 /*merge the menus */
1114 This
->hMenu
= CreateMenu();
1118 IShellBrowser_InsertMenusSB(This
->pShellBrowser
, This
->hMenu
, &omw
);
1119 TRACE("-- after fnInsertMenusSB\n");
1121 /*build the top level menu get the menu item's text*/
1122 strcpy(szText
,"dummy 31");
1124 ZeroMemory(&mii
, sizeof(mii
));
1125 mii
.cbSize
= sizeof(mii
);
1126 mii
.fMask
= MIIM_SUBMENU
| MIIM_TYPE
| MIIM_STATE
;
1127 mii
.fType
= MFT_STRING
;
1128 mii
.fState
= MFS_ENABLED
;
1129 mii
.dwTypeData
= szText
;
1130 mii
.hSubMenu
= ShellView_BuildFileMenu(This
);
1132 /*insert our menu into the menu bar*/
1135 InsertMenuItemA(This
->hMenu
, FCIDM_MENU_HELP
, FALSE
, &mii
);
1138 /*get the view menu so we can merge with it*/
1139 ZeroMemory(&mii
, sizeof(mii
));
1140 mii
.cbSize
= sizeof(mii
);
1141 mii
.fMask
= MIIM_SUBMENU
;
1143 if(GetMenuItemInfoA(This
->hMenu
, FCIDM_MENU_VIEW
, FALSE
, &mii
))
1145 ShellView_MergeViewMenu(This
, mii
.hSubMenu
);
1148 /*add the items that should only be added if we have the focus*/
1149 if(SVUIA_ACTIVATE_FOCUS
== uState
)
1151 /*get the file menu so we can merge with it */
1152 ZeroMemory(&mii
, sizeof(mii
));
1153 mii
.cbSize
= sizeof(mii
);
1154 mii
.fMask
= MIIM_SUBMENU
;
1156 if(GetMenuItemInfoA(This
->hMenu
, FCIDM_MENU_FILE
, FALSE
, &mii
))
1158 ShellView_MergeFileMenu(This
, mii
.hSubMenu
);
1161 TRACE("-- before fnSetMenuSB\n");
1162 IShellBrowser_SetMenuSB(This
->pShellBrowser
, This
->hMenu
, 0, This
->hWnd
);
1165 This
->uState
= uState
;
1170 /**********************************************************
1171 * ShellView_OnSetFocus()
1174 static LRESULT
ShellView_OnSetFocus(IShellViewImpl
* This
)
1178 /* Tell the browser one of our windows has received the focus. This
1179 should always be done before merging menus (OnActivate merges the
1180 menus) if one of our windows has the focus.*/
1182 IShellBrowser_OnViewWindowActive(This
->pShellBrowser
,(IShellView
*) This
);
1183 ShellView_OnActivate(This
, SVUIA_ACTIVATE_FOCUS
);
1185 /* Set the focus to the listview */
1186 SetFocus(This
->hWndList
);
1188 /* Notify the ICommDlgBrowser interface */
1189 OnStateChange(This
,CDBOSC_SETFOCUS
);
1194 /**********************************************************
1195 * ShellView_OnKillFocus()
1197 static LRESULT
ShellView_OnKillFocus(IShellViewImpl
* This
)
1199 TRACE("(%p) stub\n",This
);
1201 ShellView_OnActivate(This
, SVUIA_ACTIVATE_NOFOCUS
);
1202 /* Notify the ICommDlgBrowser */
1203 OnStateChange(This
,CDBOSC_KILLFOCUS
);
1208 /**********************************************************
1209 * ShellView_OnCommand()
1212 * the CmdID's are the ones from the context menu
1214 static LRESULT
ShellView_OnCommand(IShellViewImpl
* This
,DWORD dwCmdID
, DWORD dwCmd
, HWND hwndCmd
)
1216 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",This
, dwCmdID
, dwCmd
, hwndCmd
);
1220 case FCIDM_SHVIEW_SMALLICON
:
1221 This
->FolderSettings
.ViewMode
= FVM_SMALLICON
;
1222 SetStyle (This
, LVS_SMALLICON
, LVS_TYPEMASK
);
1226 case FCIDM_SHVIEW_BIGICON
:
1227 This
->FolderSettings
.ViewMode
= FVM_ICON
;
1228 SetStyle (This
, LVS_ICON
, LVS_TYPEMASK
);
1232 case FCIDM_SHVIEW_LISTVIEW
:
1233 This
->FolderSettings
.ViewMode
= FVM_LIST
;
1234 SetStyle (This
, LVS_LIST
, LVS_TYPEMASK
);
1238 case FCIDM_SHVIEW_REPORTVIEW
:
1239 This
->FolderSettings
.ViewMode
= FVM_DETAILS
;
1240 SetStyle (This
, LVS_REPORT
, LVS_TYPEMASK
);
1244 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1249 This
->ListViewSortInfo
.nHeaderID
= (LPARAM
) (dwCmdID
- 0x30);
1250 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
1251 This
->ListViewSortInfo
.nLastHeaderID
= This
->ListViewSortInfo
.nHeaderID
;
1252 SendMessageA(This
->hWndList
, LVM_SORTITEMS
, (WPARAM
) &This
->ListViewSortInfo
, (LPARAM
)ShellView_ListViewCompareItems
);
1256 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID
);
1261 /**********************************************************
1262 * ShellView_OnNotify()
1265 static LRESULT
ShellView_OnNotify(IShellViewImpl
* This
, UINT CtlID
, LPNMHDR lpnmh
)
1266 { LPNMLISTVIEW lpnmlv
= (LPNMLISTVIEW
)lpnmh
;
1267 NMLVDISPINFOW
*lpdi
= (NMLVDISPINFOW
*)lpnmh
;
1270 TRACE("%p CtlID=%u lpnmh->code=%x\n",This
,CtlID
,lpnmh
->code
);
1275 TRACE("-- NM_SETFOCUS %p\n",This
);
1276 ShellView_OnSetFocus(This
);
1280 TRACE("-- NM_KILLFOCUS %p\n",This
);
1281 ShellView_OnDeactivate(This
);
1282 /* Notify the ICommDlgBrowser interface */
1283 OnStateChange(This
,CDBOSC_KILLFOCUS
);
1287 TRACE("-- NM_CUSTOMDRAW %p\n",This
);
1288 return CDRF_DODEFAULT
;
1290 case NM_RELEASEDCAPTURE
:
1291 TRACE("-- NM_RELEASEDCAPTURE %p\n",This
);
1295 TRACE("-- NM_CLICK %p\n",This
);
1299 TRACE("-- NM_RCLICK %p\n",This
);
1303 TRACE("-- NM_DBLCLK %p\n",This
);
1304 if (OnDefaultCommand(This
) != S_OK
) ShellView_OpenSelectedItems(This
);
1308 TRACE("-- NM_DBLCLK %p\n",This
);
1309 if (OnDefaultCommand(This
) != S_OK
) ShellView_OpenSelectedItems(This
);
1313 TRACE("-- HDN_ENDTRACKW %p\n",This
);
1314 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1315 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1318 case LVN_DELETEITEM
:
1319 TRACE("-- LVN_DELETEITEM %p\n",This
);
1320 SHFree((LPITEMIDLIST
)lpnmlv
->lParam
); /*delete the pidl because we made a copy of it*/
1323 case LVN_DELETEALLITEMS
:
1324 TRACE("-- LVN_DELETEALLITEMS %p\n",This
);
1327 case LVN_INSERTITEM
:
1328 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This
);
1331 case LVN_ITEMACTIVATE
:
1332 TRACE("-- LVN_ITEMACTIVATE %p\n",This
);
1333 OnStateChange(This
, CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1336 case LVN_COLUMNCLICK
:
1337 This
->ListViewSortInfo
.nHeaderID
= lpnmlv
->iSubItem
;
1338 if(This
->ListViewSortInfo
.nLastHeaderID
== This
->ListViewSortInfo
.nHeaderID
)
1340 This
->ListViewSortInfo
.bIsAscending
= !This
->ListViewSortInfo
.bIsAscending
;
1344 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
1346 This
->ListViewSortInfo
.nLastHeaderID
= This
->ListViewSortInfo
.nHeaderID
;
1348 SendMessageW(lpnmlv
->hdr
.hwndFrom
, LVM_SORTITEMS
, (WPARAM
) &This
->ListViewSortInfo
, (LPARAM
)ShellView_ListViewCompareItems
);
1351 case LVN_GETDISPINFOA
:
1352 case LVN_GETDISPINFOW
:
1353 TRACE("-- LVN_GETDISPINFO %p\n",This
);
1354 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1356 if(lpdi
->item
.mask
& LVIF_TEXT
) /* text requested */
1358 if (This
->pSF2Parent
)
1361 IShellFolder2_GetDetailsOf(This
->pSF2Parent
, pidl
, lpdi
->item
.iSubItem
, &sd
);
1362 if (lpnmh
->code
== LVN_GETDISPINFOA
)
1364 /* shouldn't happen */
1365 NMLVDISPINFOA
*lpdiA
= (NMLVDISPINFOA
*)lpnmh
;
1366 StrRetToStrNA( lpdiA
->item
.pszText
, lpdiA
->item
.cchTextMax
, &sd
.str
, NULL
);
1367 TRACE("-- text=%s\n",lpdiA
->item
.pszText
);
1369 else /* LVN_GETDISPINFOW */
1371 StrRetToStrNW( lpdi
->item
.pszText
, lpdi
->item
.cchTextMax
, &sd
.str
, NULL
);
1372 TRACE("-- text=%s\n",debugstr_w(lpdi
->item
.pszText
));
1380 if(lpdi
->item
.mask
& LVIF_IMAGE
) /* image requested */
1382 lpdi
->item
.iImage
= SHMapPIDLToSystemImageListIndex(This
->pSFParent
, pidl
, 0);
1386 case LVN_ITEMCHANGED
:
1387 TRACE("-- LVN_ITEMCHANGED %p\n",This
);
1388 OnStateChange(This
, CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1392 case LVN_BEGINRDRAG
:
1393 TRACE("-- LVN_BEGINDRAG\n");
1395 if (ShellView_GetSelections(This
))
1398 DWORD dwAttributes
= SFGAO_CANLINK
;
1399 DWORD dwEffect
= DROPEFFECT_COPY
| DROPEFFECT_MOVE
;
1401 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, &IID_IDataObject
,0,(LPVOID
*)&pda
)))
1403 IDropSource
* pds
= (IDropSource
*)&(This
->lpvtblDropSource
); /* own DropSource interface */
1405 if (SUCCEEDED(IShellFolder_GetAttributesOf(This
->pSFParent
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, &dwAttributes
)))
1407 if (dwAttributes
& SFGAO_CANLINK
)
1409 dwEffect
|= DROPEFFECT_LINK
;
1416 DoDragDrop(pda
, pds
, dwEffect
, &dwEffect
);
1418 IDataObject_Release(pda
);
1423 case LVN_BEGINLABELEDITW
:
1425 DWORD dwAttr
= SFGAO_CANRENAME
;
1426 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1428 TRACE("-- LVN_BEGINLABELEDITA %p\n",This
);
1430 IShellFolder_GetAttributesOf(This
->pSFParent
, 1, (LPCITEMIDLIST
*)&pidl
, &dwAttr
);
1431 if (SFGAO_CANRENAME
& dwAttr
)
1438 case LVN_ENDLABELEDITW
:
1440 TRACE("-- LVN_ENDLABELEDITA %p\n",This
);
1441 if (lpdi
->item
.pszText
)
1446 lvItem
.iItem
= lpdi
->item
.iItem
;
1447 lvItem
.iSubItem
= 0;
1448 lvItem
.mask
= LVIF_PARAM
;
1449 SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
1451 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1452 hr
= IShellFolder_SetNameOf(This
->pSFParent
, 0, pidl
, lpdi
->item
.pszText
, SHGDN_INFOLDER
, &pidl
);
1454 if(SUCCEEDED(hr
) && pidl
)
1456 lvItem
.mask
= LVIF_PARAM
;
1457 lvItem
.lParam
= (LPARAM
)pidl
;
1458 SendMessageW(This
->hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
1468 msg.hwnd = This->hWnd;
1469 msg.message = WM_KEYDOWN;
1470 msg.wParam = plvKeyDown->wVKey;
1475 LPNMLVKEYDOWN plvKeyDown
= (LPNMLVKEYDOWN
) lpnmh
;
1477 /* initiate a rename of the selected file or directory */
1478 if(plvKeyDown
->wVKey
== VK_F2
)
1480 /* see how many files are selected */
1481 int i
= ListView_GetSelectedCount(This
->hWndList
);
1483 /* get selected item */
1486 /* get selected item */
1487 i
= ListView_GetNextItem(This
->hWndList
, -1,
1490 SendMessageW(This
->hWndList
, LVM_ENSUREVISIBLE
, i
, 0);
1491 SendMessageW(This
->hWndList
, LVM_EDITLABELW
, i
, 0);
1495 TranslateAccelerator(This
->hWnd
, This
->hAccel
, &msg
)
1497 else if(plvKeyDown
->wVKey
== VK_DELETE
)
1502 LPITEMIDLIST
* pItems
;
1505 IShellFolder_QueryInterface(This
->pSFParent
, &IID_ISFHelper
,
1511 if(!(i
= ListView_GetSelectedCount(This
->hWndList
)))
1514 /* allocate memory for the pidl array */
1515 pItems
= HeapAlloc(GetProcessHeap(), 0,
1516 sizeof(LPITEMIDLIST
) * i
);
1518 /* retrieve all selected items */
1521 while(ListView_GetSelectedCount(This
->hWndList
) > i
)
1523 /* get selected item */
1524 item_index
= ListView_GetNextItem(This
->hWndList
,
1525 item_index
, LVNI_SELECTED
);
1526 item
.iItem
= item_index
;
1527 item
.mask
= LVIF_PARAM
;
1528 SendMessageA(This
->hWndList
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1531 pItems
[i
] = (LPITEMIDLIST
)item
.lParam
;
1536 /* perform the item deletion */
1537 ISFHelper_DeleteItems(psfhlp
, i
, (LPCITEMIDLIST
*)pItems
);
1539 /* free pidl array memory */
1540 HeapFree(GetProcessHeap(), 0, pItems
);
1543 /* Initiate a refresh */
1544 else if(plvKeyDown
->wVKey
== VK_F5
)
1546 IShellView_Refresh((IShellView
*)This
);
1550 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown
->wVKey
);
1555 TRACE("-- %p WM_COMMAND %x unhandled\n", This
, lpnmh
->code
);
1561 /**********************************************************
1562 * ShellView_OnChange()
1565 static LRESULT
ShellView_OnChange(IShellViewImpl
* This
, LPITEMIDLIST
* Pidls
, LONG wEventId
)
1568 TRACE("(%p)(%p,%p,0x%08x)\n", This
, Pidls
[0], Pidls
[1], wEventId
);
1573 LV_AddItem(This
, Pidls
[0]);
1577 LV_DeleteItem(This
, Pidls
[0]);
1579 case SHCNE_RENAMEFOLDER
:
1580 case SHCNE_RENAMEITEM
:
1581 LV_RenameItem(This
, Pidls
[0], Pidls
[1]);
1583 case SHCNE_UPDATEITEM
:
1589 /**********************************************************
1590 * ShellView_DoMeasureItem
1593 static LRESULT
ShellView_DoCustomItem(IShellViewImpl
* pThis
, HWND hWnd
, UINT uMsg
, LPARAM lParam
)
1598 ERR("no menu!!!\n");
1602 if (pThis
->pCM
->lpVtbl
->HandleMenuMsg(pThis
->pCM
, uMsg
, (WPARAM
)hWnd
, lParam
) == S_OK
)
1608 /**********************************************************
1612 static LRESULT CALLBACK
ShellView_WndProc(HWND hWnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
)
1614 IShellViewImpl
* pThis
= (IShellViewImpl
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
1615 LPCREATESTRUCTW lpcs
;
1617 TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd
, uMessage
, wParam
, lParam
);
1622 lpcs
= (LPCREATESTRUCTW
)lParam
;
1623 pThis
= (IShellViewImpl
*)(lpcs
->lpCreateParams
);
1624 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (ULONG_PTR
)pThis
);
1625 pThis
->hWnd
= hWnd
; /*set the window handle*/
1628 case WM_SIZE
: return ShellView_OnSize(pThis
,LOWORD(lParam
), HIWORD(lParam
));
1629 case WM_SETFOCUS
: return ShellView_OnSetFocus(pThis
);
1630 case WM_KILLFOCUS
: return ShellView_OnKillFocus(pThis
);
1631 case WM_CREATE
: return ShellView_OnCreate(pThis
);
1632 case WM_ACTIVATE
: return ShellView_OnActivate(pThis
, SVUIA_ACTIVATE_FOCUS
);
1633 case WM_NOTIFY
: return ShellView_OnNotify(pThis
,(UINT
)wParam
, (LPNMHDR
)lParam
);
1634 case WM_COMMAND
: return ShellView_OnCommand(pThis
,
1635 GET_WM_COMMAND_ID(wParam
, lParam
),
1636 GET_WM_COMMAND_CMD(wParam
, lParam
),
1637 GET_WM_COMMAND_HWND(wParam
, lParam
));
1638 case SHV_CHANGE_NOTIFY
: return ShellView_OnChange(pThis
, (LPITEMIDLIST
*)wParam
, (LONG
)lParam
);
1640 case WM_CONTEXTMENU
: ShellView_DoContextMenu(pThis
, LOWORD(lParam
), HIWORD(lParam
), FALSE
);
1643 case WM_MEASUREITEM
:
1644 return ShellView_DoCustomItem(pThis
, hWnd
, uMessage
, lParam
);
1646 case WM_SHOWWINDOW
: UpdateWindow(pThis
->hWndList
);
1649 case WM_GETDLGCODE
: return SendMessageA(pThis
->hWndList
,uMessage
,0,0);
1652 RevokeDragDrop(pThis
->hWnd
);
1653 SHChangeNotifyDeregister(pThis
->hNotify
);
1657 if ((pThis
->FolderSettings
.fFlags
& FWF_DESKTOP
) ||
1658 (pThis
->FolderSettings
.fFlags
& FWF_TRANSPARENT
))
1661 case CWM_GETISHELLBROWSER
:
1662 return pThis
->pShellBrowser
;
1664 return DefWindowProcW(hWnd
, uMessage
, wParam
, lParam
);
1666 /**********************************************************
1669 * The INTERFACE of the IShellView object
1672 **********************************************************
1673 * IShellView_QueryInterface
1675 static HRESULT WINAPI
IShellView_fnQueryInterface(IShellView
* iface
,REFIID riid
, LPVOID
*ppvObj
)
1677 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1679 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
1683 if(IsEqualIID(riid
, &IID_IUnknown
))
1687 else if(IsEqualIID(riid
, &IID_IShellView
))
1689 *ppvObj
= (IShellView
*)This
;
1691 else if(IsEqualIID(riid
, &IID_IOleCommandTarget
))
1693 *ppvObj
= (IOleCommandTarget
*)&(This
->lpvtblOleCommandTarget
);
1695 else if(IsEqualIID(riid
, &IID_IDropTarget
))
1697 *ppvObj
= (IDropTarget
*)&(This
->lpvtblDropTarget
);
1699 else if(IsEqualIID(riid
, &IID_IDropSource
))
1701 *ppvObj
= (IDropSource
*)&(This
->lpvtblDropSource
);
1703 else if(IsEqualIID(riid
, &IID_IViewObject
))
1705 *ppvObj
= (IViewObject
*)&(This
->lpvtblViewObject
);
1710 IUnknown_AddRef( (IUnknown
*)*ppvObj
);
1711 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
1714 TRACE("-- Interface: E_NOINTERFACE\n");
1715 return E_NOINTERFACE
;
1718 /**********************************************************
1721 static ULONG WINAPI
IShellView_fnAddRef(IShellView
* iface
)
1723 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1724 ULONG refCount
= InterlockedIncrement(&This
->ref
);
1726 TRACE("(%p)->(count=%u)\n", This
, refCount
- 1);
1730 /**********************************************************
1731 * IShellView_Release
1733 static ULONG WINAPI
IShellView_fnRelease(IShellView
* iface
)
1735 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1736 ULONG refCount
= InterlockedDecrement(&This
->ref
);
1738 TRACE("(%p)->(count=%i)\n", This
, refCount
+ 1);
1742 TRACE(" destroying IShellView(%p)\n",This
);
1744 DestroyWindow(This
->hWndList
);
1747 IShellFolder_Release(This
->pSFParent
);
1749 if(This
->pSF2Parent
)
1750 IShellFolder2_Release(This
->pSF2Parent
);
1752 SHFree(This
->apidl
);
1755 IAdviseSink_Release(This
->pAdvSink
);
1758 IContextMenu_Release(This
->pCM
);
1760 HeapFree(GetProcessHeap(),0,This
);
1765 /**********************************************************
1766 * ShellView_GetWindow
1768 static HRESULT WINAPI
IShellView_fnGetWindow(IShellView
* iface
,HWND
* phWnd
)
1770 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1772 TRACE("(%p)\n",This
);
1774 *phWnd
= This
->hWnd
;
1779 static HRESULT WINAPI
IShellView_fnContextSensitiveHelp(IShellView
* iface
,BOOL fEnterMode
)
1781 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1783 FIXME("(%p) stub\n",This
);
1788 /**********************************************************
1789 * IShellView_TranslateAccelerator
1792 * use the accel functions
1794 static HRESULT WINAPI
IShellView_fnTranslateAccelerator(IShellView
* iface
,LPMSG lpmsg
)
1797 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1799 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This
,lpmsg
, lpmsg
->hwnd
, lpmsg
->message
, lpmsg
->lParam
, lpmsg
->wParam
);
1802 if ((lpmsg
->message
>=WM_KEYFIRST
) && (lpmsg
->message
>=WM_KEYLAST
))
1804 TRACE("-- key=0x04%lx\n",lpmsg
->wParam
) ;
1806 return S_FALSE
; /* not handled */
1809 static HRESULT WINAPI
IShellView_fnEnableModeless(IShellView
* iface
,BOOL fEnable
)
1811 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1813 FIXME("(%p) stub\n",This
);
1818 static HRESULT WINAPI
IShellView_fnUIActivate(IShellView
* iface
,UINT uState
)
1820 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1823 CHAR szName[MAX_PATH];
1826 int nPartArray
[1] = {-1};
1828 TRACE("(%p)->(state=%x) stub\n",This
, uState
);
1830 /*don't do anything if the state isn't really changing*/
1831 if(This
->uState
== uState
)
1836 /*OnActivate handles the menu merging and internal state*/
1837 ShellView_OnActivate(This
, uState
);
1839 /*only do This if we are active*/
1840 if(uState
!= SVUIA_DEACTIVATE
)
1844 GetFolderPath is not a method of IShellFolder
1845 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1847 /* set the number of parts */
1848 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_STATUS
, SB_SETPARTS
, 1,
1849 (LPARAM
)nPartArray
, &lResult
);
1851 /* set the text for the parts */
1853 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1854 0, (LPARAM)szName, &lResult);
1861 static HRESULT WINAPI
IShellView_fnRefresh(IShellView
* iface
)
1863 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1865 TRACE("(%p)\n",This
);
1867 SendMessageW(This
->hWndList
, LVM_DELETEALLITEMS
, 0, 0);
1868 ShellView_FillList(This
);
1873 static HRESULT WINAPI
IShellView_fnCreateViewWindow(
1875 IShellView
*lpPrevView
,
1876 LPCFOLDERSETTINGS lpfs
,
1877 IShellBrowser
* psb
,
1881 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1887 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This
, lpPrevView
,lpfs
, psb
, prcView
, phWnd
);
1888 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
);
1890 /*set up the member variables*/
1891 This
->pShellBrowser
= psb
;
1892 This
->FolderSettings
= *lpfs
;
1894 /*get our parent window*/
1895 IShellBrowser_AddRef(This
->pShellBrowser
);
1896 IShellBrowser_GetWindow(This
->pShellBrowser
, &(This
->hWndParent
));
1898 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1899 This
->pCommDlgBrowser
=NULL
;
1900 if ( SUCCEEDED (IShellBrowser_QueryInterface( This
->pShellBrowser
,
1901 (REFIID
)&IID_ICommDlgBrowser
, (LPVOID
*) &This
->pCommDlgBrowser
)))
1903 TRACE("-- CommDlgBrowser\n");
1906 /*if our window class has not been registered, then do so*/
1907 if(!GetClassInfoW(shell32_hInstance
, SV_CLASS_NAME
, &wc
))
1909 ZeroMemory(&wc
, sizeof(wc
));
1910 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1911 wc
.lpfnWndProc
= ShellView_WndProc
;
1914 wc
.hInstance
= shell32_hInstance
;
1916 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1917 wc
.hbrBackground
= (HBRUSH
) (COLOR_WINDOW
+ 1);
1918 wc
.lpszMenuName
= NULL
;
1919 wc
.lpszClassName
= SV_CLASS_NAME
;
1921 if(!RegisterClassW(&wc
))
1925 *phWnd
= CreateWindowExW(0,
1928 WS_CHILD
| WS_TABSTOP
,
1931 prcView
->right
- prcView
->left
,
1932 prcView
->bottom
- prcView
->top
,
1940 if(!*phWnd
) return E_FAIL
;
1942 SetWindowPos(*phWnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_SHOWWINDOW
);
1943 UpdateWindow(*phWnd
);
1948 static HRESULT WINAPI
IShellView_fnDestroyViewWindow(IShellView
* iface
)
1950 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1952 TRACE("(%p)\n",This
);
1954 /*Make absolutely sure all our UI is cleaned up.*/
1955 IShellView_UIActivate((IShellView
*)This
, SVUIA_DEACTIVATE
);
1959 DestroyMenu(This
->hMenu
);
1962 DestroyWindow(This
->hWnd
);
1963 if(This
->pShellBrowser
) IShellBrowser_Release(This
->pShellBrowser
);
1964 if(This
->pCommDlgBrowser
) ICommDlgBrowser_Release(This
->pCommDlgBrowser
);
1970 static HRESULT WINAPI
IShellView_fnGetCurrentInfo(IShellView
* iface
, LPFOLDERSETTINGS lpfs
)
1972 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1974 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This
, lpfs
,
1975 This
->FolderSettings
.ViewMode
, This
->FolderSettings
.fFlags
);
1977 if (!lpfs
) return E_INVALIDARG
;
1979 *lpfs
= This
->FolderSettings
;
1983 static HRESULT WINAPI
IShellView_fnAddPropertySheetPages(IShellView
* iface
, DWORD dwReserved
,LPFNADDPROPSHEETPAGE lpfn
, LPARAM lparam
)
1985 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1987 FIXME("(%p) stub\n",This
);
1992 static HRESULT WINAPI
IShellView_fnSaveViewState(IShellView
* iface
)
1994 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1996 FIXME("(%p) stub\n",This
);
2001 static HRESULT WINAPI
IShellView_fnSelectItem(
2006 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2009 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This
, pidl
, uFlags
);
2011 i
= LV_FindItemByPidl(This
, pidl
);
2017 if(uFlags
& SVSI_ENSUREVISIBLE
)
2018 SendMessageW(This
->hWndList
, LVM_ENSUREVISIBLE
, i
, 0);
2020 lvItem
.mask
= LVIF_STATE
;
2021 lvItem
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
2023 lvItem
.iSubItem
= 0;
2025 while(SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
))
2027 if (lvItem
.iItem
== i
)
2029 if (uFlags
& SVSI_SELECT
)
2030 lvItem
.state
|= LVIS_SELECTED
;
2032 lvItem
.state
&= ~LVIS_SELECTED
;
2034 if(uFlags
& SVSI_FOCUSED
)
2035 lvItem
.state
&= ~LVIS_FOCUSED
;
2039 if (uFlags
& SVSI_DESELECTOTHERS
)
2040 lvItem
.state
&= ~LVIS_SELECTED
;
2042 SendMessageW(This
->hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
2047 if(uFlags
& SVSI_EDIT
)
2048 SendMessageW(This
->hWndList
, LVM_EDITLABELW
, i
, 0);
2054 static HRESULT WINAPI
IShellView_fnGetItemObject(IShellView
* iface
, UINT uItem
, REFIID riid
, LPVOID
*ppvOut
)
2056 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2058 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This
, uItem
, debugstr_guid(riid
), ppvOut
);
2064 case SVGIO_BACKGROUND
:
2065 *ppvOut
= ISvBgCm_Constructor(This
->pSFParent
, FALSE
);
2068 case SVGIO_SELECTION
:
2069 ShellView_GetSelections(This
);
2070 IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, riid
, 0, ppvOut
);
2073 TRACE("-- (%p)->(interface=%p)\n",This
, *ppvOut
);
2075 if(!*ppvOut
) return E_OUTOFMEMORY
;
2080 static const IShellViewVtbl svvt
=
2082 IShellView_fnQueryInterface
,
2083 IShellView_fnAddRef
,
2084 IShellView_fnRelease
,
2085 IShellView_fnGetWindow
,
2086 IShellView_fnContextSensitiveHelp
,
2087 IShellView_fnTranslateAccelerator
,
2088 IShellView_fnEnableModeless
,
2089 IShellView_fnUIActivate
,
2090 IShellView_fnRefresh
,
2091 IShellView_fnCreateViewWindow
,
2092 IShellView_fnDestroyViewWindow
,
2093 IShellView_fnGetCurrentInfo
,
2094 IShellView_fnAddPropertySheetPages
,
2095 IShellView_fnSaveViewState
,
2096 IShellView_fnSelectItem
,
2097 IShellView_fnGetItemObject
2101 /**********************************************************
2102 * ISVOleCmdTarget_QueryInterface (IUnknown)
2104 static HRESULT WINAPI
ISVOleCmdTarget_QueryInterface(
2105 IOleCommandTarget
* iface
,
2109 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2111 return IShellFolder_QueryInterface((IShellFolder
*)This
, iid
, ppvObj
);
2114 /**********************************************************
2115 * ISVOleCmdTarget_AddRef (IUnknown)
2117 static ULONG WINAPI
ISVOleCmdTarget_AddRef(
2118 IOleCommandTarget
* iface
)
2120 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2122 return IShellFolder_AddRef((IShellFolder
*)This
);
2125 /**********************************************************
2126 * ISVOleCmdTarget_Release (IUnknown)
2128 static ULONG WINAPI
ISVOleCmdTarget_Release(
2129 IOleCommandTarget
* iface
)
2131 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2133 return IShellFolder_Release((IShellFolder
*)This
);
2136 /**********************************************************
2137 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2139 static HRESULT WINAPI
ISVOleCmdTarget_QueryStatus(
2140 IOleCommandTarget
*iface
,
2141 const GUID
* pguidCmdGroup
,
2144 OLECMDTEXT
* pCmdText
)
2147 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2149 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2150 This
, pguidCmdGroup
, debugstr_guid(pguidCmdGroup
), cCmds
, prgCmds
, pCmdText
);
2154 for (i
= 0; i
< cCmds
; i
++)
2156 FIXME("\tprgCmds[%d].cmdID = %d\n", i
, prgCmds
[i
].cmdID
);
2157 prgCmds
[i
].cmdf
= 0;
2159 return OLECMDERR_E_UNKNOWNGROUP
;
2162 /**********************************************************
2163 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2165 * nCmdID is the OLECMDID_* enumeration
2167 static HRESULT WINAPI
ISVOleCmdTarget_Exec(
2168 IOleCommandTarget
*iface
,
2169 const GUID
* pguidCmdGroup
,
2175 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2177 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2178 This
, debugstr_guid(pguidCmdGroup
), nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
2180 if (IsEqualIID(pguidCmdGroup
, &CGID_Explorer
) &&
2182 (nCmdexecopt
== 4) && pvaOut
)
2184 if (IsEqualIID(pguidCmdGroup
, &CGID_ShellDocView
) &&
2189 return OLECMDERR_E_UNKNOWNGROUP
;
2192 static const IOleCommandTargetVtbl ctvt
=
2194 ISVOleCmdTarget_QueryInterface
,
2195 ISVOleCmdTarget_AddRef
,
2196 ISVOleCmdTarget_Release
,
2197 ISVOleCmdTarget_QueryStatus
,
2198 ISVOleCmdTarget_Exec
2201 /**********************************************************
2202 * ISVDropTarget implementation
2205 static HRESULT WINAPI
ISVDropTarget_QueryInterface(
2210 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2212 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2214 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2217 static ULONG WINAPI
ISVDropTarget_AddRef( IDropTarget
*iface
)
2219 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2221 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2223 return IShellFolder_AddRef((IShellFolder
*)This
);
2226 static ULONG WINAPI
ISVDropTarget_Release( IDropTarget
*iface
)
2228 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2230 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2232 return IShellFolder_Release((IShellFolder
*)This
);
2235 /******************************************************************************
2236 * drag_notify_subitem [Internal]
2238 * Figure out the shellfolder object, which is currently under the mouse cursor
2239 * and notify it via the IDropTarget interface.
2242 #define SCROLLAREAWIDTH 20
2244 static HRESULT
drag_notify_subitem(IShellViewImpl
*This
, DWORD grfKeyState
, POINTL pt
,
2247 LVHITTESTINFO htinfo
;
2253 /* Map from global to client coordinates and query the index of the listview-item, which is
2254 * currently under the mouse cursor. */
2257 htinfo
.flags
= LVHT_ONITEM
;
2258 ScreenToClient(This
->hWndList
, &htinfo
.pt
);
2259 lResult
= SendMessageW(This
->hWndList
, LVM_HITTEST
, 0, (LPARAM
)&htinfo
);
2261 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2262 GetClientRect(This
->hWndList
, &clientRect
);
2263 if (htinfo
.pt
.x
== This
->ptLastMousePos
.x
&& htinfo
.pt
.y
== This
->ptLastMousePos
.y
&&
2264 (htinfo
.pt
.x
< SCROLLAREAWIDTH
|| htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
||
2265 htinfo
.pt
.y
< SCROLLAREAWIDTH
|| htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
))
2267 This
->cScrollDelay
= (This
->cScrollDelay
+ 1) % 5; /* DragOver is called every 50 ms */
2268 if (This
->cScrollDelay
== 0) { /* Mouse did hover another 250 ms over the scroll-area */
2269 if (htinfo
.pt
.x
< SCROLLAREAWIDTH
)
2270 SendMessageW(This
->hWndList
, WM_HSCROLL
, SB_LINEUP
, 0);
2271 if (htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
)
2272 SendMessageW(This
->hWndList
, WM_HSCROLL
, SB_LINEDOWN
, 0);
2273 if (htinfo
.pt
.y
< SCROLLAREAWIDTH
)
2274 SendMessageW(This
->hWndList
, WM_VSCROLL
, SB_LINEUP
, 0);
2275 if (htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
)
2276 SendMessageW(This
->hWndList
, WM_VSCROLL
, SB_LINEDOWN
, 0);
2279 This
->cScrollDelay
= 0; /* Reset, if the cursor is not over the listview's scroll-area */
2281 This
->ptLastMousePos
= htinfo
.pt
;
2283 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2284 if (This
->pCurDropTarget
&& lResult
== This
->iDragOverItem
)
2285 return IDropTarget_DragOver(This
->pCurDropTarget
, grfKeyState
, pt
, pdwEffect
);
2287 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2288 if (This
->pCurDropTarget
) {
2289 IDropTarget_DragLeave(This
->pCurDropTarget
);
2290 IDropTarget_Release(This
->pCurDropTarget
);
2291 This
->pCurDropTarget
= NULL
;
2294 This
->iDragOverItem
= lResult
;
2295 if (lResult
== -1) {
2296 /* We are not above one of the listview's subitems. Bind to the parent folder's
2297 * DropTarget interface. */
2298 hr
= IShellFolder_QueryInterface(This
->pSFParent
, &IID_IDropTarget
,
2299 (LPVOID
*)&This
->pCurDropTarget
);
2301 /* Query the relative PIDL of the shellfolder object represented by the currently
2302 * dragged over listview-item ... */
2303 lvItem
.mask
= LVIF_PARAM
;
2304 lvItem
.iItem
= lResult
;
2305 lvItem
.iSubItem
= 0;
2306 SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
2308 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2309 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWndList
, 1,
2310 (LPCITEMIDLIST
*)&lvItem
.lParam
, &IID_IDropTarget
, NULL
, (LPVOID
*)&This
->pCurDropTarget
);
2313 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2317 /* Notify the item just entered via DragEnter. */
2318 return IDropTarget_DragEnter(This
->pCurDropTarget
, This
->pCurDataObject
, grfKeyState
, pt
, pdwEffect
);
2321 static HRESULT WINAPI
ISVDropTarget_DragEnter(IDropTarget
*iface
, IDataObject
*pDataObject
,
2322 DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2324 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2326 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2327 This
->pCurDataObject
= pDataObject
;
2328 IDataObject_AddRef(pDataObject
);
2330 return drag_notify_subitem(This
, grfKeyState
, pt
, pdwEffect
);
2333 static HRESULT WINAPI
ISVDropTarget_DragOver(IDropTarget
*iface
, DWORD grfKeyState
, POINTL pt
,
2336 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2337 return drag_notify_subitem(This
, grfKeyState
, pt
, pdwEffect
);
2340 static HRESULT WINAPI
ISVDropTarget_DragLeave(IDropTarget
*iface
) {
2341 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2343 if (This
->pCurDropTarget
)
2345 IDropTarget_DragLeave(This
->pCurDropTarget
);
2346 IDropTarget_Release(This
->pCurDropTarget
);
2347 This
->pCurDropTarget
= NULL
;
2349 IDataObject_Release(This
->pCurDataObject
);
2350 This
->pCurDataObject
= NULL
;
2351 This
->iDragOverItem
= 0;
2356 static HRESULT WINAPI
ISVDropTarget_Drop(IDropTarget
*iface
, IDataObject
* pDataObject
,
2357 DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2359 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2361 if (This
->pCurDropTarget
)
2363 IDropTarget_Drop(This
->pCurDropTarget
, pDataObject
, grfKeyState
, pt
, pdwEffect
);
2364 IDropTarget_Release(This
->pCurDropTarget
);
2365 This
->pCurDropTarget
= NULL
;
2368 IDataObject_Release(This
->pCurDataObject
);
2369 This
->pCurDataObject
= NULL
;
2370 This
->iDragOverItem
= 0;
2375 static const IDropTargetVtbl dtvt
=
2377 ISVDropTarget_QueryInterface
,
2378 ISVDropTarget_AddRef
,
2379 ISVDropTarget_Release
,
2380 ISVDropTarget_DragEnter
,
2381 ISVDropTarget_DragOver
,
2382 ISVDropTarget_DragLeave
,
2386 /**********************************************************
2387 * ISVDropSource implementation
2390 static HRESULT WINAPI
ISVDropSource_QueryInterface(
2395 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2397 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2399 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2402 static ULONG WINAPI
ISVDropSource_AddRef( IDropSource
*iface
)
2404 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2406 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2408 return IShellFolder_AddRef((IShellFolder
*)This
);
2411 static ULONG WINAPI
ISVDropSource_Release( IDropSource
*iface
)
2413 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2415 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2417 return IShellFolder_Release((IShellFolder
*)This
);
2419 static HRESULT WINAPI
ISVDropSource_QueryContinueDrag(
2421 BOOL fEscapePressed
,
2424 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2425 TRACE("(%p)\n",This
);
2428 return DRAGDROP_S_CANCEL
;
2429 else if (!(grfKeyState
& MK_LBUTTON
) && !(grfKeyState
& MK_RBUTTON
))
2430 return DRAGDROP_S_DROP
;
2435 static HRESULT WINAPI
ISVDropSource_GiveFeedback(
2439 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2440 TRACE("(%p)\n",This
);
2442 return DRAGDROP_S_USEDEFAULTCURSORS
;
2445 static const IDropSourceVtbl dsvt
=
2447 ISVDropSource_QueryInterface
,
2448 ISVDropSource_AddRef
,
2449 ISVDropSource_Release
,
2450 ISVDropSource_QueryContinueDrag
,
2451 ISVDropSource_GiveFeedback
2453 /**********************************************************
2454 * ISVViewObject implementation
2457 static HRESULT WINAPI
ISVViewObject_QueryInterface(
2462 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2464 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2466 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2469 static ULONG WINAPI
ISVViewObject_AddRef( IViewObject
*iface
)
2471 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2473 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2475 return IShellFolder_AddRef((IShellFolder
*)This
);
2478 static ULONG WINAPI
ISVViewObject_Release( IViewObject
*iface
)
2480 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2482 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2484 return IShellFolder_Release((IShellFolder
*)This
);
2487 static HRESULT WINAPI
ISVViewObject_Draw(
2492 DVTARGETDEVICE
* ptd
,
2495 LPCRECTL lprcBounds
,
2496 LPCRECTL lprcWBounds
,
2497 BOOL (CALLBACK
*pfnContinue
)(ULONG_PTR dwContinue
),
2498 ULONG_PTR dwContinue
)
2501 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2503 FIXME("Stub: This=%p\n",This
);
2507 static HRESULT WINAPI
ISVViewObject_GetColorSet(
2512 DVTARGETDEVICE
* ptd
,
2513 HDC hicTargetDevice
,
2514 LOGPALETTE
** ppColorSet
)
2517 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2519 FIXME("Stub: This=%p\n",This
);
2523 static HRESULT WINAPI
ISVViewObject_Freeze(
2531 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2533 FIXME("Stub: This=%p\n",This
);
2537 static HRESULT WINAPI
ISVViewObject_Unfreeze(
2542 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2544 FIXME("Stub: This=%p\n",This
);
2548 static HRESULT WINAPI
ISVViewObject_SetAdvise(
2552 IAdviseSink
* pAdvSink
)
2555 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2557 FIXME("partial stub: %p %08x %08x %p\n",
2558 This
, aspects
, advf
, pAdvSink
);
2560 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2561 This
->pAdvSink
= pAdvSink
;
2562 This
->dwAspects
= aspects
;
2563 This
->dwAdvf
= advf
;
2568 static HRESULT WINAPI
ISVViewObject_GetAdvise(
2572 IAdviseSink
** ppAdvSink
)
2575 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2577 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2578 This
, pAspects
, pAdvf
, ppAdvSink
);
2582 IAdviseSink_AddRef( This
->pAdvSink
);
2583 *ppAdvSink
= This
->pAdvSink
;
2586 *pAspects
= This
->dwAspects
;
2588 *pAdvf
= This
->dwAdvf
;
2594 static const IViewObjectVtbl vovt
=
2596 ISVViewObject_QueryInterface
,
2597 ISVViewObject_AddRef
,
2598 ISVViewObject_Release
,
2600 ISVViewObject_GetColorSet
,
2601 ISVViewObject_Freeze
,
2602 ISVViewObject_Unfreeze
,
2603 ISVViewObject_SetAdvise
,
2604 ISVViewObject_GetAdvise