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
);
71 static const WCHAR SV_CLASS_NAME
[] = {'S','H','E','L','L','D','L','L','_','D','e','f','V','i','e','w',0};
77 }LISTVIEW_SORT_INFO
, *LPLISTVIEW_SORT_INFO
;
81 const IShellViewVtbl
* lpVtbl
;
83 const IOleCommandTargetVtbl
* lpvtblOleCommandTarget
;
84 const IDropTargetVtbl
* lpvtblDropTarget
;
85 const IDropSourceVtbl
* lpvtblDropSource
;
86 const IViewObjectVtbl
* lpvtblViewObject
;
87 IShellFolder
* pSFParent
;
88 IShellFolder2
* pSF2Parent
;
89 IShellBrowser
* pShellBrowser
;
90 ICommDlgBrowser
* pCommDlgBrowser
;
91 HWND hWnd
; /* SHELLDLL_DefView */
92 HWND hWndList
; /* ListView control */
94 FOLDERSETTINGS FolderSettings
;
99 LISTVIEW_SORT_INFO ListViewSortInfo
;
100 ULONG hNotify
; /* change notification handle */
104 IAdviseSink
*pAdvSink
;
105 IDropTarget
* pCurDropTarget
; /* The sub-item, which is currently dragged over */
106 IDataObject
* pCurDataObject
; /* The dragged data-object */
107 LONG iDragOverItem
; /* Dragged over item's index, iff pCurDropTarget != NULL */
108 UINT cScrollDelay
; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
109 POINT ptLastMousePos
; /* Mouse position at last DragOver call */
112 static const IShellViewVtbl svvt
;
113 static const IOleCommandTargetVtbl ctvt
;
114 static const IDropTargetVtbl dtvt
;
115 static const IDropSourceVtbl dsvt
;
116 static const IViewObjectVtbl vovt
;
119 static inline IShellViewImpl
*impl_from_IOleCommandTarget( IOleCommandTarget
*iface
)
121 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblOleCommandTarget
));
124 static inline IShellViewImpl
*impl_from_IDropTarget( IDropTarget
*iface
)
126 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblDropTarget
));
129 static inline IShellViewImpl
*impl_from_IDropSource( IDropSource
*iface
)
131 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblDropSource
));
134 static inline IShellViewImpl
*impl_from_IViewObject( IViewObject
*iface
)
136 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblViewObject
));
139 /* ListView Header ID's */
140 #define LISTVIEW_COLUMN_NAME 0
141 #define LISTVIEW_COLUMN_SIZE 1
142 #define LISTVIEW_COLUMN_TYPE 2
143 #define LISTVIEW_COLUMN_TIME 3
144 #define LISTVIEW_COLUMN_ATTRIB 4
147 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
148 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
149 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
151 #define ID_LISTVIEW 1
153 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
156 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
157 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
158 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
161 Items merged into the toolbar and the filemenu
170 } MYTOOLINFO
, *LPMYTOOLINFO
;
172 static const MYTOOLINFO Tools
[] =
174 { FCIDM_SHVIEW_BIGICON
, 0, 0, IDS_VIEW_LARGE
, TBSTATE_ENABLED
, BTNS_BUTTON
},
175 { FCIDM_SHVIEW_SMALLICON
, 0, 0, IDS_VIEW_SMALL
, TBSTATE_ENABLED
, BTNS_BUTTON
},
176 { FCIDM_SHVIEW_LISTVIEW
, 0, 0, IDS_VIEW_LIST
, TBSTATE_ENABLED
, BTNS_BUTTON
},
177 { FCIDM_SHVIEW_REPORTVIEW
, 0, 0, IDS_VIEW_DETAILS
, TBSTATE_ENABLED
, BTNS_BUTTON
},
181 typedef void (CALLBACK
*PFNSHGETSETTINGSPROC
)(LPSHELLFLAGSTATE lpsfs
, DWORD dwMask
);
183 /**********************************************************
184 * IShellView_Constructor
186 IShellView
* IShellView_Constructor( IShellFolder
* pFolder
)
187 { IShellViewImpl
* sv
;
188 sv
=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IShellViewImpl
));
191 sv
->lpvtblOleCommandTarget
=&ctvt
;
192 sv
->lpvtblDropTarget
=&dtvt
;
193 sv
->lpvtblDropSource
=&dsvt
;
194 sv
->lpvtblViewObject
=&vovt
;
196 sv
->pSFParent
= pFolder
;
197 if(pFolder
) IShellFolder_AddRef(pFolder
);
198 IShellFolder_QueryInterface(sv
->pSFParent
, &IID_IShellFolder2
, (LPVOID
*)&sv
->pSF2Parent
);
200 sv
->pCurDropTarget
= NULL
;
201 sv
->pCurDataObject
= NULL
;
202 sv
->iDragOverItem
= 0;
203 sv
->cScrollDelay
= 0;
204 sv
->ptLastMousePos
.x
= 0;
205 sv
->ptLastMousePos
.y
= 0;
207 TRACE("(%p)->(%p)\n",sv
, pFolder
);
208 return (IShellView
*) sv
;
211 /**********************************************************
213 * ##### helperfunctions for communication with ICommDlgBrowser #####
215 static BOOL
IsInCommDlg(IShellViewImpl
* This
)
216 { return(This
->pCommDlgBrowser
!= NULL
);
219 static HRESULT
IncludeObject(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
223 if ( IsInCommDlg(This
) )
225 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl
);
226 ret
= ICommDlgBrowser_IncludeObject(This
->pCommDlgBrowser
, (IShellView
*)This
, pidl
);
227 TRACE("--0x%08x\n", ret
);
232 static HRESULT
OnDefaultCommand(IShellViewImpl
* This
)
234 HRESULT ret
= S_FALSE
;
236 if (IsInCommDlg(This
))
238 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
239 ret
= ICommDlgBrowser_OnDefaultCommand(This
->pCommDlgBrowser
, (IShellView
*)This
);
240 TRACE("-- returns %08x\n", ret
);
245 static HRESULT
OnStateChange(IShellViewImpl
* This
, UINT uFlags
)
247 HRESULT ret
= S_FALSE
;
249 if (IsInCommDlg(This
))
251 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags
);
252 ret
= ICommDlgBrowser_OnStateChange(This
->pCommDlgBrowser
, (IShellView
*)This
, uFlags
);
257 /**********************************************************
258 * set the toolbar of the filedialog buttons
260 * - activates the buttons from the shellbrowser according to
263 static void CheckToolbar(IShellViewImpl
* This
)
269 if (IsInCommDlg(This
))
271 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_CHECKBUTTON
,
272 FCIDM_TB_SMALLICON
, (This
->FolderSettings
.ViewMode
==FVM_LIST
)? TRUE
: FALSE
, &result
);
273 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_CHECKBUTTON
,
274 FCIDM_TB_REPORTVIEW
, (This
->FolderSettings
.ViewMode
==FVM_DETAILS
)? TRUE
: FALSE
, &result
);
275 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_ENABLEBUTTON
,
276 FCIDM_TB_SMALLICON
, TRUE
, &result
);
277 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_ENABLEBUTTON
,
278 FCIDM_TB_REPORTVIEW
, TRUE
, &result
);
282 /**********************************************************
284 * ##### helperfunctions for initializing the view #####
286 /**********************************************************
287 * change the style of the listview control
289 static void SetStyle(IShellViewImpl
* This
, DWORD dwAdd
, DWORD dwRemove
)
293 TRACE("(%p)\n", This
);
295 tmpstyle
= GetWindowLongW(This
->hWndList
, GWL_STYLE
);
296 SetWindowLongW(This
->hWndList
, GWL_STYLE
, dwAdd
| (tmpstyle
& ~dwRemove
));
299 /**********************************************************
300 * ShellView_CreateList()
302 * - creates the list view window
304 static BOOL
ShellView_CreateList (IShellViewImpl
* This
)
305 { DWORD dwStyle
, dwExStyle
;
309 dwStyle
= WS_TABSTOP
| WS_VISIBLE
| WS_CHILDWINDOW
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
310 LVS_SHAREIMAGELISTS
| LVS_EDITLABELS
| LVS_ALIGNLEFT
| LVS_AUTOARRANGE
;
311 dwExStyle
= WS_EX_CLIENTEDGE
;
313 switch (This
->FolderSettings
.ViewMode
)
315 case FVM_ICON
: dwStyle
|= LVS_ICON
; break;
316 case FVM_DETAILS
: dwStyle
|= LVS_REPORT
; break;
317 case FVM_SMALLICON
: dwStyle
|= LVS_SMALLICON
; break;
318 case FVM_LIST
: dwStyle
|= LVS_LIST
; break;
319 default: dwStyle
|= LVS_LIST
; break;
322 if (This
->FolderSettings
.fFlags
& FWF_AUTOARRANGE
) dwStyle
|= LVS_AUTOARRANGE
;
323 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
)
324 This
->FolderSettings
.fFlags
|= FWF_NOCLIENTEDGE
| FWF_NOSCROLL
;
325 if (This
->FolderSettings
.fFlags
& FWF_SINGLESEL
) dwStyle
|= LVS_SINGLESEL
;
326 if (This
->FolderSettings
.fFlags
& FWF_NOCLIENTEDGE
)
327 dwExStyle
&= ~WS_EX_CLIENTEDGE
;
329 This
->hWndList
=CreateWindowExW( dwExStyle
,
342 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
343 This
->ListViewSortInfo
.nHeaderID
= -1;
344 This
->ListViewSortInfo
.nLastHeaderID
= -1;
346 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
) {
348 * FIXME: look at the registry value
349 * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
350 * and activate drop shadows if necessary
353 SendMessageW(This
->hWndList
, LVM_SETTEXTBKCOLOR
, 0, CLR_NONE
);
355 SendMessageW(This
->hWndList
, LVM_SETTEXTBKCOLOR
, 0, GetSysColor(COLOR_DESKTOP
));
357 SendMessageW(This
->hWndList
, LVM_SETTEXTCOLOR
, 0, RGB(255,255,255));
360 /* UpdateShellSettings(); */
364 /**********************************************************
365 * ShellView_InitList()
367 * - adds all needed columns to the shellview
369 static BOOL
ShellView_InitList(IShellViewImpl
* This
)
378 SendMessageW(This
->hWndList
, LVM_DELETEALLITEMS
, 0, 0);
380 lvColumn
.mask
= LVCF_FMT
| LVCF_WIDTH
| LVCF_TEXT
;
381 lvColumn
.pszText
= szTemp
;
383 if (This
->pSF2Parent
)
387 if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This
->pSF2Parent
, NULL
, i
, &sd
)))
389 lvColumn
.fmt
= sd
.fmt
;
390 lvColumn
.cx
= sd
.cxChar
*8; /* chars->pixel */
391 StrRetToStrNW( szTemp
, 50, &sd
.str
, NULL
);
392 SendMessageW(This
->hWndList
, LVM_INSERTCOLUMNW
, i
, (LPARAM
) &lvColumn
);
400 SendMessageW(This
->hWndList
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)ShellSmallIconList
);
401 SendMessageW(This
->hWndList
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)ShellBigIconList
);
405 /**********************************************************
406 * ShellView_CompareItems()
409 * internal, CALLBACK for DSA_Sort
411 static INT CALLBACK
ShellView_CompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
)
414 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1
, lParam2
, (LPVOID
) lpData
);
416 if(!lpData
) return 0;
418 ret
= (SHORT
) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER
)lpData
, 0, (LPITEMIDLIST
)lParam1
, (LPITEMIDLIST
)lParam2
));
419 TRACE("ret=%i\n",ret
);
423 /*************************************************************************
424 * ShellView_ListViewCompareItems
426 * Compare Function for the Listview (FileOpen Dialog)
429 * lParam1 [I] the first ItemIdList to compare with
430 * lParam2 [I] the second ItemIdList to compare with
431 * lpData [I] The column ID for the header Ctrl to process
434 * A negative value if the first item should precede the second,
435 * a positive value if the first item should follow the second,
436 * or zero if the two items are equivalent
439 * FIXME: function does what ShellView_CompareItems is supposed to do.
440 * unify it and figure out how to use the undocumented first parameter
441 * of IShellFolder_CompareIDs to do the job this function does and
442 * move this code to IShellFolder.
443 * make LISTVIEW_SORT_INFO obsolete
444 * the way this function works is only usable if we had only
445 * filesystemfolders (25/10/99 jsch)
447 static INT CALLBACK
ShellView_ListViewCompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
)
451 char strName1
[MAX_PATH
], strName2
[MAX_PATH
];
452 BOOL bIsFolder1
, bIsFolder2
,bIsBothFolder
;
453 LPITEMIDLIST pItemIdList1
= (LPITEMIDLIST
) lParam1
;
454 LPITEMIDLIST pItemIdList2
= (LPITEMIDLIST
) lParam2
;
455 LISTVIEW_SORT_INFO
*pSortInfo
= (LPLISTVIEW_SORT_INFO
) lpData
;
458 bIsFolder1
= _ILIsFolder(pItemIdList1
);
459 bIsFolder2
= _ILIsFolder(pItemIdList2
);
460 bIsBothFolder
= bIsFolder1
&& bIsFolder2
;
462 /* When sorting between a File and a Folder, the Folder gets sorted first */
463 if( (bIsFolder1
|| bIsFolder2
) && !bIsBothFolder
)
465 nDiff
= bIsFolder1
? -1 : 1;
469 /* Sort by Time: Folders or Files can be sorted */
471 if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_TIME
)
473 _ILGetFileDateTime(pItemIdList1
, &fd1
);
474 _ILGetFileDateTime(pItemIdList2
, &fd2
);
475 nDiff
= CompareFileTime(&fd2
, &fd1
);
477 /* Sort by Attribute: Folder or Files can be sorted */
478 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_ATTRIB
)
480 _ILGetFileAttributes(pItemIdList1
, strName1
, MAX_PATH
);
481 _ILGetFileAttributes(pItemIdList2
, strName2
, MAX_PATH
);
482 nDiff
= lstrcmpiA(strName1
, strName2
);
484 /* Sort by FileName: Folder or Files can be sorted */
485 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_NAME
|| bIsBothFolder
)
488 _ILSimpleGetText(pItemIdList1
, strName1
, MAX_PATH
);
489 _ILSimpleGetText(pItemIdList2
, strName2
, MAX_PATH
);
490 nDiff
= lstrcmpiA(strName1
, strName2
);
492 /* Sort by File Size, Only valid for Files */
493 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_SIZE
)
495 nDiff
= (INT
)(_ILGetFileSize(pItemIdList1
, NULL
, 0) - _ILGetFileSize(pItemIdList2
, NULL
, 0));
497 /* Sort by File Type, Only valid for Files */
498 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_TYPE
)
501 _ILGetFileType(pItemIdList1
, strName1
, MAX_PATH
);
502 _ILGetFileType(pItemIdList2
, strName2
, MAX_PATH
);
503 nDiff
= lstrcmpiA(strName1
, strName2
);
506 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
510 _ILSimpleGetText(pItemIdList1
, strName1
, MAX_PATH
);
511 _ILSimpleGetText(pItemIdList2
, strName2
, MAX_PATH
);
512 nDiff
= lstrcmpiA(strName1
, strName2
);
515 if(!pSortInfo
->bIsAscending
)
524 /**********************************************************
525 * LV_FindItemByPidl()
527 static int LV_FindItemByPidl(
528 IShellViewImpl
* This
,
533 lvItem
.mask
= LVIF_PARAM
;
534 for(lvItem
.iItem
= 0;
535 SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
538 LPITEMIDLIST currentpidl
= (LPITEMIDLIST
) lvItem
.lParam
;
539 HRESULT hr
= IShellFolder_CompareIDs(This
->pSFParent
, 0, pidl
, currentpidl
);
540 if(SUCCEEDED(hr
) && !HRESULT_CODE(hr
))
548 /**********************************************************
551 static BOOLEAN
LV_AddItem(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
555 TRACE("(%p)(pidl=%p)\n", This
, pidl
);
557 lvItem
.mask
= LVIF_TEXT
| LVIF_IMAGE
| LVIF_PARAM
; /*set the mask*/
558 lvItem
.iItem
= ListView_GetItemCount(This
->hWndList
); /*add the item to the end of the list*/
560 lvItem
.lParam
= (LPARAM
) ILClone(ILFindLastID(pidl
)); /*set the item's data*/
561 lvItem
.pszText
= LPSTR_TEXTCALLBACKW
; /*get text on a callback basis*/
562 lvItem
.iImage
= I_IMAGECALLBACK
; /*get the image on a callback basis*/
563 return (-1==ListView_InsertItemW(This
->hWndList
, &lvItem
))? FALSE
: TRUE
;
566 /**********************************************************
569 static BOOLEAN
LV_DeleteItem(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
573 TRACE("(%p)(pidl=%p)\n", This
, pidl
);
575 nIndex
= LV_FindItemByPidl(This
, ILFindLastID(pidl
));
576 return (-1==ListView_DeleteItem(This
->hWndList
, nIndex
))? FALSE
: TRUE
;
579 /**********************************************************
582 static BOOLEAN
LV_RenameItem(IShellViewImpl
* This
, LPCITEMIDLIST pidlOld
, LPCITEMIDLIST pidlNew
)
587 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This
, pidlOld
, pidlNew
);
589 nItem
= LV_FindItemByPidl(This
, ILFindLastID(pidlOld
));
592 lvItem
.mask
= LVIF_PARAM
; /* only the pidl */
593 lvItem
.iItem
= nItem
;
594 SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
596 SHFree((LPITEMIDLIST
)lvItem
.lParam
);
597 lvItem
.mask
= LVIF_PARAM
;
598 lvItem
.iItem
= nItem
;
599 lvItem
.lParam
= (LPARAM
) ILClone(ILFindLastID(pidlNew
)); /* set the item's data */
600 SendMessageW(This
->hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
601 SendMessageW(This
->hWndList
, LVM_UPDATE
, nItem
, 0);
602 return TRUE
; /* FIXME: better handling */
606 /**********************************************************
607 * ShellView_FillList()
609 * - gets the objectlist from the shellfolder
611 * - fills the list into the view
614 static INT CALLBACK
fill_list( LPVOID ptr
, LPVOID arg
)
616 LPITEMIDLIST pidl
= ptr
;
617 IShellViewImpl
*This
= arg
;
618 /* in a commdlg This works as a filemask*/
619 if ( IncludeObject(This
, pidl
)==S_OK
) LV_AddItem(This
, pidl
);
624 static HRESULT
ShellView_FillList(IShellViewImpl
* This
)
626 LPENUMIDLIST pEnumIDList
;
634 /* get the itemlist from the shfolder*/
635 hRes
= IShellFolder_EnumObjects(This
->pSFParent
,This
->hWnd
, SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
, &pEnumIDList
);
643 /* create a pointer array */
644 hdpa
= DPA_Create(16);
647 return(E_OUTOFMEMORY
);
650 /* copy the items into the array*/
651 while((S_OK
== IEnumIDList_Next(pEnumIDList
,1, &pidl
, &dwFetched
)) && dwFetched
)
653 if (DPA_InsertPtr(hdpa
, 0x7fff, pidl
) == -1)
660 DPA_Sort(hdpa
, ShellView_CompareItems
, (LPARAM
)This
->pSFParent
);
662 /*turn the listview's redrawing off*/
663 SendMessageA(This
->hWndList
, WM_SETREDRAW
, FALSE
, 0);
665 DPA_DestroyCallback( hdpa
, fill_list
, This
);
667 /*turn the listview's redrawing back on and force it to draw*/
668 SendMessageA(This
->hWndList
, WM_SETREDRAW
, TRUE
, 0);
670 IEnumIDList_Release(pEnumIDList
); /* destroy the list*/
675 /**********************************************************
676 * ShellView_OnCreate()
678 static LRESULT
ShellView_OnCreate(IShellViewImpl
* This
)
681 SHChangeNotifyEntry ntreg
;
682 IPersistFolder2
* ppf2
= NULL
;
686 if(ShellView_CreateList(This
))
688 if(ShellView_InitList(This
))
690 ShellView_FillList(This
);
694 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown
*)&This
->lpVtbl
, &IID_IDropTarget
, (LPVOID
*)&pdt
)))
696 RegisterDragDrop(This
->hWnd
, pdt
);
697 IDropTarget_Release(pdt
);
700 /* register for receiving notifications */
701 IShellFolder_QueryInterface(This
->pSFParent
, &IID_IPersistFolder2
, (LPVOID
*)&ppf2
);
704 IPersistFolder2_GetCurFolder(ppf2
, (LPITEMIDLIST
*)&ntreg
.pidl
);
705 ntreg
.fRecursive
= TRUE
;
706 This
->hNotify
= SHChangeNotifyRegister(This
->hWnd
, SHCNF_IDLIST
, SHCNE_ALLEVENTS
, SHV_CHANGE_NOTIFY
, 1, &ntreg
);
707 SHFree((LPITEMIDLIST
)ntreg
.pidl
);
708 IPersistFolder2_Release(ppf2
);
711 This
->hAccel
= LoadAcceleratorsA(shell32_hInstance
, "shv_accel");
716 /**********************************************************
717 * #### Handling of the menus ####
720 /**********************************************************
721 * ShellView_BuildFileMenu()
723 static HMENU
ShellView_BuildFileMenu(IShellViewImpl
* This
)
724 { WCHAR szText
[MAX_PATH
];
729 TRACE("(%p)\n",This
);
731 hSubMenu
= CreatePopupMenu();
733 { /*get the number of items in our global array*/
734 for(nTools
= 0; Tools
[nTools
].idCommand
!= -1; nTools
++){}
736 /*add the menu items*/
737 for(i
= 0; i
< nTools
; i
++)
739 LoadStringW(shell32_hInstance
, Tools
[i
].idMenuString
, szText
, MAX_PATH
);
741 ZeroMemory(&mii
, sizeof(mii
));
742 mii
.cbSize
= sizeof(mii
);
743 mii
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
745 if(BTNS_SEP
!= Tools
[i
].bStyle
) /* no separator*/
747 mii
.fType
= MFT_STRING
;
748 mii
.fState
= MFS_ENABLED
;
749 mii
.dwTypeData
= szText
;
750 mii
.wID
= Tools
[i
].idCommand
;
754 mii
.fType
= MFT_SEPARATOR
;
756 /* tack This item onto the end of the menu */
757 InsertMenuItemW(hSubMenu
, (UINT
)-1, TRUE
, &mii
);
760 TRACE("-- return (menu=%p)\n",hSubMenu
);
763 /**********************************************************
764 * ShellView_MergeFileMenu()
766 static void ShellView_MergeFileMenu(IShellViewImpl
* This
, HMENU hSubMenu
)
767 { TRACE("(%p)->(submenu=%p) stub\n",This
,hSubMenu
);
770 { /*insert This item at the beginning of the menu */
773 mii
.cbSize
= sizeof(mii
);
774 mii
.fMask
= MIIM_ID
| MIIM_TYPE
;
776 mii
.fType
= MFT_SEPARATOR
;
777 InsertMenuItemA(hSubMenu
, 0, TRUE
, &mii
);
779 mii
.cbSize
= sizeof(mii
);
780 mii
.fMask
= MIIM_ID
| MIIM_TYPE
| MIIM_STATE
;
781 mii
.dwTypeData
= (LPSTR
)"dummy45";
782 mii
.fState
= MFS_ENABLED
;
783 mii
.wID
= IDM_MYFILEITEM
;
784 mii
.fType
= MFT_STRING
;
785 InsertMenuItemA(hSubMenu
, 0, TRUE
, &mii
);
790 /**********************************************************
791 * ShellView_MergeViewMenu()
794 static void ShellView_MergeViewMenu(IShellViewImpl
* This
, HMENU hSubMenu
)
796 TRACE("(%p)->(submenu=%p)\n",This
,hSubMenu
);
799 { /*add a separator at the correct position in the menu*/
801 static char view
[] = "View";
803 ZeroMemory(&mii
, sizeof(mii
));
804 mii
.cbSize
= sizeof(mii
);
805 mii
.fMask
= MIIM_ID
| MIIM_TYPE
;
807 mii
.fType
= MFT_SEPARATOR
;
808 InsertMenuItemA(hSubMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
, FALSE
, &mii
);
810 mii
.cbSize
= sizeof(mii
);
811 mii
.fMask
= MIIM_SUBMENU
| MIIM_TYPE
| MIIM_DATA
;
812 mii
.fType
= MFT_STRING
;
813 mii
.dwTypeData
= view
;
814 mii
.hSubMenu
= LoadMenuA(shell32_hInstance
, "MENU_001");
815 InsertMenuItemA(hSubMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
, FALSE
, &mii
);
819 /**********************************************************
820 * ShellView_GetSelections()
822 * - fills the this->apidl list with the selected objects
825 * number of selected items
827 static UINT
ShellView_GetSelections(IShellViewImpl
* This
)
834 This
->cidl
= ListView_GetSelectedCount(This
->hWndList
);
835 This
->apidl
= (LPITEMIDLIST
*)SHAlloc(This
->cidl
* sizeof(LPITEMIDLIST
));
837 TRACE("selected=%i\n", This
->cidl
);
841 TRACE("-- Items selected =%u\n", This
->cidl
);
843 lvItem
.mask
= LVIF_STATE
| LVIF_PARAM
;
844 lvItem
.stateMask
= LVIS_SELECTED
;
848 while(ListView_GetItemW(This
->hWndList
, &lvItem
) && (i
< This
->cidl
))
850 if(lvItem
.state
& LVIS_SELECTED
)
852 This
->apidl
[i
] = (LPITEMIDLIST
)lvItem
.lParam
;
854 TRACE("-- selected Item found\n");
863 /**********************************************************
864 * ShellView_OpenSelectedItems()
866 static HRESULT
ShellView_OpenSelectedItems(IShellViewImpl
* This
)
868 static UINT CF_IDLIST
= 0;
870 IDataObject
* selection
;
874 LPCITEMIDLIST parent_pidl
;
875 WCHAR parent_path
[MAX_PATH
];
876 LPCWSTR parent_dir
= NULL
;
880 if (0 == ShellView_GetSelections(This
))
884 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
,
885 (LPCITEMIDLIST
*)This
->apidl
, &IID_IDataObject
,
886 0, (LPVOID
*)&selection
);
892 CF_IDLIST
= RegisterClipboardFormatA(CFSTR_SHELLIDLIST
);
894 fetc
.cfFormat
= CF_IDLIST
;
896 fetc
.dwAspect
= DVASPECT_CONTENT
;
898 fetc
.tymed
= TYMED_HGLOBAL
;
900 hr
= IDataObject_QueryGetData(selection
, &fetc
);
904 hr
= IDataObject_GetData(selection
, &fetc
, &stgm
);
908 pIDList
= GlobalLock(stgm
.u
.hGlobal
);
910 parent_pidl
= (LPCITEMIDLIST
) ((LPBYTE
)pIDList
+pIDList
->aoffset
[0]);
911 hr
= IShellFolder_GetAttributesOf(This
->pSFParent
, 1, &parent_pidl
, &attribs
);
912 if (SUCCEEDED(hr
) && (attribs
& SFGAO_FILESYSTEM
) &&
913 SHGetPathFromIDListW(parent_pidl
, parent_path
))
915 parent_dir
= parent_path
;
918 for (i
= pIDList
->cidl
; i
> 0; --i
)
922 pidl
= (LPCITEMIDLIST
)((LPBYTE
)pIDList
+pIDList
->aoffset
[i
]);
924 attribs
= SFGAO_FOLDER
;
925 hr
= IShellFolder_GetAttributesOf(This
->pSFParent
, 1, &pidl
, &attribs
);
927 if (SUCCEEDED(hr
) && ! (attribs
& SFGAO_FOLDER
))
929 SHELLEXECUTEINFOW shexinfo
;
931 shexinfo
.cbSize
= sizeof(SHELLEXECUTEINFOW
);
932 shexinfo
.fMask
= SEE_MASK_INVOKEIDLIST
; /* SEE_MASK_IDLIST is also possible. */
933 shexinfo
.hwnd
= NULL
;
934 shexinfo
.lpVerb
= NULL
;
935 shexinfo
.lpFile
= NULL
;
936 shexinfo
.lpParameters
= NULL
;
937 shexinfo
.lpDirectory
= parent_dir
;
938 shexinfo
.nShow
= SW_NORMAL
;
939 shexinfo
.lpIDList
= ILCombine(parent_pidl
, pidl
);
941 ShellExecuteExW(&shexinfo
); /* Discard error/success info */
943 ILFree((LPITEMIDLIST
)shexinfo
.lpIDList
);
947 GlobalUnlock(stgm
.u
.hGlobal
);
948 ReleaseStgMedium(&stgm
);
950 IDataObject_Release(selection
);
955 /**********************************************************
956 * ShellView_DoContextMenu()
958 static void ShellView_DoContextMenu(IShellViewImpl
* This
, WORD x
, WORD y
, BOOL bDefault
)
962 BOOL fExplore
= FALSE
;
964 LPCONTEXTMENU pContextMenu
= NULL
;
965 IContextMenu2
*pCM
= NULL
;
966 CMINVOKECOMMANDINFO cmi
;
968 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This
, x
, y
, bDefault
);
970 /* look, what's selected and create a context menu object of it*/
971 if( ShellView_GetSelections(This
) )
973 IShellFolder_GetUIObjectOf( This
->pSFParent
, This
->hWndParent
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
,
974 (REFIID
)&IID_IContextMenu
, NULL
, (LPVOID
*)&pContextMenu
);
978 TRACE("-- pContextMenu\n");
979 hMenu
= CreatePopupMenu();
983 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
984 if(SUCCEEDED(IShellBrowser_GetControlWindow(This
->pShellBrowser
,FCW_TREE
, &hwndTree
)) && hwndTree
)
986 TRACE("-- explore mode\n");
990 /* build the flags depending on what we can do with the selected item */
991 wFlags
= CMF_NORMAL
| (This
->cidl
!= 1 ? 0 : CMF_CANRENAME
) | (fExplore
? CMF_EXPLORE
: 0);
993 /* let the ContextMenu merge its items in */
994 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu
, hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, wFlags
)))
996 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
)
997 SetMenuDefaultItem(hMenu
, FCIDM_SHVIEW_OPEN
, MF_BYCOMMAND
);
1001 TRACE("-- get menu default command\n");
1002 uCommand
= GetMenuDefaultItem(hMenu
, FALSE
, GMDI_GOINTOPOPUPS
);
1006 TRACE("-- track popup\n");
1007 uCommand
= TrackPopupMenu( hMenu
,TPM_LEFTALIGN
| TPM_RETURNCMD
,x
,y
,0,This
->hWnd
,NULL
);
1012 TRACE("-- uCommand=%u\n", uCommand
);
1013 if (uCommand
==FCIDM_SHVIEW_OPEN
&& IsInCommDlg(This
))
1015 TRACE("-- dlg: OnDefaultCommand\n");
1016 if (OnDefaultCommand(This
) != S_OK
)
1018 ShellView_OpenSelectedItems(This
);
1023 TRACE("-- explore -- invoke command\n");
1024 ZeroMemory(&cmi
, sizeof(cmi
));
1025 cmi
.cbSize
= sizeof(cmi
);
1026 cmi
.hwnd
= This
->hWndParent
; /* this window has to answer CWM_GETISHELLBROWSER */
1027 cmi
.lpVerb
= (LPCSTR
)MAKEINTRESOURCEA(uCommand
);
1028 IContextMenu_InvokeCommand(pContextMenu
, &cmi
);
1035 IContextMenu_Release(pContextMenu
);
1038 else /* background context menu */
1040 hMenu
= CreatePopupMenu();
1042 pCM
= ISvBgCm_Constructor(This
->pSFParent
, FALSE
);
1043 IContextMenu2_QueryContextMenu(pCM
, hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, 0);
1045 uCommand
= TrackPopupMenu( hMenu
, TPM_LEFTALIGN
| TPM_RETURNCMD
,x
,y
,0,This
->hWnd
,NULL
);
1048 TRACE("-- (%p)->(uCommand=0x%08x )\n",This
, uCommand
);
1050 ZeroMemory(&cmi
, sizeof(cmi
));
1051 cmi
.cbSize
= sizeof(cmi
);
1052 cmi
.lpVerb
= (LPCSTR
)MAKEINTRESOURCEA(uCommand
);
1053 cmi
.hwnd
= This
->hWndParent
;
1054 IContextMenu2_InvokeCommand(pCM
, &cmi
);
1056 IContextMenu2_Release(pCM
);
1060 /**********************************************************
1061 * ##### message handling #####
1064 /**********************************************************
1065 * ShellView_OnSize()
1067 static LRESULT
ShellView_OnSize(IShellViewImpl
* This
, WORD wWidth
, WORD wHeight
)
1069 TRACE("%p width=%u height=%u\n",This
, wWidth
,wHeight
);
1071 /*resize the ListView to fit our window*/
1074 MoveWindow(This
->hWndList
, 0, 0, wWidth
, wHeight
, TRUE
);
1079 /**********************************************************
1080 * ShellView_OnDeactivate()
1085 static void ShellView_OnDeactivate(IShellViewImpl
* This
)
1089 if(This
->uState
!= SVUIA_DEACTIVATE
)
1093 IShellBrowser_SetMenuSB(This
->pShellBrowser
,0, 0, 0);
1094 IShellBrowser_RemoveMenusSB(This
->pShellBrowser
,This
->hMenu
);
1095 DestroyMenu(This
->hMenu
);
1099 This
->uState
= SVUIA_DEACTIVATE
;
1103 /**********************************************************
1104 * ShellView_OnActivate()
1106 static LRESULT
ShellView_OnActivate(IShellViewImpl
* This
, UINT uState
)
1107 { OLEMENUGROUPWIDTHS omw
= { {0, 0, 0, 0, 0, 0} };
1109 CHAR szText
[MAX_PATH
];
1111 TRACE("%p uState=%x\n",This
,uState
);
1113 /*don't do anything if the state isn't really changing */
1114 if(This
->uState
== uState
)
1119 ShellView_OnDeactivate(This
);
1121 /*only do This if we are active */
1122 if(uState
!= SVUIA_DEACTIVATE
)
1124 /*merge the menus */
1125 This
->hMenu
= CreateMenu();
1129 IShellBrowser_InsertMenusSB(This
->pShellBrowser
, This
->hMenu
, &omw
);
1130 TRACE("-- after fnInsertMenusSB\n");
1132 /*build the top level menu get the menu item's text*/
1133 strcpy(szText
,"dummy 31");
1135 ZeroMemory(&mii
, sizeof(mii
));
1136 mii
.cbSize
= sizeof(mii
);
1137 mii
.fMask
= MIIM_SUBMENU
| MIIM_TYPE
| MIIM_STATE
;
1138 mii
.fType
= MFT_STRING
;
1139 mii
.fState
= MFS_ENABLED
;
1140 mii
.dwTypeData
= szText
;
1141 mii
.hSubMenu
= ShellView_BuildFileMenu(This
);
1143 /*insert our menu into the menu bar*/
1146 InsertMenuItemA(This
->hMenu
, FCIDM_MENU_HELP
, FALSE
, &mii
);
1149 /*get the view menu so we can merge with it*/
1150 ZeroMemory(&mii
, sizeof(mii
));
1151 mii
.cbSize
= sizeof(mii
);
1152 mii
.fMask
= MIIM_SUBMENU
;
1154 if(GetMenuItemInfoA(This
->hMenu
, FCIDM_MENU_VIEW
, FALSE
, &mii
))
1156 ShellView_MergeViewMenu(This
, mii
.hSubMenu
);
1159 /*add the items that should only be added if we have the focus*/
1160 if(SVUIA_ACTIVATE_FOCUS
== uState
)
1162 /*get the file menu so we can merge with it */
1163 ZeroMemory(&mii
, sizeof(mii
));
1164 mii
.cbSize
= sizeof(mii
);
1165 mii
.fMask
= MIIM_SUBMENU
;
1167 if(GetMenuItemInfoA(This
->hMenu
, FCIDM_MENU_FILE
, FALSE
, &mii
))
1169 ShellView_MergeFileMenu(This
, mii
.hSubMenu
);
1172 TRACE("-- before fnSetMenuSB\n");
1173 IShellBrowser_SetMenuSB(This
->pShellBrowser
, This
->hMenu
, 0, This
->hWnd
);
1176 This
->uState
= uState
;
1181 /**********************************************************
1182 * ShellView_OnSetFocus()
1185 static LRESULT
ShellView_OnSetFocus(IShellViewImpl
* This
)
1189 /* Tell the browser one of our windows has received the focus. This
1190 should always be done before merging menus (OnActivate merges the
1191 menus) if one of our windows has the focus.*/
1193 IShellBrowser_OnViewWindowActive(This
->pShellBrowser
,(IShellView
*) This
);
1194 ShellView_OnActivate(This
, SVUIA_ACTIVATE_FOCUS
);
1196 /* Set the focus to the listview */
1197 SetFocus(This
->hWndList
);
1199 /* Notify the ICommDlgBrowser interface */
1200 OnStateChange(This
,CDBOSC_SETFOCUS
);
1205 /**********************************************************
1206 * ShellView_OnKillFocus()
1208 static LRESULT
ShellView_OnKillFocus(IShellViewImpl
* This
)
1210 TRACE("(%p) stub\n",This
);
1212 ShellView_OnActivate(This
, SVUIA_ACTIVATE_NOFOCUS
);
1213 /* Notify the ICommDlgBrowser */
1214 OnStateChange(This
,CDBOSC_KILLFOCUS
);
1219 /**********************************************************
1220 * ShellView_OnCommand()
1223 * the CmdID's are the ones from the context menu
1225 static LRESULT
ShellView_OnCommand(IShellViewImpl
* This
,DWORD dwCmdID
, DWORD dwCmd
, HWND hwndCmd
)
1227 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",This
, dwCmdID
, dwCmd
, hwndCmd
);
1231 case FCIDM_SHVIEW_SMALLICON
:
1232 This
->FolderSettings
.ViewMode
= FVM_SMALLICON
;
1233 SetStyle (This
, LVS_SMALLICON
, LVS_TYPEMASK
);
1237 case FCIDM_SHVIEW_BIGICON
:
1238 This
->FolderSettings
.ViewMode
= FVM_ICON
;
1239 SetStyle (This
, LVS_ICON
, LVS_TYPEMASK
);
1243 case FCIDM_SHVIEW_LISTVIEW
:
1244 This
->FolderSettings
.ViewMode
= FVM_LIST
;
1245 SetStyle (This
, LVS_LIST
, LVS_TYPEMASK
);
1249 case FCIDM_SHVIEW_REPORTVIEW
:
1250 This
->FolderSettings
.ViewMode
= FVM_DETAILS
;
1251 SetStyle (This
, LVS_REPORT
, LVS_TYPEMASK
);
1255 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1260 This
->ListViewSortInfo
.nHeaderID
= (LPARAM
) (dwCmdID
- 0x30);
1261 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
1262 This
->ListViewSortInfo
.nLastHeaderID
= This
->ListViewSortInfo
.nHeaderID
;
1263 SendMessageA(This
->hWndList
, LVM_SORTITEMS
, (WPARAM
) &This
->ListViewSortInfo
, (LPARAM
)ShellView_ListViewCompareItems
);
1267 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID
);
1272 /**********************************************************
1273 * ShellView_OnNotify()
1276 static LRESULT
ShellView_OnNotify(IShellViewImpl
* This
, UINT CtlID
, LPNMHDR lpnmh
)
1277 { LPNMLISTVIEW lpnmlv
= (LPNMLISTVIEW
)lpnmh
;
1278 NMLVDISPINFOW
*lpdi
= (NMLVDISPINFOW
*)lpnmh
;
1281 TRACE("%p CtlID=%u lpnmh->code=%x\n",This
,CtlID
,lpnmh
->code
);
1286 TRACE("-- NM_SETFOCUS %p\n",This
);
1287 ShellView_OnSetFocus(This
);
1291 TRACE("-- NM_KILLFOCUS %p\n",This
);
1292 ShellView_OnDeactivate(This
);
1293 /* Notify the ICommDlgBrowser interface */
1294 OnStateChange(This
,CDBOSC_KILLFOCUS
);
1298 TRACE("-- NM_CUSTOMDRAW %p\n",This
);
1299 return CDRF_DODEFAULT
;
1301 case NM_RELEASEDCAPTURE
:
1302 TRACE("-- NM_RELEASEDCAPTURE %p\n",This
);
1306 TRACE("-- NM_CLICK %p\n",This
);
1310 TRACE("-- NM_RCLICK %p\n",This
);
1314 TRACE("-- NM_DBLCLK %p\n",This
);
1315 if (OnDefaultCommand(This
) != S_OK
) ShellView_OpenSelectedItems(This
);
1319 TRACE("-- NM_DBLCLK %p\n",This
);
1320 if (OnDefaultCommand(This
) != S_OK
) ShellView_OpenSelectedItems(This
);
1324 TRACE("-- HDN_ENDTRACKW %p\n",This
);
1325 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1326 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1329 case LVN_DELETEITEM
:
1330 TRACE("-- LVN_DELETEITEM %p\n",This
);
1331 SHFree((LPITEMIDLIST
)lpnmlv
->lParam
); /*delete the pidl because we made a copy of it*/
1334 case LVN_DELETEALLITEMS
:
1335 TRACE("-- LVN_DELETEALLITEMS %p\n",This
);
1338 case LVN_INSERTITEM
:
1339 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This
);
1342 case LVN_ITEMACTIVATE
:
1343 TRACE("-- LVN_ITEMACTIVATE %p\n",This
);
1344 OnStateChange(This
, CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1347 case LVN_COLUMNCLICK
:
1348 This
->ListViewSortInfo
.nHeaderID
= lpnmlv
->iSubItem
;
1349 if(This
->ListViewSortInfo
.nLastHeaderID
== This
->ListViewSortInfo
.nHeaderID
)
1351 This
->ListViewSortInfo
.bIsAscending
= !This
->ListViewSortInfo
.bIsAscending
;
1355 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
1357 This
->ListViewSortInfo
.nLastHeaderID
= This
->ListViewSortInfo
.nHeaderID
;
1359 SendMessageW(lpnmlv
->hdr
.hwndFrom
, LVM_SORTITEMS
, (WPARAM
) &This
->ListViewSortInfo
, (LPARAM
)ShellView_ListViewCompareItems
);
1362 case LVN_GETDISPINFOA
:
1363 case LVN_GETDISPINFOW
:
1364 TRACE("-- LVN_GETDISPINFO %p\n",This
);
1365 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1367 if(lpdi
->item
.mask
& LVIF_TEXT
) /* text requested */
1369 if (This
->pSF2Parent
)
1372 IShellFolder2_GetDetailsOf(This
->pSF2Parent
, pidl
, lpdi
->item
.iSubItem
, &sd
);
1373 if (lpnmh
->code
== LVN_GETDISPINFOA
)
1375 /* shouldn't happen */
1376 NMLVDISPINFOA
*lpdiA
= (NMLVDISPINFOA
*)lpnmh
;
1377 StrRetToStrNA( lpdiA
->item
.pszText
, lpdiA
->item
.cchTextMax
, &sd
.str
, NULL
);
1378 TRACE("-- text=%s\n",lpdiA
->item
.pszText
);
1380 else /* LVN_GETDISPINFOW */
1382 StrRetToStrNW( lpdi
->item
.pszText
, lpdi
->item
.cchTextMax
, &sd
.str
, NULL
);
1383 TRACE("-- text=%s\n",debugstr_w(lpdi
->item
.pszText
));
1391 if(lpdi
->item
.mask
& LVIF_IMAGE
) /* image requested */
1393 lpdi
->item
.iImage
= SHMapPIDLToSystemImageListIndex(This
->pSFParent
, pidl
, 0);
1397 case LVN_ITEMCHANGED
:
1398 TRACE("-- LVN_ITEMCHANGED %p\n",This
);
1399 OnStateChange(This
, CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1403 case LVN_BEGINRDRAG
:
1404 TRACE("-- LVN_BEGINDRAG\n");
1406 if (ShellView_GetSelections(This
))
1409 DWORD dwAttributes
= SFGAO_CANLINK
;
1410 DWORD dwEffect
= DROPEFFECT_COPY
| DROPEFFECT_MOVE
;
1412 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, &IID_IDataObject
,0,(LPVOID
*)&pda
)))
1414 IDropSource
* pds
= (IDropSource
*)&(This
->lpvtblDropSource
); /* own DropSource interface */
1416 if (SUCCEEDED(IShellFolder_GetAttributesOf(This
->pSFParent
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, &dwAttributes
)))
1418 if (dwAttributes
& SFGAO_CANLINK
)
1420 dwEffect
|= DROPEFFECT_LINK
;
1427 DoDragDrop(pda
, pds
, dwEffect
, &dwEffect
);
1429 IDataObject_Release(pda
);
1434 case LVN_BEGINLABELEDITW
:
1436 DWORD dwAttr
= SFGAO_CANRENAME
;
1437 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1439 TRACE("-- LVN_BEGINLABELEDITA %p\n",This
);
1441 IShellFolder_GetAttributesOf(This
->pSFParent
, 1, (LPCITEMIDLIST
*)&pidl
, &dwAttr
);
1442 if (SFGAO_CANRENAME
& dwAttr
)
1449 case LVN_ENDLABELEDITW
:
1451 TRACE("-- LVN_ENDLABELEDITA %p\n",This
);
1452 if (lpdi
->item
.pszText
)
1457 lvItem
.iItem
= lpdi
->item
.iItem
;
1458 lvItem
.iSubItem
= 0;
1459 lvItem
.mask
= LVIF_PARAM
;
1460 SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
1462 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1463 hr
= IShellFolder_SetNameOf(This
->pSFParent
, 0, pidl
, lpdi
->item
.pszText
, SHGDN_INFOLDER
, &pidl
);
1465 if(SUCCEEDED(hr
) && pidl
)
1467 lvItem
.mask
= LVIF_PARAM
;
1468 lvItem
.lParam
= (LPARAM
)pidl
;
1469 SendMessageW(This
->hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
1479 msg.hwnd = This->hWnd;
1480 msg.message = WM_KEYDOWN;
1481 msg.wParam = plvKeyDown->wVKey;
1486 LPNMLVKEYDOWN plvKeyDown
= (LPNMLVKEYDOWN
) lpnmh
;
1488 /* initiate a rename of the selected file or directory */
1489 if(plvKeyDown
->wVKey
== VK_F2
)
1491 /* see how many files are selected */
1492 int i
= ListView_GetSelectedCount(This
->hWndList
);
1494 /* get selected item */
1497 /* get selected item */
1498 i
= ListView_GetNextItem(This
->hWndList
, -1,
1501 SendMessageW(This
->hWndList
, LVM_ENSUREVISIBLE
, i
, 0);
1502 SendMessageW(This
->hWndList
, LVM_EDITLABELW
, i
, 0);
1506 TranslateAccelerator(This
->hWnd
, This
->hAccel
, &msg
)
1508 else if(plvKeyDown
->wVKey
== VK_DELETE
)
1513 LPITEMIDLIST
* pItems
;
1516 IShellFolder_QueryInterface(This
->pSFParent
, &IID_ISFHelper
,
1522 if(!(i
= ListView_GetSelectedCount(This
->hWndList
)))
1525 /* allocate memory for the pidl array */
1526 pItems
= HeapAlloc(GetProcessHeap(), 0,
1527 sizeof(LPITEMIDLIST
) * i
);
1529 /* retrieve all selected items */
1532 while(ListView_GetSelectedCount(This
->hWndList
) > i
)
1534 /* get selected item */
1535 item_index
= ListView_GetNextItem(This
->hWndList
,
1536 item_index
, LVNI_SELECTED
);
1537 item
.iItem
= item_index
;
1538 item
.mask
= LVIF_PARAM
;
1539 SendMessageA(This
->hWndList
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1542 pItems
[i
] = (LPITEMIDLIST
)item
.lParam
;
1547 /* perform the item deletion */
1548 ISFHelper_DeleteItems(psfhlp
, i
, (LPCITEMIDLIST
*)pItems
);
1550 /* free pidl array memory */
1551 HeapFree(GetProcessHeap(), 0, pItems
);
1554 /* Initiate a refresh */
1555 else if(plvKeyDown
->wVKey
== VK_F5
)
1557 IShellView_Refresh((IShellView
*)This
);
1561 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown
->wVKey
);
1566 TRACE("-- %p WM_COMMAND %x unhandled\n", This
, lpnmh
->code
);
1572 /**********************************************************
1573 * ShellView_OnChange()
1576 static LRESULT
ShellView_OnChange(IShellViewImpl
* This
, const LPCITEMIDLIST
* Pidls
, LONG wEventId
)
1579 TRACE("(%p)(%p,%p,0x%08x)\n", This
, Pidls
[0], Pidls
[1], wEventId
);
1584 LV_AddItem(This
, Pidls
[0]);
1588 LV_DeleteItem(This
, Pidls
[0]);
1590 case SHCNE_RENAMEFOLDER
:
1591 case SHCNE_RENAMEITEM
:
1592 LV_RenameItem(This
, Pidls
[0], Pidls
[1]);
1594 case SHCNE_UPDATEITEM
:
1599 /**********************************************************
1603 static LRESULT CALLBACK
ShellView_WndProc(HWND hWnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
)
1605 IShellViewImpl
* pThis
= (IShellViewImpl
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
1606 LPCREATESTRUCTW lpcs
;
1608 TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd
, uMessage
, wParam
, lParam
);
1613 lpcs
= (LPCREATESTRUCTW
)lParam
;
1614 pThis
= (IShellViewImpl
*)(lpcs
->lpCreateParams
);
1615 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (ULONG_PTR
)pThis
);
1616 pThis
->hWnd
= hWnd
; /*set the window handle*/
1619 case WM_SIZE
: return ShellView_OnSize(pThis
,LOWORD(lParam
), HIWORD(lParam
));
1620 case WM_SETFOCUS
: return ShellView_OnSetFocus(pThis
);
1621 case WM_KILLFOCUS
: return ShellView_OnKillFocus(pThis
);
1622 case WM_CREATE
: return ShellView_OnCreate(pThis
);
1623 case WM_ACTIVATE
: return ShellView_OnActivate(pThis
, SVUIA_ACTIVATE_FOCUS
);
1624 case WM_NOTIFY
: return ShellView_OnNotify(pThis
,(UINT
)wParam
, (LPNMHDR
)lParam
);
1625 case WM_COMMAND
: return ShellView_OnCommand(pThis
,
1626 GET_WM_COMMAND_ID(wParam
, lParam
),
1627 GET_WM_COMMAND_CMD(wParam
, lParam
),
1628 GET_WM_COMMAND_HWND(wParam
, lParam
));
1629 case SHV_CHANGE_NOTIFY
: return ShellView_OnChange(pThis
, (const LPCITEMIDLIST
*)wParam
, (LONG
)lParam
);
1631 case WM_CONTEXTMENU
: ShellView_DoContextMenu(pThis
, LOWORD(lParam
), HIWORD(lParam
), FALSE
);
1634 case WM_SHOWWINDOW
: UpdateWindow(pThis
->hWndList
);
1637 case WM_GETDLGCODE
: return SendMessageA(pThis
->hWndList
,uMessage
,0,0);
1640 RevokeDragDrop(pThis
->hWnd
);
1641 SHChangeNotifyDeregister(pThis
->hNotify
);
1645 if ((pThis
->FolderSettings
.fFlags
& FWF_DESKTOP
) ||
1646 (pThis
->FolderSettings
.fFlags
& FWF_TRANSPARENT
))
1651 return DefWindowProcW(hWnd
, uMessage
, wParam
, lParam
);
1653 /**********************************************************
1656 * The INTERFACE of the IShellView object
1659 **********************************************************
1660 * IShellView_QueryInterface
1662 static HRESULT WINAPI
IShellView_fnQueryInterface(IShellView
* iface
,REFIID riid
, LPVOID
*ppvObj
)
1664 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1666 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
1670 if(IsEqualIID(riid
, &IID_IUnknown
))
1674 else if(IsEqualIID(riid
, &IID_IShellView
))
1676 *ppvObj
= (IShellView
*)This
;
1678 else if(IsEqualIID(riid
, &IID_IOleCommandTarget
))
1680 *ppvObj
= (IOleCommandTarget
*)&(This
->lpvtblOleCommandTarget
);
1682 else if(IsEqualIID(riid
, &IID_IDropTarget
))
1684 *ppvObj
= (IDropTarget
*)&(This
->lpvtblDropTarget
);
1686 else if(IsEqualIID(riid
, &IID_IDropSource
))
1688 *ppvObj
= (IDropSource
*)&(This
->lpvtblDropSource
);
1690 else if(IsEqualIID(riid
, &IID_IViewObject
))
1692 *ppvObj
= (IViewObject
*)&(This
->lpvtblViewObject
);
1697 IUnknown_AddRef( (IUnknown
*)*ppvObj
);
1698 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
1701 TRACE("-- Interface: E_NOINTERFACE\n");
1702 return E_NOINTERFACE
;
1705 /**********************************************************
1708 static ULONG WINAPI
IShellView_fnAddRef(IShellView
* iface
)
1710 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1711 ULONG refCount
= InterlockedIncrement(&This
->ref
);
1713 TRACE("(%p)->(count=%u)\n", This
, refCount
- 1);
1717 /**********************************************************
1718 * IShellView_Release
1720 static ULONG WINAPI
IShellView_fnRelease(IShellView
* iface
)
1722 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1723 ULONG refCount
= InterlockedDecrement(&This
->ref
);
1725 TRACE("(%p)->(count=%i)\n", This
, refCount
+ 1);
1729 TRACE(" destroying IShellView(%p)\n",This
);
1731 DestroyWindow(This
->hWndList
);
1734 IShellFolder_Release(This
->pSFParent
);
1736 if(This
->pSF2Parent
)
1737 IShellFolder2_Release(This
->pSF2Parent
);
1739 SHFree(This
->apidl
);
1742 IAdviseSink_Release(This
->pAdvSink
);
1744 HeapFree(GetProcessHeap(),0,This
);
1749 /**********************************************************
1750 * ShellView_GetWindow
1752 static HRESULT WINAPI
IShellView_fnGetWindow(IShellView
* iface
,HWND
* phWnd
)
1754 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1756 TRACE("(%p)\n",This
);
1758 *phWnd
= This
->hWnd
;
1763 static HRESULT WINAPI
IShellView_fnContextSensitiveHelp(IShellView
* iface
,BOOL fEnterMode
)
1765 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1767 FIXME("(%p) stub\n",This
);
1772 /**********************************************************
1773 * IShellView_TranslateAccelerator
1776 * use the accel functions
1778 static HRESULT WINAPI
IShellView_fnTranslateAccelerator(IShellView
* iface
,LPMSG lpmsg
)
1781 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1783 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This
,lpmsg
, lpmsg
->hwnd
, lpmsg
->message
, lpmsg
->lParam
, lpmsg
->wParam
);
1786 if ((lpmsg
->message
>=WM_KEYFIRST
) && (lpmsg
->message
>=WM_KEYLAST
))
1788 TRACE("-- key=0x04%lx\n",lpmsg
->wParam
) ;
1790 return S_FALSE
; /* not handled */
1793 static HRESULT WINAPI
IShellView_fnEnableModeless(IShellView
* iface
,BOOL fEnable
)
1795 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1797 FIXME("(%p) stub\n",This
);
1802 static HRESULT WINAPI
IShellView_fnUIActivate(IShellView
* iface
,UINT uState
)
1804 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1807 CHAR szName[MAX_PATH];
1810 int nPartArray
[1] = {-1};
1812 TRACE("(%p)->(state=%x) stub\n",This
, uState
);
1814 /*don't do anything if the state isn't really changing*/
1815 if(This
->uState
== uState
)
1820 /*OnActivate handles the menu merging and internal state*/
1821 ShellView_OnActivate(This
, uState
);
1823 /*only do This if we are active*/
1824 if(uState
!= SVUIA_DEACTIVATE
)
1828 GetFolderPath is not a method of IShellFolder
1829 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1831 /* set the number of parts */
1832 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_STATUS
, SB_SETPARTS
, 1,
1833 (LPARAM
)nPartArray
, &lResult
);
1835 /* set the text for the parts */
1837 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1838 0, (LPARAM)szName, &lResult);
1845 static HRESULT WINAPI
IShellView_fnRefresh(IShellView
* iface
)
1847 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1849 TRACE("(%p)\n",This
);
1851 SendMessageW(This
->hWndList
, LVM_DELETEALLITEMS
, 0, 0);
1852 ShellView_FillList(This
);
1857 static HRESULT WINAPI
IShellView_fnCreateViewWindow(
1859 IShellView
*lpPrevView
,
1860 LPCFOLDERSETTINGS lpfs
,
1861 IShellBrowser
* psb
,
1865 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1871 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This
, lpPrevView
,lpfs
, psb
, prcView
, phWnd
);
1872 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
);
1874 /*set up the member variables*/
1875 This
->pShellBrowser
= psb
;
1876 This
->FolderSettings
= *lpfs
;
1878 /*get our parent window*/
1879 IShellBrowser_AddRef(This
->pShellBrowser
);
1880 IShellBrowser_GetWindow(This
->pShellBrowser
, &(This
->hWndParent
));
1882 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1883 This
->pCommDlgBrowser
=NULL
;
1884 if ( SUCCEEDED (IShellBrowser_QueryInterface( This
->pShellBrowser
,
1885 (REFIID
)&IID_ICommDlgBrowser
, (LPVOID
*) &This
->pCommDlgBrowser
)))
1887 TRACE("-- CommDlgBrowser\n");
1890 /*if our window class has not been registered, then do so*/
1891 if(!GetClassInfoW(shell32_hInstance
, SV_CLASS_NAME
, &wc
))
1893 ZeroMemory(&wc
, sizeof(wc
));
1894 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1895 wc
.lpfnWndProc
= ShellView_WndProc
;
1898 wc
.hInstance
= shell32_hInstance
;
1900 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1901 wc
.hbrBackground
= (HBRUSH
) (COLOR_WINDOW
+ 1);
1902 wc
.lpszMenuName
= NULL
;
1903 wc
.lpszClassName
= SV_CLASS_NAME
;
1905 if(!RegisterClassW(&wc
))
1909 *phWnd
= CreateWindowExW(0,
1912 WS_CHILD
| WS_TABSTOP
,
1915 prcView
->right
- prcView
->left
,
1916 prcView
->bottom
- prcView
->top
,
1924 if(!*phWnd
) return E_FAIL
;
1926 SetWindowPos(*phWnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_SHOWWINDOW
);
1927 UpdateWindow(*phWnd
);
1932 static HRESULT WINAPI
IShellView_fnDestroyViewWindow(IShellView
* iface
)
1934 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1936 TRACE("(%p)\n",This
);
1938 /*Make absolutely sure all our UI is cleaned up.*/
1939 IShellView_UIActivate((IShellView
*)This
, SVUIA_DEACTIVATE
);
1943 DestroyMenu(This
->hMenu
);
1946 DestroyWindow(This
->hWnd
);
1947 if(This
->pShellBrowser
) IShellBrowser_Release(This
->pShellBrowser
);
1948 if(This
->pCommDlgBrowser
) ICommDlgBrowser_Release(This
->pCommDlgBrowser
);
1954 static HRESULT WINAPI
IShellView_fnGetCurrentInfo(IShellView
* iface
, LPFOLDERSETTINGS lpfs
)
1956 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1958 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This
, lpfs
,
1959 This
->FolderSettings
.ViewMode
, This
->FolderSettings
.fFlags
);
1961 if (!lpfs
) return E_INVALIDARG
;
1963 *lpfs
= This
->FolderSettings
;
1967 static HRESULT WINAPI
IShellView_fnAddPropertySheetPages(IShellView
* iface
, DWORD dwReserved
,LPFNADDPROPSHEETPAGE lpfn
, LPARAM lparam
)
1969 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1971 FIXME("(%p) stub\n",This
);
1976 static HRESULT WINAPI
IShellView_fnSaveViewState(IShellView
* iface
)
1978 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1980 FIXME("(%p) stub\n",This
);
1985 static HRESULT WINAPI
IShellView_fnSelectItem(
1990 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1993 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This
, pidl
, uFlags
);
1995 i
= LV_FindItemByPidl(This
, pidl
);
2001 if(uFlags
& SVSI_ENSUREVISIBLE
)
2002 SendMessageW(This
->hWndList
, LVM_ENSUREVISIBLE
, i
, 0);
2004 lvItem
.mask
= LVIF_STATE
;
2005 lvItem
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
2007 lvItem
.iSubItem
= 0;
2009 while(SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
))
2011 if (lvItem
.iItem
== i
)
2013 if (uFlags
& SVSI_SELECT
)
2014 lvItem
.state
|= LVIS_SELECTED
;
2016 lvItem
.state
&= ~LVIS_SELECTED
;
2018 if(uFlags
& SVSI_FOCUSED
)
2019 lvItem
.state
&= ~LVIS_FOCUSED
;
2023 if (uFlags
& SVSI_DESELECTOTHERS
)
2024 lvItem
.state
&= ~LVIS_SELECTED
;
2026 SendMessageW(This
->hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
2031 if(uFlags
& SVSI_EDIT
)
2032 SendMessageW(This
->hWndList
, LVM_EDITLABELW
, i
, 0);
2038 static HRESULT WINAPI
IShellView_fnGetItemObject(IShellView
* iface
, UINT uItem
, REFIID riid
, LPVOID
*ppvOut
)
2040 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2042 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This
, uItem
, debugstr_guid(riid
), ppvOut
);
2048 case SVGIO_BACKGROUND
:
2049 *ppvOut
= ISvBgCm_Constructor(This
->pSFParent
, FALSE
);
2052 case SVGIO_SELECTION
:
2053 ShellView_GetSelections(This
);
2054 IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, riid
, 0, ppvOut
);
2057 TRACE("-- (%p)->(interface=%p)\n",This
, *ppvOut
);
2059 if(!*ppvOut
) return E_OUTOFMEMORY
;
2064 static const IShellViewVtbl svvt
=
2066 IShellView_fnQueryInterface
,
2067 IShellView_fnAddRef
,
2068 IShellView_fnRelease
,
2069 IShellView_fnGetWindow
,
2070 IShellView_fnContextSensitiveHelp
,
2071 IShellView_fnTranslateAccelerator
,
2072 IShellView_fnEnableModeless
,
2073 IShellView_fnUIActivate
,
2074 IShellView_fnRefresh
,
2075 IShellView_fnCreateViewWindow
,
2076 IShellView_fnDestroyViewWindow
,
2077 IShellView_fnGetCurrentInfo
,
2078 IShellView_fnAddPropertySheetPages
,
2079 IShellView_fnSaveViewState
,
2080 IShellView_fnSelectItem
,
2081 IShellView_fnGetItemObject
2085 /**********************************************************
2086 * ISVOleCmdTarget_QueryInterface (IUnknown)
2088 static HRESULT WINAPI
ISVOleCmdTarget_QueryInterface(
2089 IOleCommandTarget
* iface
,
2093 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2095 return IShellFolder_QueryInterface((IShellFolder
*)This
, iid
, ppvObj
);
2098 /**********************************************************
2099 * ISVOleCmdTarget_AddRef (IUnknown)
2101 static ULONG WINAPI
ISVOleCmdTarget_AddRef(
2102 IOleCommandTarget
* iface
)
2104 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2106 return IShellFolder_AddRef((IShellFolder
*)This
);
2109 /**********************************************************
2110 * ISVOleCmdTarget_Release (IUnknown)
2112 static ULONG WINAPI
ISVOleCmdTarget_Release(
2113 IOleCommandTarget
* iface
)
2115 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2117 return IShellFolder_Release((IShellFolder
*)This
);
2120 /**********************************************************
2121 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2123 static HRESULT WINAPI
ISVOleCmdTarget_QueryStatus(
2124 IOleCommandTarget
*iface
,
2125 const GUID
* pguidCmdGroup
,
2128 OLECMDTEXT
* pCmdText
)
2131 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2133 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2134 This
, pguidCmdGroup
, debugstr_guid(pguidCmdGroup
), cCmds
, prgCmds
, pCmdText
);
2138 for (i
= 0; i
< cCmds
; i
++)
2140 FIXME("\tprgCmds[%d].cmdID = %d\n", i
, prgCmds
[i
].cmdID
);
2141 prgCmds
[i
].cmdf
= 0;
2143 return OLECMDERR_E_UNKNOWNGROUP
;
2146 /**********************************************************
2147 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2149 * nCmdID is the OLECMDID_* enumeration
2151 static HRESULT WINAPI
ISVOleCmdTarget_Exec(
2152 IOleCommandTarget
*iface
,
2153 const GUID
* pguidCmdGroup
,
2159 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2161 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2162 This
, debugstr_guid(pguidCmdGroup
), nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
2164 if (IsEqualIID(pguidCmdGroup
, &CGID_Explorer
) &&
2166 (nCmdexecopt
== 4) && pvaOut
)
2168 if (IsEqualIID(pguidCmdGroup
, &CGID_ShellDocView
) &&
2173 return OLECMDERR_E_UNKNOWNGROUP
;
2176 static const IOleCommandTargetVtbl ctvt
=
2178 ISVOleCmdTarget_QueryInterface
,
2179 ISVOleCmdTarget_AddRef
,
2180 ISVOleCmdTarget_Release
,
2181 ISVOleCmdTarget_QueryStatus
,
2182 ISVOleCmdTarget_Exec
2185 /**********************************************************
2186 * ISVDropTarget implementation
2189 static HRESULT WINAPI
ISVDropTarget_QueryInterface(
2194 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2196 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2198 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2201 static ULONG WINAPI
ISVDropTarget_AddRef( IDropTarget
*iface
)
2203 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2205 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2207 return IShellFolder_AddRef((IShellFolder
*)This
);
2210 static ULONG WINAPI
ISVDropTarget_Release( IDropTarget
*iface
)
2212 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2214 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2216 return IShellFolder_Release((IShellFolder
*)This
);
2219 /******************************************************************************
2220 * drag_notify_subitem [Internal]
2222 * Figure out the shellfolder object, which is currently under the mouse cursor
2223 * and notify it via the IDropTarget interface.
2226 #define SCROLLAREAWIDTH 20
2228 static HRESULT
drag_notify_subitem(IShellViewImpl
*This
, DWORD grfKeyState
, POINTL pt
,
2231 LVHITTESTINFO htinfo
;
2237 /* Map from global to client coordinates and query the index of the listview-item, which is
2238 * currently under the mouse cursor. */
2241 htinfo
.flags
= LVHT_ONITEM
;
2242 ScreenToClient(This
->hWndList
, &htinfo
.pt
);
2243 lResult
= SendMessageW(This
->hWndList
, LVM_HITTEST
, 0, (LPARAM
)&htinfo
);
2245 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2246 GetClientRect(This
->hWndList
, &clientRect
);
2247 if (htinfo
.pt
.x
== This
->ptLastMousePos
.x
&& htinfo
.pt
.y
== This
->ptLastMousePos
.y
&&
2248 (htinfo
.pt
.x
< SCROLLAREAWIDTH
|| htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
||
2249 htinfo
.pt
.y
< SCROLLAREAWIDTH
|| htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
))
2251 This
->cScrollDelay
= (This
->cScrollDelay
+ 1) % 5; /* DragOver is called every 50 ms */
2252 if (This
->cScrollDelay
== 0) { /* Mouse did hover another 250 ms over the scroll-area */
2253 if (htinfo
.pt
.x
< SCROLLAREAWIDTH
)
2254 SendMessageW(This
->hWndList
, WM_HSCROLL
, SB_LINEUP
, 0);
2255 if (htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
)
2256 SendMessageW(This
->hWndList
, WM_HSCROLL
, SB_LINEDOWN
, 0);
2257 if (htinfo
.pt
.y
< SCROLLAREAWIDTH
)
2258 SendMessageW(This
->hWndList
, WM_VSCROLL
, SB_LINEUP
, 0);
2259 if (htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
)
2260 SendMessageW(This
->hWndList
, WM_VSCROLL
, SB_LINEDOWN
, 0);
2263 This
->cScrollDelay
= 0; /* Reset, if the cursor is not over the listview's scroll-area */
2265 This
->ptLastMousePos
= htinfo
.pt
;
2267 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2268 if (This
->pCurDropTarget
&& lResult
== This
->iDragOverItem
)
2269 return IDropTarget_DragOver(This
->pCurDropTarget
, grfKeyState
, pt
, pdwEffect
);
2271 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2272 if (This
->pCurDropTarget
) {
2273 IDropTarget_DragLeave(This
->pCurDropTarget
);
2274 IDropTarget_Release(This
->pCurDropTarget
);
2275 This
->pCurDropTarget
= NULL
;
2278 This
->iDragOverItem
= lResult
;
2279 if (lResult
== -1) {
2280 /* We are not above one of the listview's subitems. Bind to the parent folder's
2281 * DropTarget interface. */
2282 hr
= IShellFolder_QueryInterface(This
->pSFParent
, &IID_IDropTarget
,
2283 (LPVOID
*)&This
->pCurDropTarget
);
2285 /* Query the relative PIDL of the shellfolder object represented by the currently
2286 * dragged over listview-item ... */
2287 lvItem
.mask
= LVIF_PARAM
;
2288 lvItem
.iItem
= lResult
;
2289 lvItem
.iSubItem
= 0;
2290 SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
2292 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2293 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWndList
, 1,
2294 (LPCITEMIDLIST
*)&lvItem
.lParam
, &IID_IDropTarget
, NULL
, (LPVOID
*)&This
->pCurDropTarget
);
2297 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2301 /* Notify the item just entered via DragEnter. */
2302 return IDropTarget_DragEnter(This
->pCurDropTarget
, This
->pCurDataObject
, grfKeyState
, pt
, pdwEffect
);
2305 static HRESULT WINAPI
ISVDropTarget_DragEnter(IDropTarget
*iface
, IDataObject
*pDataObject
,
2306 DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2308 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2310 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2311 This
->pCurDataObject
= pDataObject
;
2312 IDataObject_AddRef(pDataObject
);
2314 return drag_notify_subitem(This
, grfKeyState
, pt
, pdwEffect
);
2317 static HRESULT WINAPI
ISVDropTarget_DragOver(IDropTarget
*iface
, DWORD grfKeyState
, POINTL pt
,
2320 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2321 return drag_notify_subitem(This
, grfKeyState
, pt
, pdwEffect
);
2324 static HRESULT WINAPI
ISVDropTarget_DragLeave(IDropTarget
*iface
) {
2325 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2327 IDropTarget_DragLeave(This
->pCurDropTarget
);
2329 IDropTarget_Release(This
->pCurDropTarget
);
2330 IDataObject_Release(This
->pCurDataObject
);
2331 This
->pCurDataObject
= NULL
;
2332 This
->pCurDropTarget
= NULL
;
2333 This
->iDragOverItem
= 0;
2338 static HRESULT WINAPI
ISVDropTarget_Drop(IDropTarget
*iface
, IDataObject
* pDataObject
,
2339 DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2341 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2343 IDropTarget_Drop(This
->pCurDropTarget
, pDataObject
, grfKeyState
, pt
, pdwEffect
);
2345 IDropTarget_Release(This
->pCurDropTarget
);
2346 IDataObject_Release(This
->pCurDataObject
);
2347 This
->pCurDataObject
= NULL
;
2348 This
->pCurDropTarget
= NULL
;
2349 This
->iDragOverItem
= 0;
2354 static const IDropTargetVtbl dtvt
=
2356 ISVDropTarget_QueryInterface
,
2357 ISVDropTarget_AddRef
,
2358 ISVDropTarget_Release
,
2359 ISVDropTarget_DragEnter
,
2360 ISVDropTarget_DragOver
,
2361 ISVDropTarget_DragLeave
,
2365 /**********************************************************
2366 * ISVDropSource implementation
2369 static HRESULT WINAPI
ISVDropSource_QueryInterface(
2374 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2376 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2378 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2381 static ULONG WINAPI
ISVDropSource_AddRef( IDropSource
*iface
)
2383 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2385 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2387 return IShellFolder_AddRef((IShellFolder
*)This
);
2390 static ULONG WINAPI
ISVDropSource_Release( IDropSource
*iface
)
2392 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2394 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2396 return IShellFolder_Release((IShellFolder
*)This
);
2398 static HRESULT WINAPI
ISVDropSource_QueryContinueDrag(
2400 BOOL fEscapePressed
,
2403 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2404 TRACE("(%p)\n",This
);
2407 return DRAGDROP_S_CANCEL
;
2408 else if (!(grfKeyState
& MK_LBUTTON
) && !(grfKeyState
& MK_RBUTTON
))
2409 return DRAGDROP_S_DROP
;
2414 static HRESULT WINAPI
ISVDropSource_GiveFeedback(
2418 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2419 TRACE("(%p)\n",This
);
2421 return DRAGDROP_S_USEDEFAULTCURSORS
;
2424 static const IDropSourceVtbl dsvt
=
2426 ISVDropSource_QueryInterface
,
2427 ISVDropSource_AddRef
,
2428 ISVDropSource_Release
,
2429 ISVDropSource_QueryContinueDrag
,
2430 ISVDropSource_GiveFeedback
2432 /**********************************************************
2433 * ISVViewObject implementation
2436 static HRESULT WINAPI
ISVViewObject_QueryInterface(
2441 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2443 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2445 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2448 static ULONG WINAPI
ISVViewObject_AddRef( IViewObject
*iface
)
2450 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2452 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2454 return IShellFolder_AddRef((IShellFolder
*)This
);
2457 static ULONG WINAPI
ISVViewObject_Release( IViewObject
*iface
)
2459 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2461 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2463 return IShellFolder_Release((IShellFolder
*)This
);
2466 static HRESULT WINAPI
ISVViewObject_Draw(
2471 DVTARGETDEVICE
* ptd
,
2474 LPCRECTL lprcBounds
,
2475 LPCRECTL lprcWBounds
,
2476 BOOL (CALLBACK
*pfnContinue
)(ULONG_PTR dwContinue
),
2477 ULONG_PTR dwContinue
)
2480 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2482 FIXME("Stub: This=%p\n",This
);
2486 static HRESULT WINAPI
ISVViewObject_GetColorSet(
2491 DVTARGETDEVICE
* ptd
,
2492 HDC hicTargetDevice
,
2493 LOGPALETTE
** ppColorSet
)
2496 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2498 FIXME("Stub: This=%p\n",This
);
2502 static HRESULT WINAPI
ISVViewObject_Freeze(
2510 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2512 FIXME("Stub: This=%p\n",This
);
2516 static HRESULT WINAPI
ISVViewObject_Unfreeze(
2521 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2523 FIXME("Stub: This=%p\n",This
);
2527 static HRESULT WINAPI
ISVViewObject_SetAdvise(
2531 IAdviseSink
* pAdvSink
)
2534 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2536 FIXME("partial stub: %p %08x %08x %p\n",
2537 This
, aspects
, advf
, pAdvSink
);
2539 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2540 This
->pAdvSink
= pAdvSink
;
2541 This
->dwAspects
= aspects
;
2542 This
->dwAdvf
= advf
;
2547 static HRESULT WINAPI
ISVViewObject_GetAdvise(
2551 IAdviseSink
** ppAdvSink
)
2554 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2556 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2557 This
, pAspects
, pAdvf
, ppAdvSink
);
2561 IAdviseSink_AddRef( This
->pAdvSink
);
2562 *ppAdvSink
= This
->pAdvSink
;
2565 *pAspects
= This
->dwAspects
;
2567 *pAdvf
= This
->dwAdvf
;
2573 static const IViewObjectVtbl vovt
=
2575 ISVViewObject_QueryInterface
,
2576 ISVViewObject_AddRef
,
2577 ISVViewObject_Release
,
2579 ISVViewObject_GetColorSet
,
2580 ISVViewObject_Freeze
,
2581 ISVViewObject_Unfreeze
,
2582 ISVViewObject_SetAdvise
,
2583 ISVViewObject_GetAdvise