4 * Copyright 1998,1999 <juergen.schmied@debitel.net>
6 * This is the view visualizing the data provided 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 * built according to the columns shown.
26 * FIXME: Load/Save the view state from/into the stream provided 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
41 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
45 static const WCHAR SV_CLASS_NAME
[] = {'S','H','E','L','L','D','L','L','_','D','e','f','V','i','e','w',0};
51 }LISTVIEW_SORT_INFO
, *LPLISTVIEW_SORT_INFO
;
55 const IShellViewVtbl
* lpVtbl
;
57 const IOleCommandTargetVtbl
* lpvtblOleCommandTarget
;
58 const IDropTargetVtbl
* lpvtblDropTarget
;
59 const IDropSourceVtbl
* lpvtblDropSource
;
60 const IViewObjectVtbl
* lpvtblViewObject
;
61 IShellFolder
* pSFParent
;
62 IShellFolder2
* pSF2Parent
;
63 IShellBrowser
* pShellBrowser
;
64 ICommDlgBrowser
* pCommDlgBrowser
;
65 HWND hWnd
; /* SHELLDLL_DefView */
66 HWND hWndList
; /* ListView control */
68 FOLDERSETTINGS FolderSettings
;
73 LISTVIEW_SORT_INFO ListViewSortInfo
;
74 ULONG hNotify
; /* change notification handle */
78 IAdviseSink
*pAdvSink
;
79 IDropTarget
* pCurDropTarget
; /* The sub-item, which is currently dragged over */
80 IDataObject
* pCurDataObject
; /* The dragged data-object */
81 LONG iDragOverItem
; /* Dragged over item's index, iff pCurDropTarget != NULL */
82 UINT cScrollDelay
; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
83 POINT ptLastMousePos
; /* Mouse position at last DragOver call */
85 } IShellViewImpl
, *LPIShellViewImpl
;
87 static const IShellViewVtbl svvt
;
88 static const IOleCommandTargetVtbl ctvt
;
89 static const IDropTargetVtbl dtvt
;
90 static const IDropSourceVtbl dsvt
;
91 static const IViewObjectVtbl vovt
;
94 static LPIShellViewImpl __inline
impl_from_IOleCommandTarget( IOleCommandTarget
*iface
)
96 return (LPIShellViewImpl
)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblOleCommandTarget
));
99 static LPIShellViewImpl __inline
impl_from_IDropTarget( IDropTarget
*iface
)
101 return (LPIShellViewImpl
)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblDropTarget
));
104 static LPIShellViewImpl __inline
impl_from_IDropSource( IDropSource
*iface
)
106 return (LPIShellViewImpl
)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblDropSource
));
109 static LPIShellViewImpl __inline
impl_from_IViewObject( IViewObject
*iface
)
111 return (LPIShellViewImpl
)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblViewObject
));
114 /* ListView Header ID's */
115 #define LISTVIEW_COLUMN_NAME 0
116 #define LISTVIEW_COLUMN_SIZE 1
117 #define LISTVIEW_COLUMN_TYPE 2
118 #define LISTVIEW_COLUMN_TIME 3
119 #define LISTVIEW_COLUMN_ATTRIB 4
122 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
123 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
124 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
126 #define ID_LISTVIEW 1
128 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
131 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
132 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
133 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
136 Items merged into the toolbar and the filemenu
145 } MYTOOLINFO
, *LPMYTOOLINFO
;
147 static const MYTOOLINFO Tools
[] =
149 { FCIDM_SHVIEW_BIGICON
, 0, 0, IDS_VIEW_LARGE
, TBSTATE_ENABLED
, BTNS_BUTTON
},
150 { FCIDM_SHVIEW_SMALLICON
, 0, 0, IDS_VIEW_SMALL
, TBSTATE_ENABLED
, BTNS_BUTTON
},
151 { FCIDM_SHVIEW_LISTVIEW
, 0, 0, IDS_VIEW_LIST
, TBSTATE_ENABLED
, BTNS_BUTTON
},
152 { FCIDM_SHVIEW_REPORTVIEW
, 0, 0, IDS_VIEW_DETAILS
, TBSTATE_ENABLED
, BTNS_BUTTON
},
156 typedef void (CALLBACK
*PFNSHGETSETTINGSPROC
)(LPSHELLFLAGSTATE lpsfs
, DWORD dwMask
);
158 /**********************************************************
159 * IShellView_Constructor
161 IShellView
* IShellView_Constructor( IShellFolder
* pFolder
)
162 { IShellViewImpl
* sv
;
163 sv
=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IShellViewImpl
));
166 sv
->lpvtblOleCommandTarget
=&ctvt
;
167 sv
->lpvtblDropTarget
=&dtvt
;
168 sv
->lpvtblDropSource
=&dsvt
;
169 sv
->lpvtblViewObject
=&vovt
;
171 sv
->pSFParent
= pFolder
;
172 if(pFolder
) IShellFolder_AddRef(pFolder
);
173 IShellFolder_QueryInterface(sv
->pSFParent
, &IID_IShellFolder2
, (LPVOID
*)&sv
->pSF2Parent
);
175 sv
->pCurDropTarget
= NULL
;
176 sv
->pCurDataObject
= NULL
;
177 sv
->iDragOverItem
= 0;
178 sv
->cScrollDelay
= 0;
179 sv
->ptLastMousePos
.x
= 0;
180 sv
->ptLastMousePos
.y
= 0;
182 TRACE("(%p)->(%p)\n",sv
, pFolder
);
183 return (IShellView
*) sv
;
186 /**********************************************************
188 * ##### helperfunctions for communication with ICommDlgBrowser #####
190 static BOOL
IsInCommDlg(IShellViewImpl
* This
)
191 { return(This
->pCommDlgBrowser
!= NULL
);
194 static HRESULT
IncludeObject(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
198 if ( IsInCommDlg(This
) )
200 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl
);
201 ret
= ICommDlgBrowser_IncludeObject(This
->pCommDlgBrowser
, (IShellView
*)This
, pidl
);
202 TRACE("--0x%08x\n", ret
);
207 static HRESULT
OnDefaultCommand(IShellViewImpl
* This
)
209 HRESULT ret
= S_FALSE
;
211 if (IsInCommDlg(This
))
213 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
214 ret
= ICommDlgBrowser_OnDefaultCommand(This
->pCommDlgBrowser
, (IShellView
*)This
);
215 TRACE("-- returns %08x\n", ret
);
220 static HRESULT
OnStateChange(IShellViewImpl
* This
, UINT uFlags
)
222 HRESULT ret
= S_FALSE
;
224 if (IsInCommDlg(This
))
226 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags
);
227 ret
= ICommDlgBrowser_OnStateChange(This
->pCommDlgBrowser
, (IShellView
*)This
, uFlags
);
232 /**********************************************************
233 * set the toolbar of the filedialog buttons
235 * - activates the buttons from the shellbrowser according to
238 static void CheckToolbar(IShellViewImpl
* This
)
244 if (IsInCommDlg(This
))
246 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_CHECKBUTTON
,
247 FCIDM_TB_SMALLICON
, (This
->FolderSettings
.ViewMode
==FVM_LIST
)? TRUE
: FALSE
, &result
);
248 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_CHECKBUTTON
,
249 FCIDM_TB_REPORTVIEW
, (This
->FolderSettings
.ViewMode
==FVM_DETAILS
)? TRUE
: FALSE
, &result
);
250 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_ENABLEBUTTON
,
251 FCIDM_TB_SMALLICON
, TRUE
, &result
);
252 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_ENABLEBUTTON
,
253 FCIDM_TB_REPORTVIEW
, TRUE
, &result
);
257 /**********************************************************
259 * ##### helperfunctions for initializing the view #####
261 /**********************************************************
262 * change the style of the listview control
264 static void SetStyle(IShellViewImpl
* This
, DWORD dwAdd
, DWORD dwRemove
)
268 TRACE("(%p)\n", This
);
270 tmpstyle
= GetWindowLongPtrW(This
->hWndList
, GWL_STYLE
);
271 SetWindowLongPtrW(This
->hWndList
, GWL_STYLE
, dwAdd
| (tmpstyle
& ~dwRemove
));
274 /**********************************************************
275 * ShellView_CreateList()
277 * - creates the list view window
279 static BOOL
ShellView_CreateList (IShellViewImpl
* This
)
280 { DWORD dwStyle
, dwExStyle
;
284 dwStyle
= WS_TABSTOP
| WS_VISIBLE
| WS_CHILDWINDOW
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
285 LVS_SHAREIMAGELISTS
| LVS_EDITLABELS
| LVS_ALIGNLEFT
| LVS_AUTOARRANGE
;
286 dwExStyle
= WS_EX_CLIENTEDGE
;
288 switch (This
->FolderSettings
.ViewMode
)
290 case FVM_ICON
: dwStyle
|= LVS_ICON
; break;
291 case FVM_DETAILS
: dwStyle
|= LVS_REPORT
; break;
292 case FVM_SMALLICON
: dwStyle
|= LVS_SMALLICON
; break;
293 case FVM_LIST
: dwStyle
|= LVS_LIST
; break;
294 default: dwStyle
|= LVS_LIST
; break;
297 if (This
->FolderSettings
.fFlags
& FWF_AUTOARRANGE
) dwStyle
|= LVS_AUTOARRANGE
;
298 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
)
299 This
->FolderSettings
.fFlags
|= FWF_NOCLIENTEDGE
| FWF_NOSCROLL
;
300 if (This
->FolderSettings
.fFlags
& FWF_SINGLESEL
) dwStyle
|= LVS_SINGLESEL
;
301 if (This
->FolderSettings
.fFlags
& FWF_NOCLIENTEDGE
)
302 dwExStyle
&= ~WS_EX_CLIENTEDGE
;
304 This
->hWndList
=CreateWindowExW( dwExStyle
,
317 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
318 This
->ListViewSortInfo
.nHeaderID
= -1;
319 This
->ListViewSortInfo
.nLastHeaderID
= -1;
321 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
) {
323 * FIXME: look at the registry value
324 * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
325 * and activate drop shadows if necessary
328 SendMessageW(This
->hWndList
, LVM_SETTEXTBKCOLOR
, 0, CLR_NONE
);
331 SendMessageW(This
->hWndList
, LVM_SETTEXTBKCOLOR
, 0, GetSysColor(COLOR_DESKTOP
));
332 SendMessageW(This
->hWndList
, LVM_SETBKCOLOR
, 0, GetSysColor(COLOR_DESKTOP
));
335 SendMessageW(This
->hWndList
, LVM_SETTEXTCOLOR
, 0, RGB(255,255,255));
338 /* UpdateShellSettings(); */
342 /**********************************************************
343 * ShellView_InitList()
345 * - adds all needed columns to the shellview
347 static BOOL
ShellView_InitList(IShellViewImpl
* This
)
356 SendMessageW(This
->hWndList
, LVM_DELETEALLITEMS
, 0, 0);
358 lvColumn
.mask
= LVCF_FMT
| LVCF_WIDTH
| LVCF_TEXT
;
359 lvColumn
.pszText
= szTemp
;
361 if (This
->pSF2Parent
)
365 if (FAILED(IShellFolder2_GetDetailsOf(This
->pSF2Parent
, NULL
, i
, &sd
)))
367 lvColumn
.fmt
= sd
.fmt
;
368 lvColumn
.cx
= sd
.cxChar
*8; /* chars->pixel */
369 StrRetToStrNW( szTemp
, 50, &sd
.str
, NULL
);
370 SendMessageW(This
->hWndList
, LVM_INSERTCOLUMNW
, i
, (LPARAM
) &lvColumn
);
378 SendMessageW(This
->hWndList
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)ShellSmallIconList
);
379 SendMessageW(This
->hWndList
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)ShellBigIconList
);
383 /**********************************************************
384 * ShellView_CompareItems()
387 * internal, CALLBACK for DSA_Sort
389 static INT CALLBACK
ShellView_CompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
)
392 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1
, lParam2
, (LPVOID
) lpData
);
394 if(!lpData
) return 0;
396 ret
= (SHORT
) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER
)lpData
, 0, (LPITEMIDLIST
)lParam1
, (LPITEMIDLIST
)lParam2
));
397 TRACE("ret=%i\n",ret
);
401 /*************************************************************************
402 * ShellView_ListViewCompareItems
404 * Compare Function for the Listview (FileOpen Dialog)
407 * lParam1 [I] the first ItemIdList to compare with
408 * lParam2 [I] the second ItemIdList to compare with
409 * lpData [I] The column ID for the header Ctrl to process
412 * A negative value if the first item should precede the second,
413 * a positive value if the first item should follow the second,
414 * or zero if the two items are equivalent
417 * FIXME: function does what ShellView_CompareItems is supposed to do.
418 * unify it and figure out how to use the undocumented first parameter
419 * of IShellFolder_CompareIDs to do the job this function does and
420 * move this code to IShellFolder.
421 * make LISTVIEW_SORT_INFO obsolete
422 * the way this function works is only usable if we had only
423 * filesystemfolders (25/10/99 jsch)
425 static INT CALLBACK
ShellView_ListViewCompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
)
429 char strName1
[MAX_PATH
], strName2
[MAX_PATH
];
430 BOOL bIsFolder1
, bIsFolder2
,bIsBothFolder
;
431 LPITEMIDLIST pItemIdList1
= lParam1
;
432 LPITEMIDLIST pItemIdList2
= lParam2
;
433 LISTVIEW_SORT_INFO
*pSortInfo
= (LPLISTVIEW_SORT_INFO
) lpData
;
436 bIsFolder1
= _ILIsFolder(pItemIdList1
);
437 bIsFolder2
= _ILIsFolder(pItemIdList2
);
438 bIsBothFolder
= bIsFolder1
&& bIsFolder2
;
440 /* When sorting between a File and a Folder, the Folder gets sorted first */
441 if( (bIsFolder1
|| bIsFolder2
) && !bIsBothFolder
)
443 nDiff
= bIsFolder1
? -1 : 1;
447 /* Sort by Time: Folders or Files can be sorted */
449 if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_TIME
)
451 _ILGetFileDateTime(pItemIdList1
, &fd1
);
452 _ILGetFileDateTime(pItemIdList2
, &fd2
);
453 nDiff
= CompareFileTime(&fd2
, &fd1
);
455 /* Sort by Attribute: Folder or Files can be sorted */
456 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_ATTRIB
)
458 _ILGetFileAttributes(pItemIdList1
, strName1
, MAX_PATH
);
459 _ILGetFileAttributes(pItemIdList2
, strName2
, MAX_PATH
);
460 nDiff
= lstrcmpiA(strName1
, strName2
);
462 /* Sort by FileName: Folder or Files can be sorted */
463 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_NAME
|| bIsBothFolder
)
466 _ILSimpleGetText(pItemIdList1
, strName1
, MAX_PATH
);
467 _ILSimpleGetText(pItemIdList2
, strName2
, MAX_PATH
);
468 nDiff
= lstrcmpiA(strName1
, strName2
);
470 /* Sort by File Size, Only valid for Files */
471 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_SIZE
)
473 nDiff
= (INT
)(_ILGetFileSize(pItemIdList1
, NULL
, 0) - _ILGetFileSize(pItemIdList2
, NULL
, 0));
475 /* Sort by File Type, Only valid for Files */
476 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_TYPE
)
479 _ILGetFileType(pItemIdList1
, strName1
, MAX_PATH
);
480 _ILGetFileType(pItemIdList2
, strName2
, MAX_PATH
);
481 nDiff
= lstrcmpiA(strName1
, strName2
);
484 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
488 _ILSimpleGetText(pItemIdList1
, strName1
, MAX_PATH
);
489 _ILSimpleGetText(pItemIdList2
, strName2
, MAX_PATH
);
490 nDiff
= lstrcmpiA(strName1
, strName2
);
493 if(!pSortInfo
->bIsAscending
)
502 /**********************************************************
503 * LV_FindItemByPidl()
505 static int LV_FindItemByPidl(
506 IShellViewImpl
* This
,
511 lvItem
.mask
= LVIF_PARAM
;
512 for(lvItem
.iItem
= 0;
513 SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
516 LPITEMIDLIST currentpidl
= (LPITEMIDLIST
) lvItem
.lParam
;
517 HRESULT hr
= IShellFolder_CompareIDs(This
->pSFParent
, 0, pidl
, currentpidl
);
518 if(SUCCEEDED(hr
) && !HRESULT_CODE(hr
))
526 /**********************************************************
529 static BOOLEAN
LV_AddItem(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
533 TRACE("(%p)(pidl=%p)\n", This
, pidl
);
535 lvItem
.mask
= LVIF_TEXT
| LVIF_IMAGE
| LVIF_PARAM
; /*set the mask*/
536 lvItem
.iItem
= ListView_GetItemCount(This
->hWndList
); /*add the item to the end of the list*/
538 lvItem
.lParam
= (LPARAM
) ILClone(ILFindLastID(pidl
)); /*set the item's data*/
539 lvItem
.pszText
= LPSTR_TEXTCALLBACKW
; /*get text on a callback basis*/
540 lvItem
.iImage
= I_IMAGECALLBACK
; /*get the image on a callback basis*/
541 if (SendMessageW(This
->hWndList
, LVM_INSERTITEMW
, 0, (LPARAM
)&lvItem
) == -1)
547 /**********************************************************
550 static BOOLEAN
LV_DeleteItem(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
554 TRACE("(%p)(pidl=%p)\n", This
, pidl
);
556 nIndex
= LV_FindItemByPidl(This
, ILFindLastID(pidl
));
557 return (-1==ListView_DeleteItem(This
->hWndList
, nIndex
))? FALSE
: TRUE
;
560 /**********************************************************
563 static BOOLEAN
LV_RenameItem(IShellViewImpl
* This
, LPCITEMIDLIST pidlOld
, LPCITEMIDLIST pidlNew
)
568 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This
, pidlOld
, pidlNew
);
570 nItem
= LV_FindItemByPidl(This
, ILFindLastID(pidlOld
));
573 lvItem
.mask
= LVIF_PARAM
; /* only the pidl */
574 lvItem
.iItem
= nItem
;
575 SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
577 SHFree((LPITEMIDLIST
)lvItem
.lParam
);
578 lvItem
.mask
= LVIF_PARAM
;
579 lvItem
.iItem
= nItem
;
580 lvItem
.lParam
= (LPARAM
) ILClone(ILFindLastID(pidlNew
)); /* set the item's data */
581 SendMessageW(This
->hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
582 SendMessageW(This
->hWndList
, LVM_UPDATE
, nItem
, 0);
583 return TRUE
; /* FIXME: better handling */
587 /**********************************************************
588 * ShellView_FillList()
590 * - gets the objectlist from the shellfolder
592 * - fills the list into the view
595 static INT CALLBACK
fill_list( LPVOID ptr
, LPVOID arg
)
597 LPITEMIDLIST pidl
= ptr
;
598 IShellViewImpl
*This
= arg
;
599 /* in a commdlg This works as a filemask*/
600 if ( IncludeObject(This
, pidl
)==S_OK
) LV_AddItem(This
, pidl
);
605 static HRESULT
ShellView_FillList(IShellViewImpl
* This
)
607 LPENUMIDLIST pEnumIDList
;
615 /* get the itemlist from the shfolder*/
616 hRes
= IShellFolder_EnumObjects(This
->pSFParent
,This
->hWnd
, SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
, &pEnumIDList
);
624 /* create a pointer array */
625 hdpa
= DPA_Create(16);
628 return(E_OUTOFMEMORY
);
631 /* copy the items into the array*/
632 while((S_OK
== IEnumIDList_Next(pEnumIDList
,1, &pidl
, &dwFetched
)) && dwFetched
)
634 if (DPA_InsertPtr(hdpa
, 0x7fff, pidl
) == -1)
641 DPA_Sort(hdpa
, ShellView_CompareItems
, (LPARAM
)This
->pSFParent
);
643 /*turn the listview's redrawing off*/
644 SendMessageA(This
->hWndList
, WM_SETREDRAW
, FALSE
, 0);
646 DPA_DestroyCallback( hdpa
, fill_list
, This
);
648 /*turn the listview's redrawing back on and force it to draw*/
649 SendMessageA(This
->hWndList
, WM_SETREDRAW
, TRUE
, 0);
651 IEnumIDList_Release(pEnumIDList
); /* destroy the list*/
656 /**********************************************************
657 * ShellView_OnCreate()
659 static LRESULT
ShellView_OnCreate(IShellViewImpl
* This
)
662 SHChangeNotifyEntry ntreg
;
663 IPersistFolder2
* ppf2
= NULL
;
667 if(ShellView_CreateList(This
))
669 if(ShellView_InitList(This
))
671 ShellView_FillList(This
);
675 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown
*)&This
->lpVtbl
, &IID_IDropTarget
, (LPVOID
*)&pdt
)))
677 RegisterDragDrop(This
->hWnd
, pdt
);
678 IDropTarget_Release(pdt
);
681 /* register for receiving notifications */
682 IShellFolder_QueryInterface(This
->pSFParent
, &IID_IPersistFolder2
, (LPVOID
*)&ppf2
);
685 IPersistFolder2_GetCurFolder(ppf2
, (LPITEMIDLIST
*)&ntreg
.pidl
);
686 ntreg
.fRecursive
= TRUE
;
687 This
->hNotify
= SHChangeNotifyRegister(This
->hWnd
, SHCNF_IDLIST
, SHCNE_ALLEVENTS
, SHV_CHANGE_NOTIFY
, 1, &ntreg
);
688 SHFree((LPITEMIDLIST
)ntreg
.pidl
);
689 IPersistFolder2_Release(ppf2
);
692 This
->hAccel
= LoadAcceleratorsA(shell32_hInstance
, "shv_accel");
697 /**********************************************************
698 * #### Handling of the menus ####
701 /**********************************************************
702 * ShellView_BuildFileMenu()
704 static HMENU
ShellView_BuildFileMenu(IShellViewImpl
* This
)
705 { WCHAR szText
[MAX_PATH
];
710 TRACE("(%p)\n",This
);
712 hSubMenu
= CreatePopupMenu();
714 { /*get the number of items in our global array*/
715 for(nTools
= 0; Tools
[nTools
].idCommand
!= -1; nTools
++){}
717 /*add the menu items*/
718 for(i
= 0; i
< nTools
; i
++)
720 LoadStringW(shell32_hInstance
, Tools
[i
].idMenuString
, szText
, MAX_PATH
);
722 ZeroMemory(&mii
, sizeof(mii
));
723 mii
.cbSize
= sizeof(mii
);
724 mii
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
726 if(BTNS_SEP
!= Tools
[i
].bStyle
) /* no separator*/
728 mii
.fType
= MFT_STRING
;
729 mii
.fState
= MFS_ENABLED
;
730 mii
.dwTypeData
= szText
;
731 mii
.wID
= Tools
[i
].idCommand
;
735 mii
.fType
= MFT_SEPARATOR
;
737 /* tack This item onto the end of the menu */
738 InsertMenuItemW(hSubMenu
, (UINT
)-1, TRUE
, &mii
);
741 TRACE("-- return (menu=%p)\n",hSubMenu
);
744 /**********************************************************
745 * ShellView_MergeFileMenu()
747 static void ShellView_MergeFileMenu(IShellViewImpl
* This
, HMENU hSubMenu
)
748 { TRACE("(%p)->(submenu=%p) stub\n",This
,hSubMenu
);
751 { /*insert This item at the beginning of the menu */
752 _InsertMenuItemW(hSubMenu
, 0, TRUE
, 0, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
753 _InsertMenuItemW(hSubMenu
, 0, TRUE
, IDM_MYFILEITEM
, MFT_STRING
, L
"dummy45", MFS_ENABLED
);
759 /**********************************************************
760 * ShellView_MergeViewMenu()
763 static void ShellView_MergeViewMenu(IShellViewImpl
* This
, HMENU hSubMenu
)
765 TRACE("(%p)->(submenu=%p)\n",This
,hSubMenu
);
768 { /*add a separator at the correct position in the menu*/
770 static WCHAR view
[] = L
"View";
772 _InsertMenuItemW(hSubMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
, FALSE
, 0, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
774 ZeroMemory(&mii
, sizeof(mii
));
775 mii
.cbSize
= sizeof(mii
);
776 mii
.fMask
= MIIM_SUBMENU
| MIIM_TYPE
| MIIM_DATA
;
777 mii
.fType
= MFT_STRING
;
778 mii
.dwTypeData
= view
;
779 mii
.hSubMenu
= LoadMenuW(shell32_hInstance
, L
"MENU_001");
780 InsertMenuItemW(hSubMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
, FALSE
, &mii
);
784 /**********************************************************
785 * ShellView_GetSelections()
787 * - fills the this->apidl list with the selected objects
790 * number of selected items
792 static UINT
ShellView_GetSelections(IShellViewImpl
* This
)
799 This
->cidl
= ListView_GetSelectedCount(This
->hWndList
);
800 This
->apidl
= (LPITEMIDLIST
*)SHAlloc(This
->cidl
* sizeof(LPITEMIDLIST
));
802 TRACE("selected=%i\n", This
->cidl
);
806 TRACE("-- Items selected =%u\n", This
->cidl
);
808 lvItem
.mask
= LVIF_STATE
| LVIF_PARAM
;
809 lvItem
.stateMask
= LVIS_SELECTED
;
813 while(SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
)&lvItem
) && (i
< This
->cidl
))
815 if(lvItem
.state
& LVIS_SELECTED
)
817 This
->apidl
[i
] = (LPITEMIDLIST
)lvItem
.lParam
;
821 TRACE("-- selected Item found\n");
830 /**********************************************************
831 * ShellView_OpenSelectedItems()
833 static HRESULT
ShellView_OpenSelectedItems(IShellViewImpl
* This
)
835 static UINT CF_IDLIST
= 0;
837 IDataObject
* selection
;
843 LPCITEMIDLIST parent_pidl
;
844 WCHAR parent_path
[MAX_PATH
];
845 LPCWSTR parent_dir
= NULL
;
848 CMINVOKECOMMANDINFOEX ici
;
851 if (0 == ShellView_GetSelections(This
))
856 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
,
857 (LPCITEMIDLIST
*)This
->apidl
, &IID_IContextMenu
,
862 hmenu
= CreatePopupMenu();
865 if (SUCCEEDED(IContextMenu_QueryContextMenu( cm
, hmenu
, 0, 0x20, 0x7fff, CMF_DEFAULTONLY
)))
867 INT def
= -1, n
= GetMenuItemCount(hmenu
);
869 for ( i
= 0; i
< n
; i
++ )
871 memset( &info
, 0, sizeof info
);
872 info
.cbSize
= sizeof info
;
873 info
.fMask
= MIIM_FTYPE
| MIIM_STATE
| MIIM_ID
;
874 if (GetMenuItemInfoW( hmenu
, i
, TRUE
, &info
))
876 if (info
.fState
& MFS_DEFAULT
)
885 memset( &ici
, 0, sizeof ici
);
886 ici
.cbSize
= sizeof ici
;
887 ici
.lpVerb
= MAKEINTRESOURCEA( def
);
888 ici
.hwnd
= This
->hWnd
;
890 if (IContextMenu_InvokeCommand(cm
, (LPCMINVOKECOMMANDINFO
) &ici
) == S_OK
)
892 IContextMenu_Release(cm
);
893 DestroyMenu( hmenu
);
899 DestroyMenu( hmenu
);
901 IContextMenu_Release(cm
);
906 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
,
907 (LPCITEMIDLIST
*)This
->apidl
, &IID_IDataObject
,
908 0, (LPVOID
*)&selection
);
917 CF_IDLIST
= RegisterClipboardFormatW(CFSTR_SHELLIDLIST
);
919 fetc
.cfFormat
= CF_IDLIST
;
921 fetc
.dwAspect
= DVASPECT_CONTENT
;
923 fetc
.tymed
= TYMED_HGLOBAL
;
925 hr
= IDataObject_QueryGetData(selection
, &fetc
);
929 hr
= IDataObject_GetData(selection
, &fetc
, &stgm
);
933 pIDList
= GlobalLock(stgm
.u
.hGlobal
);
935 parent_pidl
= (LPCITEMIDLIST
) ((LPBYTE
)pIDList
+pIDList
->aoffset
[0]);
936 hr
= IShellFolder_GetAttributesOf(This
->pSFParent
, 1, &parent_pidl
, &attribs
);
937 if (SUCCEEDED(hr
) && (attribs
& SFGAO_FILESYSTEM
) &&
938 SHGetPathFromIDListW(parent_pidl
, parent_path
))
940 parent_dir
= parent_path
;
943 for (i
= pIDList
->cidl
; i
> 0; --i
)
947 pidl
= (LPCITEMIDLIST
)((LPBYTE
)pIDList
+pIDList
->aoffset
[i
]);
949 attribs
= SFGAO_FOLDER
;
950 hr
= IShellFolder_GetAttributesOf(This
->pSFParent
, 1, &pidl
, &attribs
);
952 if (SUCCEEDED(hr
) && ! (attribs
& SFGAO_FOLDER
))
954 SHELLEXECUTEINFOW shexinfo
;
956 shexinfo
.cbSize
= sizeof(SHELLEXECUTEINFOW
);
957 shexinfo
.fMask
= SEE_MASK_INVOKEIDLIST
; /* SEE_MASK_IDLIST is also possible. */
958 shexinfo
.hwnd
= NULL
;
959 shexinfo
.lpVerb
= NULL
;
960 shexinfo
.lpFile
= NULL
;
961 shexinfo
.lpParameters
= NULL
;
962 shexinfo
.lpDirectory
= parent_dir
;
963 shexinfo
.nShow
= SW_NORMAL
;
964 shexinfo
.lpIDList
= ILCombine(parent_pidl
, pidl
);
966 ShellExecuteExW(&shexinfo
); /* Discard error/success info */
968 ILFree((LPITEMIDLIST
)shexinfo
.lpIDList
);
972 GlobalUnlock(stgm
.u
.hGlobal
);
973 ReleaseStgMedium(&stgm
);
975 IDataObject_Release(selection
);
980 /**********************************************************
981 * ShellView_DoContextMenu()
983 static void ShellView_DoContextMenu(IShellViewImpl
* This
, WORD x
, WORD y
, BOOL bDefault
)
987 BOOL fExplore
= FALSE
;
989 CMINVOKECOMMANDINFO cmi
;
991 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This
, x
, y
, bDefault
);
993 /* look, what's selected and create a context menu object of it*/
994 if( ShellView_GetSelections(This
) )
996 IShellFolder_GetUIObjectOf( This
->pSFParent
, This
->hWndParent
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
,
997 (REFIID
)&IID_IContextMenu
, NULL
, (LPVOID
*)&This
->pCM
);
1001 TRACE("-- pContextMenu\n");
1002 hMenu
= CreatePopupMenu();
1006 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
1007 if(SUCCEEDED(IShellBrowser_GetControlWindow(This
->pShellBrowser
,FCW_TREE
, &hwndTree
)) && hwndTree
)
1009 TRACE("-- explore mode\n");
1013 /* build the flags depending on what we can do with the selected item */
1014 wFlags
= CMF_NORMAL
| (This
->cidl
!= 1 ? 0 : CMF_CANRENAME
) | (fExplore
? CMF_EXPLORE
: 0);
1016 /* let the ContextMenu merge its items in */
1017 if (SUCCEEDED(IContextMenu_QueryContextMenu( This
->pCM
, hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, wFlags
)))
1019 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
)
1020 SetMenuDefaultItem(hMenu
, FCIDM_SHVIEW_OPEN
, MF_BYCOMMAND
);
1024 TRACE("-- get menu default command\n");
1025 uCommand
= GetMenuDefaultItem(hMenu
, FALSE
, GMDI_GOINTOPOPUPS
);
1029 TRACE("-- track popup\n");
1030 uCommand
= TrackPopupMenu( hMenu
,TPM_LEFTALIGN
| TPM_RETURNCMD
,x
,y
,0,This
->hWnd
,NULL
);
1035 TRACE("-- uCommand=%u\n", uCommand
);
1036 if (uCommand
==FCIDM_SHVIEW_OPEN
&& IsInCommDlg(This
))
1038 TRACE("-- dlg: OnDefaultCommand\n");
1039 if (OnDefaultCommand(This
) != S_OK
)
1041 ShellView_OpenSelectedItems(This
);
1046 TRACE("-- explore -- invoke command\n");
1047 ZeroMemory(&cmi
, sizeof(cmi
));
1048 cmi
.cbSize
= sizeof(cmi
);
1049 cmi
.hwnd
= This
->hWndParent
; /* this window has to answer CWM_GETISHELLBROWSER */
1050 cmi
.lpVerb
= (LPCSTR
)MAKEINTRESOURCEA(uCommand
);
1051 IContextMenu_InvokeCommand(This
->pCM
, &cmi
);
1059 IContextMenu_Release(This
->pCM
);
1064 else /* background context menu */
1066 hMenu
= CreatePopupMenu();
1068 CDefFolderMenu_Create2(NULL
, NULL
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, This
->pSFParent
, NULL
, 0, NULL
, (IContextMenu
**)&This
->pCM
);
1069 IContextMenu2_QueryContextMenu(This
->pCM
, hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, 0);
1071 uCommand
= TrackPopupMenu( hMenu
, TPM_LEFTALIGN
| TPM_RETURNCMD
,x
,y
,0,This
->hWnd
,NULL
);
1074 TRACE("-- (%p)->(uCommand=0x%08x )\n",This
, uCommand
);
1076 ZeroMemory(&cmi
, sizeof(cmi
));
1077 cmi
.cbSize
= sizeof(cmi
);
1078 cmi
.lpVerb
= (LPCSTR
)MAKEINTRESOURCEA(uCommand
);
1079 cmi
.hwnd
= This
->hWndParent
;
1080 IContextMenu2_InvokeCommand(This
->pCM
, &cmi
);
1082 IContextMenu2_Release(This
->pCM
);
1087 /**********************************************************
1088 * ##### message handling #####
1091 /**********************************************************
1092 * ShellView_OnSize()
1094 static LRESULT
ShellView_OnSize(IShellViewImpl
* This
, WORD wWidth
, WORD wHeight
)
1096 TRACE("%p width=%u height=%u\n",This
, wWidth
,wHeight
);
1098 /*resize the ListView to fit our window*/
1101 MoveWindow(This
->hWndList
, 0, 0, wWidth
, wHeight
, TRUE
);
1106 /**********************************************************
1107 * ShellView_OnDeactivate()
1112 static void ShellView_OnDeactivate(IShellViewImpl
* This
)
1116 if(This
->uState
!= SVUIA_DEACTIVATE
)
1120 IShellBrowser_SetMenuSB(This
->pShellBrowser
,0, 0, 0);
1121 IShellBrowser_RemoveMenusSB(This
->pShellBrowser
,This
->hMenu
);
1122 DestroyMenu(This
->hMenu
);
1126 This
->uState
= SVUIA_DEACTIVATE
;
1130 /**********************************************************
1131 * ShellView_OnActivate()
1133 static LRESULT
ShellView_OnActivate(IShellViewImpl
* This
, UINT uState
)
1134 { OLEMENUGROUPWIDTHS omw
= { {0, 0, 0, 0, 0, 0} };
1136 CHAR szText
[MAX_PATH
];
1138 TRACE("%p uState=%x\n",This
,uState
);
1140 /*don't do anything if the state isn't really changing */
1141 if(This
->uState
== uState
)
1146 ShellView_OnDeactivate(This
);
1148 /*only do This if we are active */
1149 if(uState
!= SVUIA_DEACTIVATE
)
1151 /*merge the menus */
1152 This
->hMenu
= CreateMenu();
1156 IShellBrowser_InsertMenusSB(This
->pShellBrowser
, This
->hMenu
, &omw
);
1157 TRACE("-- after fnInsertMenusSB\n");
1159 /*build the top level menu get the menu item's text*/
1160 strcpy(szText
,"dummy 31");
1162 ZeroMemory(&mii
, sizeof(mii
));
1163 mii
.cbSize
= sizeof(mii
);
1164 mii
.fMask
= MIIM_SUBMENU
| MIIM_TYPE
| MIIM_STATE
;
1165 mii
.fType
= MFT_STRING
;
1166 mii
.fState
= MFS_ENABLED
;
1167 mii
.dwTypeData
= szText
;
1168 mii
.hSubMenu
= ShellView_BuildFileMenu(This
);
1170 /*insert our menu into the menu bar*/
1173 InsertMenuItemA(This
->hMenu
, FCIDM_MENU_HELP
, FALSE
, &mii
);
1176 /*get the view menu so we can merge with it*/
1177 ZeroMemory(&mii
, sizeof(mii
));
1178 mii
.cbSize
= sizeof(mii
);
1179 mii
.fMask
= MIIM_SUBMENU
;
1181 if(GetMenuItemInfoA(This
->hMenu
, FCIDM_MENU_VIEW
, FALSE
, &mii
))
1183 ShellView_MergeViewMenu(This
, mii
.hSubMenu
);
1186 /*add the items that should only be added if we have the focus*/
1187 if(SVUIA_ACTIVATE_FOCUS
== uState
)
1189 /*get the file menu so we can merge with it */
1190 ZeroMemory(&mii
, sizeof(mii
));
1191 mii
.cbSize
= sizeof(mii
);
1192 mii
.fMask
= MIIM_SUBMENU
;
1194 if(GetMenuItemInfoA(This
->hMenu
, FCIDM_MENU_FILE
, FALSE
, &mii
))
1196 ShellView_MergeFileMenu(This
, mii
.hSubMenu
);
1199 TRACE("-- before fnSetMenuSB\n");
1200 IShellBrowser_SetMenuSB(This
->pShellBrowser
, This
->hMenu
, 0, This
->hWnd
);
1203 This
->uState
= uState
;
1208 /**********************************************************
1209 * ShellView_OnSetFocus()
1212 static LRESULT
ShellView_OnSetFocus(IShellViewImpl
* This
)
1216 /* Tell the browser one of our windows has received the focus. This
1217 should always be done before merging menus (OnActivate merges the
1218 menus) if one of our windows has the focus.*/
1220 IShellBrowser_OnViewWindowActive(This
->pShellBrowser
,(IShellView
*) This
);
1221 ShellView_OnActivate(This
, SVUIA_ACTIVATE_FOCUS
);
1223 /* Set the focus to the listview */
1224 SetFocus(This
->hWndList
);
1226 /* Notify the ICommDlgBrowser interface */
1227 OnStateChange(This
,CDBOSC_SETFOCUS
);
1232 /**********************************************************
1233 * ShellView_OnKillFocus()
1235 static LRESULT
ShellView_OnKillFocus(IShellViewImpl
* This
)
1237 TRACE("(%p) stub\n",This
);
1239 ShellView_OnActivate(This
, SVUIA_ACTIVATE_NOFOCUS
);
1240 /* Notify the ICommDlgBrowser */
1241 OnStateChange(This
,CDBOSC_KILLFOCUS
);
1246 /**********************************************************
1247 * ShellView_OnCommand()
1250 * the CmdID's are the ones from the context menu
1252 static LRESULT
ShellView_OnCommand(IShellViewImpl
* This
,DWORD dwCmdID
, DWORD dwCmd
, HWND hwndCmd
)
1254 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",This
, dwCmdID
, dwCmd
, hwndCmd
);
1258 case FCIDM_SHVIEW_SMALLICON
:
1259 This
->FolderSettings
.ViewMode
= FVM_SMALLICON
;
1260 SetStyle (This
, LVS_SMALLICON
, LVS_TYPEMASK
);
1264 case FCIDM_SHVIEW_BIGICON
:
1265 This
->FolderSettings
.ViewMode
= FVM_ICON
;
1266 SetStyle (This
, LVS_ICON
, LVS_TYPEMASK
);
1270 case FCIDM_SHVIEW_LISTVIEW
:
1271 This
->FolderSettings
.ViewMode
= FVM_LIST
;
1272 SetStyle (This
, LVS_LIST
, LVS_TYPEMASK
);
1276 case FCIDM_SHVIEW_REPORTVIEW
:
1277 This
->FolderSettings
.ViewMode
= FVM_DETAILS
;
1278 SetStyle (This
, LVS_REPORT
, LVS_TYPEMASK
);
1282 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1287 This
->ListViewSortInfo
.nHeaderID
= (LPARAM
) (dwCmdID
- 0x30);
1288 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
1289 This
->ListViewSortInfo
.nLastHeaderID
= This
->ListViewSortInfo
.nHeaderID
;
1290 SendMessageA(This
->hWndList
, LVM_SORTITEMS
, (WPARAM
) &This
->ListViewSortInfo
, (LPARAM
)ShellView_ListViewCompareItems
);
1294 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID
);
1299 /**********************************************************
1300 * ShellView_OnNotify()
1303 static LRESULT
ShellView_OnNotify(IShellViewImpl
* This
, UINT CtlID
, LPNMHDR lpnmh
)
1304 { LPNMLISTVIEW lpnmlv
= (LPNMLISTVIEW
)lpnmh
;
1305 NMLVDISPINFOW
*lpdi
= (NMLVDISPINFOW
*)lpnmh
;
1308 TRACE("%p CtlID=%u lpnmh->code=%x\n",This
,CtlID
,lpnmh
->code
);
1313 TRACE("-- NM_SETFOCUS %p\n",This
);
1314 ShellView_OnSetFocus(This
);
1318 TRACE("-- NM_KILLFOCUS %p\n",This
);
1319 ShellView_OnDeactivate(This
);
1320 /* Notify the ICommDlgBrowser interface */
1321 OnStateChange(This
,CDBOSC_KILLFOCUS
);
1325 TRACE("-- NM_CUSTOMDRAW %p\n",This
);
1326 return CDRF_DODEFAULT
;
1328 case NM_RELEASEDCAPTURE
:
1329 TRACE("-- NM_RELEASEDCAPTURE %p\n",This
);
1333 TRACE("-- NM_CLICK %p\n",This
);
1337 TRACE("-- NM_RCLICK %p\n",This
);
1341 TRACE("-- NM_DBLCLK %p\n",This
);
1342 if (OnDefaultCommand(This
) != S_OK
) ShellView_OpenSelectedItems(This
);
1346 TRACE("-- NM_RETURN %p\n",This
);
1347 if (OnDefaultCommand(This
) != S_OK
) ShellView_OpenSelectedItems(This
);
1351 TRACE("-- HDN_ENDTRACKW %p\n",This
);
1352 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1353 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1356 case LVN_DELETEITEM
:
1357 TRACE("-- LVN_DELETEITEM %p\n",This
);
1358 SHFree((LPITEMIDLIST
)lpnmlv
->lParam
); /*delete the pidl because we made a copy of it*/
1361 case LVN_DELETEALLITEMS
:
1362 TRACE("-- LVN_DELETEALLITEMS %p\n",This
);
1365 case LVN_INSERTITEM
:
1366 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This
);
1369 case LVN_ITEMACTIVATE
:
1370 TRACE("-- LVN_ITEMACTIVATE %p\n",This
);
1371 OnStateChange(This
, CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1374 case LVN_COLUMNCLICK
:
1375 This
->ListViewSortInfo
.nHeaderID
= lpnmlv
->iSubItem
;
1376 if(This
->ListViewSortInfo
.nLastHeaderID
== This
->ListViewSortInfo
.nHeaderID
)
1378 This
->ListViewSortInfo
.bIsAscending
= !This
->ListViewSortInfo
.bIsAscending
;
1382 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
1384 This
->ListViewSortInfo
.nLastHeaderID
= This
->ListViewSortInfo
.nHeaderID
;
1386 SendMessageW(lpnmlv
->hdr
.hwndFrom
, LVM_SORTITEMS
, (WPARAM
) &This
->ListViewSortInfo
, (LPARAM
)ShellView_ListViewCompareItems
);
1389 case LVN_GETDISPINFOA
:
1390 case LVN_GETDISPINFOW
:
1391 TRACE("-- LVN_GETDISPINFO %p\n",This
);
1392 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1394 if(lpdi
->item
.mask
& LVIF_TEXT
) /* text requested */
1396 if (This
->pSF2Parent
)
1399 IShellFolder2_GetDetailsOf(This
->pSF2Parent
, pidl
, lpdi
->item
.iSubItem
, &sd
);
1400 if (lpnmh
->code
== LVN_GETDISPINFOA
)
1402 /* shouldn't happen */
1403 NMLVDISPINFOA
*lpdiA
= (NMLVDISPINFOA
*)lpnmh
;
1404 StrRetToStrNA( lpdiA
->item
.pszText
, lpdiA
->item
.cchTextMax
, &sd
.str
, NULL
);
1405 TRACE("-- text=%s\n",lpdiA
->item
.pszText
);
1407 else /* LVN_GETDISPINFOW */
1409 StrRetToStrNW( lpdi
->item
.pszText
, lpdi
->item
.cchTextMax
, &sd
.str
, NULL
);
1410 TRACE("-- text=%s\n",debugstr_w(lpdi
->item
.pszText
));
1418 if(lpdi
->item
.mask
& LVIF_IMAGE
) /* image requested */
1420 lpdi
->item
.iImage
= SHMapPIDLToSystemImageListIndex(This
->pSFParent
, pidl
, 0);
1424 case LVN_ITEMCHANGED
:
1425 TRACE("-- LVN_ITEMCHANGED %p\n",This
);
1426 OnStateChange(This
, CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1430 case LVN_BEGINRDRAG
:
1431 TRACE("-- LVN_BEGINDRAG\n");
1433 if (ShellView_GetSelections(This
))
1436 DWORD dwAttributes
= SFGAO_CANLINK
;
1437 DWORD dwEffect
= DROPEFFECT_COPY
| DROPEFFECT_MOVE
;
1439 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, &IID_IDataObject
,0,(LPVOID
*)&pda
)))
1441 IDropSource
* pds
= (IDropSource
*)&(This
->lpvtblDropSource
); /* own DropSource interface */
1443 if (SUCCEEDED(IShellFolder_GetAttributesOf(This
->pSFParent
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, &dwAttributes
)))
1445 if (dwAttributes
& SFGAO_CANLINK
)
1447 dwEffect
|= DROPEFFECT_LINK
;
1454 DoDragDrop(pda
, pds
, dwEffect
, &dwEffect2
);
1456 IDataObject_Release(pda
);
1461 case LVN_BEGINLABELEDITW
:
1463 DWORD dwAttr
= SFGAO_CANRENAME
;
1464 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1466 TRACE("-- LVN_BEGINLABELEDITW %p\n",This
);
1468 IShellFolder_GetAttributesOf(This
->pSFParent
, 1, (LPCITEMIDLIST
*)&pidl
, &dwAttr
);
1469 if (SFGAO_CANRENAME
& dwAttr
)
1476 case LVN_ENDLABELEDITW
:
1478 TRACE("-- LVN_ENDLABELEDITA %p\n",This
);
1479 if (lpdi
->item
.pszText
)
1484 lvItem
.iItem
= lpdi
->item
.iItem
;
1485 lvItem
.iSubItem
= 0;
1486 lvItem
.mask
= LVIF_PARAM
;
1487 SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
1489 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1490 hr
= IShellFolder_SetNameOf(This
->pSFParent
, 0, pidl
, lpdi
->item
.pszText
, SHGDN_INFOLDER
, &pidl
);
1492 if(SUCCEEDED(hr
) && pidl
)
1494 lvItem
.mask
= LVIF_PARAM
;
1495 lvItem
.lParam
= (LPARAM
)pidl
;
1496 SendMessageW(This
->hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
1506 msg.hwnd = This->hWnd;
1507 msg.message = WM_KEYDOWN;
1508 msg.wParam = plvKeyDown->wVKey;
1513 LPNMLVKEYDOWN plvKeyDown
= (LPNMLVKEYDOWN
) lpnmh
;
1515 /* initiate a rename of the selected file or directory */
1516 if(plvKeyDown
->wVKey
== VK_F2
)
1518 /* see how many files are selected */
1519 int i
= ListView_GetSelectedCount(This
->hWndList
);
1521 /* get selected item */
1524 /* get selected item */
1525 i
= ListView_GetNextItem(This
->hWndList
, -1,
1528 SendMessageW(This
->hWndList
, LVM_ENSUREVISIBLE
, i
, 0);
1529 SendMessageW(This
->hWndList
, LVM_EDITLABELW
, i
, 0);
1533 TranslateAccelerator(This
->hWnd
, This
->hAccel
, &msg
)
1535 else if(plvKeyDown
->wVKey
== VK_DELETE
)
1540 LPITEMIDLIST
* pItems
;
1543 IShellFolder_QueryInterface(This
->pSFParent
, &IID_ISFHelper
,
1549 if(!(i
= ListView_GetSelectedCount(This
->hWndList
)))
1552 /* allocate memory for the pidl array */
1553 pItems
= HeapAlloc(GetProcessHeap(), 0,
1554 sizeof(LPITEMIDLIST
) * i
);
1556 /* retrieve all selected items */
1559 while(ListView_GetSelectedCount(This
->hWndList
) > i
)
1561 /* get selected item */
1562 item_index
= ListView_GetNextItem(This
->hWndList
,
1563 item_index
, LVNI_SELECTED
);
1564 item
.iItem
= item_index
;
1565 item
.mask
= LVIF_PARAM
;
1566 SendMessageA(This
->hWndList
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1569 pItems
[i
] = (LPITEMIDLIST
)item
.lParam
;
1574 /* perform the item deletion */
1575 ISFHelper_DeleteItems(psfhlp
, i
, (LPCITEMIDLIST
*)pItems
);
1577 /* free pidl array memory */
1578 HeapFree(GetProcessHeap(), 0, pItems
);
1581 /* Initiate a refresh */
1582 else if(plvKeyDown
->wVKey
== VK_F5
)
1584 IShellView_Refresh((IShellView
*)This
);
1586 else if(plvKeyDown
->wVKey
== VK_BACK
)
1588 LPSHELLBROWSER lpSb
;
1589 if((lpSb
= (LPSHELLBROWSER
)SendMessageW(This
->hWndParent
, CWM_GETISHELLBROWSER
, 0, 0)))
1591 IShellBrowser_BrowseObject(lpSb
, NULL
, SBSP_PARENT
);
1595 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown
->wVKey
);
1600 TRACE("-- %p WM_COMMAND %x unhandled\n", This
, lpnmh
->code
);
1606 /**********************************************************
1607 * ShellView_OnChange()
1610 static LRESULT
ShellView_OnChange(IShellViewImpl
* This
, LPITEMIDLIST
* Pidls
, LONG wEventId
)
1613 TRACE("(%p)(%p,%p,0x%08x)\n", This
, Pidls
[0], Pidls
[1], wEventId
);
1618 LV_AddItem(This
, Pidls
[0]);
1622 LV_DeleteItem(This
, Pidls
[0]);
1624 case SHCNE_RENAMEFOLDER
:
1625 case SHCNE_RENAMEITEM
:
1626 LV_RenameItem(This
, Pidls
[0], Pidls
[1]);
1628 case SHCNE_UPDATEITEM
:
1634 /**********************************************************
1635 * ShellView_DoMeasureItem
1638 static LRESULT
ShellView_DoCustomItem(IShellViewImpl
* pThis
, HWND hWnd
, UINT uMsg
, LPARAM lParam
)
1643 ERR("no menu!!!\n");
1647 if (pThis
->pCM
->lpVtbl
->HandleMenuMsg(pThis
->pCM
, uMsg
, (WPARAM
)hWnd
, lParam
) == S_OK
)
1653 /**********************************************************
1657 static LRESULT CALLBACK
ShellView_WndProc(HWND hWnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
)
1659 IShellViewImpl
* pThis
= (IShellViewImpl
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
1660 LPCREATESTRUCTW lpcs
;
1662 TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd
, uMessage
, wParam
, lParam
);
1667 lpcs
= (LPCREATESTRUCTW
)lParam
;
1668 pThis
= (IShellViewImpl
*)(lpcs
->lpCreateParams
);
1669 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (ULONG_PTR
)pThis
);
1670 pThis
->hWnd
= hWnd
; /*set the window handle*/
1673 case WM_SIZE
: return ShellView_OnSize(pThis
,LOWORD(lParam
), HIWORD(lParam
));
1674 case WM_SETFOCUS
: return ShellView_OnSetFocus(pThis
);
1675 case WM_KILLFOCUS
: return ShellView_OnKillFocus(pThis
);
1676 case WM_CREATE
: return ShellView_OnCreate(pThis
);
1677 case WM_ACTIVATE
: return ShellView_OnActivate(pThis
, SVUIA_ACTIVATE_FOCUS
);
1678 case WM_NOTIFY
: return ShellView_OnNotify(pThis
,(UINT
)wParam
, (LPNMHDR
)lParam
);
1679 case WM_COMMAND
: return ShellView_OnCommand(pThis
,
1680 GET_WM_COMMAND_ID(wParam
, lParam
),
1681 GET_WM_COMMAND_CMD(wParam
, lParam
),
1682 GET_WM_COMMAND_HWND(wParam
, lParam
));
1683 case SHV_CHANGE_NOTIFY
: return ShellView_OnChange(pThis
, (LPITEMIDLIST
*)wParam
, (LONG
)lParam
);
1685 case WM_CONTEXTMENU
: ShellView_DoContextMenu(pThis
, LOWORD(lParam
), HIWORD(lParam
), FALSE
);
1688 case WM_MEASUREITEM
:
1689 return ShellView_DoCustomItem(pThis
, hWnd
, uMessage
, lParam
);
1691 case WM_SHOWWINDOW
: UpdateWindow(pThis
->hWndList
);
1694 case WM_GETDLGCODE
: return SendMessageA(pThis
->hWndList
,uMessage
,0,0);
1697 RevokeDragDrop(pThis
->hWnd
);
1698 SHChangeNotifyDeregister(pThis
->hNotify
);
1702 if ((pThis
->FolderSettings
.fFlags
& FWF_DESKTOP
) ||
1703 (pThis
->FolderSettings
.fFlags
& FWF_TRANSPARENT
))
1706 case CWM_GETISHELLBROWSER
:
1707 return (LRESULT
)pThis
->pShellBrowser
;
1709 return DefWindowProcW(hWnd
, uMessage
, wParam
, lParam
);
1711 /**********************************************************
1714 * The INTERFACE of the IShellView object
1717 **********************************************************
1718 * IShellView_QueryInterface
1720 static HRESULT WINAPI
IShellView_fnQueryInterface(IShellView
* iface
,REFIID riid
, LPVOID
*ppvObj
)
1722 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1724 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
1728 if(IsEqualIID(riid
, &IID_IUnknown
))
1732 else if(IsEqualIID(riid
, &IID_IShellView
))
1734 *ppvObj
= (IShellView
*)This
;
1736 else if(IsEqualIID(riid
, &IID_IOleCommandTarget
))
1738 *ppvObj
= (IOleCommandTarget
*)&(This
->lpvtblOleCommandTarget
);
1740 else if(IsEqualIID(riid
, &IID_IDropTarget
))
1742 *ppvObj
= (IDropTarget
*)&(This
->lpvtblDropTarget
);
1744 else if(IsEqualIID(riid
, &IID_IDropSource
))
1746 *ppvObj
= (IDropSource
*)&(This
->lpvtblDropSource
);
1748 else if(IsEqualIID(riid
, &IID_IViewObject
))
1750 *ppvObj
= (IViewObject
*)&(This
->lpvtblViewObject
);
1755 IUnknown_AddRef( (IUnknown
*)*ppvObj
);
1756 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
1759 TRACE("-- Interface: E_NOINTERFACE\n");
1760 return E_NOINTERFACE
;
1763 /**********************************************************
1766 static ULONG WINAPI
IShellView_fnAddRef(IShellView
* iface
)
1768 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1769 ULONG refCount
= InterlockedIncrement(&This
->ref
);
1771 TRACE("(%p)->(count=%u)\n", This
, refCount
- 1);
1775 /**********************************************************
1776 * IShellView_Release
1778 static ULONG WINAPI
IShellView_fnRelease(IShellView
* iface
)
1780 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1781 ULONG refCount
= InterlockedDecrement(&This
->ref
);
1783 TRACE("(%p)->(count=%i)\n", This
, refCount
+ 1);
1787 TRACE(" destroying IShellView(%p)\n",This
);
1789 DestroyWindow(This
->hWndList
);
1792 IShellFolder_Release(This
->pSFParent
);
1794 if(This
->pSF2Parent
)
1795 IShellFolder2_Release(This
->pSF2Parent
);
1797 SHFree(This
->apidl
);
1800 IAdviseSink_Release(This
->pAdvSink
);
1803 IContextMenu_Release(This
->pCM
);
1805 HeapFree(GetProcessHeap(),0,This
);
1810 /**********************************************************
1811 * ShellView_GetWindow
1813 static HRESULT WINAPI
IShellView_fnGetWindow(IShellView
* iface
,HWND
* phWnd
)
1815 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1817 TRACE("(%p)\n",This
);
1819 *phWnd
= This
->hWnd
;
1824 static HRESULT WINAPI
IShellView_fnContextSensitiveHelp(IShellView
* iface
,BOOL fEnterMode
)
1826 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1828 FIXME("(%p) stub\n",This
);
1833 /**********************************************************
1834 * IShellView_TranslateAccelerator
1837 * use the accel functions
1839 static HRESULT WINAPI
IShellView_fnTranslateAccelerator(IShellView
* iface
,LPMSG lpmsg
)
1842 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1844 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This
,lpmsg
, lpmsg
->hwnd
, lpmsg
->message
, lpmsg
->lParam
, lpmsg
->wParam
);
1847 if ((lpmsg
->message
>=WM_KEYFIRST
) && (lpmsg
->message
>=WM_KEYLAST
))
1849 TRACE("-- key=0x04%lx\n",lpmsg
->wParam
) ;
1851 return S_FALSE
; /* not handled */
1854 static HRESULT WINAPI
IShellView_fnEnableModeless(IShellView
* iface
,BOOL fEnable
)
1856 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1858 FIXME("(%p) stub\n",This
);
1863 static HRESULT WINAPI
IShellView_fnUIActivate(IShellView
* iface
,UINT uState
)
1865 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1868 CHAR szName[MAX_PATH];
1871 int nPartArray
[1] = {-1};
1873 TRACE("(%p)->(state=%x) stub\n",This
, uState
);
1875 /*don't do anything if the state isn't really changing*/
1876 if(This
->uState
== uState
)
1881 /*OnActivate handles the menu merging and internal state*/
1882 ShellView_OnActivate(This
, uState
);
1884 /*only do This if we are active*/
1885 if(uState
!= SVUIA_DEACTIVATE
)
1889 GetFolderPath is not a method of IShellFolder
1890 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1892 /* set the number of parts */
1893 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_STATUS
, SB_SETPARTS
, 1,
1894 (LPARAM
)nPartArray
, &lResult
);
1896 /* set the text for the parts */
1898 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1899 0, (LPARAM)szName, &lResult);
1906 static HRESULT WINAPI
IShellView_fnRefresh(IShellView
* iface
)
1908 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1910 TRACE("(%p)\n",This
);
1912 SendMessageW(This
->hWndList
, LVM_DELETEALLITEMS
, 0, 0);
1913 ShellView_FillList(This
);
1918 static HRESULT WINAPI
IShellView_fnCreateViewWindow(
1920 IShellView
*lpPrevView
,
1921 LPCFOLDERSETTINGS lpfs
,
1922 IShellBrowser
* psb
,
1926 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1932 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This
, lpPrevView
,lpfs
, psb
, prcView
, phWnd
);
1933 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
);
1935 /*set up the member variables*/
1936 This
->pShellBrowser
= psb
;
1937 This
->FolderSettings
= *lpfs
;
1939 /*get our parent window*/
1940 IShellBrowser_AddRef(This
->pShellBrowser
);
1941 IShellBrowser_GetWindow(This
->pShellBrowser
, &(This
->hWndParent
));
1943 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1944 This
->pCommDlgBrowser
=NULL
;
1945 if ( SUCCEEDED (IShellBrowser_QueryInterface( This
->pShellBrowser
,
1946 (REFIID
)&IID_ICommDlgBrowser
, (LPVOID
*) &This
->pCommDlgBrowser
)))
1948 TRACE("-- CommDlgBrowser\n");
1951 /*if our window class has not been registered, then do so*/
1952 if(!GetClassInfoW(shell32_hInstance
, SV_CLASS_NAME
, &wc
))
1954 ZeroMemory(&wc
, sizeof(wc
));
1955 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1956 wc
.lpfnWndProc
= ShellView_WndProc
;
1959 wc
.hInstance
= shell32_hInstance
;
1961 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1962 wc
.hbrBackground
= (HBRUSH
) (COLOR_BACKGROUND
+1);
1963 wc
.lpszMenuName
= NULL
;
1964 wc
.lpszClassName
= SV_CLASS_NAME
;
1966 if(!RegisterClassW(&wc
))
1970 *phWnd
= CreateWindowExW(0,
1973 WS_CHILD
| WS_TABSTOP
,
1976 prcView
->right
- prcView
->left
,
1977 prcView
->bottom
- prcView
->top
,
1985 if(!*phWnd
) return E_FAIL
;
1987 SetWindowPos(*phWnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_SHOWWINDOW
);
1988 UpdateWindow(*phWnd
);
1993 static HRESULT WINAPI
IShellView_fnDestroyViewWindow(IShellView
* iface
)
1995 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1997 TRACE("(%p)\n",This
);
1999 /*Make absolutely sure all our UI is cleaned up.*/
2000 IShellView_UIActivate((IShellView
*)This
, SVUIA_DEACTIVATE
);
2004 DestroyMenu(This
->hMenu
);
2007 DestroyWindow(This
->hWnd
);
2008 if(This
->pShellBrowser
) IShellBrowser_Release(This
->pShellBrowser
);
2009 if(This
->pCommDlgBrowser
) ICommDlgBrowser_Release(This
->pCommDlgBrowser
);
2015 static HRESULT WINAPI
IShellView_fnGetCurrentInfo(IShellView
* iface
, LPFOLDERSETTINGS lpfs
)
2017 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2019 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This
, lpfs
,
2020 This
->FolderSettings
.ViewMode
, This
->FolderSettings
.fFlags
);
2022 if (!lpfs
) return E_INVALIDARG
;
2024 *lpfs
= This
->FolderSettings
;
2028 static HRESULT WINAPI
IShellView_fnAddPropertySheetPages(IShellView
* iface
, DWORD dwReserved
,LPFNADDPROPSHEETPAGE lpfn
, LPARAM lparam
)
2030 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2032 FIXME("(%p) stub\n",This
);
2037 static HRESULT WINAPI
IShellView_fnSaveViewState(IShellView
* iface
)
2039 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2041 FIXME("(%p) stub\n",This
);
2046 static HRESULT WINAPI
IShellView_fnSelectItem(
2051 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2054 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This
, pidl
, uFlags
);
2056 i
= LV_FindItemByPidl(This
, pidl
);
2062 if(uFlags
& SVSI_ENSUREVISIBLE
)
2063 SendMessageW(This
->hWndList
, LVM_ENSUREVISIBLE
, i
, 0);
2065 lvItem
.mask
= LVIF_STATE
;
2066 lvItem
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
2068 lvItem
.iSubItem
= 0;
2070 while(SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
))
2072 if (lvItem
.iItem
== i
)
2074 if (uFlags
& SVSI_SELECT
)
2075 lvItem
.state
|= LVIS_SELECTED
;
2077 lvItem
.state
&= ~LVIS_SELECTED
;
2079 if(uFlags
& SVSI_FOCUSED
)
2080 lvItem
.state
&= ~LVIS_FOCUSED
;
2084 if (uFlags
& SVSI_DESELECTOTHERS
)
2085 lvItem
.state
&= ~LVIS_SELECTED
;
2087 SendMessageW(This
->hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
2092 if(uFlags
& SVSI_EDIT
)
2093 SendMessageW(This
->hWndList
, LVM_EDITLABELW
, i
, 0);
2099 static HRESULT WINAPI
IShellView_fnGetItemObject(IShellView
* iface
, UINT uItem
, REFIID riid
, LPVOID
*ppvOut
)
2101 HRESULT hr
= E_FAIL
;
2102 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2104 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This
, uItem
, debugstr_guid(riid
), ppvOut
);
2110 case SVGIO_BACKGROUND
:
2111 //*ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2112 CDefFolderMenu_Create2(NULL
, NULL
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, This
->pSFParent
, NULL
, 0, NULL
, (IContextMenu
**)ppvOut
);
2113 if (!ppvOut
) hr
= E_OUTOFMEMORY
;
2116 case SVGIO_SELECTION
:
2117 ShellView_GetSelections(This
);
2118 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, riid
, 0, ppvOut
);
2121 TRACE("-- (%p)->(interface=%p)\n",This
, *ppvOut
);
2126 static const IShellViewVtbl svvt
=
2128 IShellView_fnQueryInterface
,
2129 IShellView_fnAddRef
,
2130 IShellView_fnRelease
,
2131 IShellView_fnGetWindow
,
2132 IShellView_fnContextSensitiveHelp
,
2133 IShellView_fnTranslateAccelerator
,
2134 IShellView_fnEnableModeless
,
2135 IShellView_fnUIActivate
,
2136 IShellView_fnRefresh
,
2137 IShellView_fnCreateViewWindow
,
2138 IShellView_fnDestroyViewWindow
,
2139 IShellView_fnGetCurrentInfo
,
2140 IShellView_fnAddPropertySheetPages
,
2141 IShellView_fnSaveViewState
,
2142 IShellView_fnSelectItem
,
2143 IShellView_fnGetItemObject
2147 /**********************************************************
2148 * ISVOleCmdTarget_QueryInterface (IUnknown)
2150 static HRESULT WINAPI
ISVOleCmdTarget_QueryInterface(
2151 IOleCommandTarget
* iface
,
2155 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2157 return IShellFolder_QueryInterface((IShellFolder
*)This
, iid
, ppvObj
);
2160 /**********************************************************
2161 * ISVOleCmdTarget_AddRef (IUnknown)
2163 static ULONG WINAPI
ISVOleCmdTarget_AddRef(
2164 IOleCommandTarget
* iface
)
2166 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2168 return IShellFolder_AddRef((IShellFolder
*)This
);
2171 /**********************************************************
2172 * ISVOleCmdTarget_Release (IUnknown)
2174 static ULONG WINAPI
ISVOleCmdTarget_Release(
2175 IOleCommandTarget
* iface
)
2177 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2179 return IShellFolder_Release((IShellFolder
*)This
);
2182 /**********************************************************
2183 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2185 static HRESULT WINAPI
ISVOleCmdTarget_QueryStatus(
2186 IOleCommandTarget
*iface
,
2187 const GUID
* pguidCmdGroup
,
2190 OLECMDTEXT
* pCmdText
)
2193 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2195 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2196 This
, pguidCmdGroup
, debugstr_guid(pguidCmdGroup
), cCmds
, prgCmds
, pCmdText
);
2200 for (i
= 0; i
< cCmds
; i
++)
2202 FIXME("\tprgCmds[%d].cmdID = %d\n", i
, prgCmds
[i
].cmdID
);
2203 prgCmds
[i
].cmdf
= 0;
2205 return OLECMDERR_E_UNKNOWNGROUP
;
2208 /**********************************************************
2209 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2211 * nCmdID is the OLECMDID_* enumeration
2213 static HRESULT WINAPI
ISVOleCmdTarget_Exec(
2214 IOleCommandTarget
*iface
,
2215 const GUID
* pguidCmdGroup
,
2221 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2223 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2224 This
, debugstr_guid(pguidCmdGroup
), nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
2226 if (IsEqualIID(pguidCmdGroup
, &CGID_Explorer
) &&
2228 (nCmdexecopt
== 4) && pvaOut
)
2230 if (IsEqualIID(pguidCmdGroup
, &CGID_ShellDocView
) &&
2235 return OLECMDERR_E_UNKNOWNGROUP
;
2238 static const IOleCommandTargetVtbl ctvt
=
2240 ISVOleCmdTarget_QueryInterface
,
2241 ISVOleCmdTarget_AddRef
,
2242 ISVOleCmdTarget_Release
,
2243 ISVOleCmdTarget_QueryStatus
,
2244 ISVOleCmdTarget_Exec
2247 /**********************************************************
2248 * ISVDropTarget implementation
2251 static HRESULT WINAPI
ISVDropTarget_QueryInterface(
2256 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2258 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2260 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2263 static ULONG WINAPI
ISVDropTarget_AddRef( IDropTarget
*iface
)
2265 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2267 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2269 return IShellFolder_AddRef((IShellFolder
*)This
);
2272 static ULONG WINAPI
ISVDropTarget_Release( IDropTarget
*iface
)
2274 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2276 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2278 return IShellFolder_Release((IShellFolder
*)This
);
2281 /******************************************************************************
2282 * drag_notify_subitem [Internal]
2284 * Figure out the shellfolder object, which is currently under the mouse cursor
2285 * and notify it via the IDropTarget interface.
2288 #define SCROLLAREAWIDTH 20
2290 static HRESULT
drag_notify_subitem(IShellViewImpl
*This
, DWORD grfKeyState
, POINTL pt
,
2293 LVHITTESTINFO htinfo
;
2299 /* Map from global to client coordinates and query the index of the listview-item, which is
2300 * currently under the mouse cursor. */
2303 htinfo
.flags
= LVHT_ONITEM
;
2304 ScreenToClient(This
->hWndList
, &htinfo
.pt
);
2305 lResult
= SendMessageW(This
->hWndList
, LVM_HITTEST
, 0, (LPARAM
)&htinfo
);
2307 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2308 GetClientRect(This
->hWndList
, &clientRect
);
2309 if (htinfo
.pt
.x
== This
->ptLastMousePos
.x
&& htinfo
.pt
.y
== This
->ptLastMousePos
.y
&&
2310 (htinfo
.pt
.x
< SCROLLAREAWIDTH
|| htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
||
2311 htinfo
.pt
.y
< SCROLLAREAWIDTH
|| htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
))
2313 This
->cScrollDelay
= (This
->cScrollDelay
+ 1) % 5; /* DragOver is called every 50 ms */
2314 if (This
->cScrollDelay
== 0) { /* Mouse did hover another 250 ms over the scroll-area */
2315 if (htinfo
.pt
.x
< SCROLLAREAWIDTH
)
2316 SendMessageW(This
->hWndList
, WM_HSCROLL
, SB_LINEUP
, 0);
2317 if (htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
)
2318 SendMessageW(This
->hWndList
, WM_HSCROLL
, SB_LINEDOWN
, 0);
2319 if (htinfo
.pt
.y
< SCROLLAREAWIDTH
)
2320 SendMessageW(This
->hWndList
, WM_VSCROLL
, SB_LINEUP
, 0);
2321 if (htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
)
2322 SendMessageW(This
->hWndList
, WM_VSCROLL
, SB_LINEDOWN
, 0);
2325 This
->cScrollDelay
= 0; /* Reset, if the cursor is not over the listview's scroll-area */
2327 This
->ptLastMousePos
= htinfo
.pt
;
2329 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2330 if (This
->pCurDropTarget
&& lResult
== This
->iDragOverItem
)
2331 return IDropTarget_DragOver(This
->pCurDropTarget
, grfKeyState
, pt
, pdwEffect
);
2333 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2334 if (This
->pCurDropTarget
) {
2335 IDropTarget_DragLeave(This
->pCurDropTarget
);
2336 IDropTarget_Release(This
->pCurDropTarget
);
2337 This
->pCurDropTarget
= NULL
;
2340 This
->iDragOverItem
= lResult
;
2341 if (lResult
== -1) {
2342 /* We are not above one of the listview's subitems. Bind to the parent folder's
2343 * DropTarget interface. */
2344 hr
= IShellFolder_QueryInterface(This
->pSFParent
, &IID_IDropTarget
,
2345 (LPVOID
*)&This
->pCurDropTarget
);
2347 /* Query the relative PIDL of the shellfolder object represented by the currently
2348 * dragged over listview-item ... */
2349 lvItem
.mask
= LVIF_PARAM
;
2350 lvItem
.iItem
= lResult
;
2351 lvItem
.iSubItem
= 0;
2352 SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
2354 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2355 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWndList
, 1,
2356 (LPCITEMIDLIST
*)&lvItem
.lParam
, &IID_IDropTarget
, NULL
, (LPVOID
*)&This
->pCurDropTarget
);
2359 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2363 /* Notify the item just entered via DragEnter. */
2364 return IDropTarget_DragEnter(This
->pCurDropTarget
, This
->pCurDataObject
, grfKeyState
, pt
, pdwEffect
);
2367 static HRESULT WINAPI
ISVDropTarget_DragEnter(IDropTarget
*iface
, IDataObject
*pDataObject
,
2368 DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2370 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2372 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2373 This
->pCurDataObject
= pDataObject
;
2374 IDataObject_AddRef(pDataObject
);
2376 return drag_notify_subitem(This
, grfKeyState
, pt
, pdwEffect
);
2379 static HRESULT WINAPI
ISVDropTarget_DragOver(IDropTarget
*iface
, DWORD grfKeyState
, POINTL pt
,
2382 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2383 return drag_notify_subitem(This
, grfKeyState
, pt
, pdwEffect
);
2386 static HRESULT WINAPI
ISVDropTarget_DragLeave(IDropTarget
*iface
) {
2387 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2389 if (This
->pCurDropTarget
)
2391 IDropTarget_DragLeave(This
->pCurDropTarget
);
2392 IDropTarget_Release(This
->pCurDropTarget
);
2393 This
->pCurDropTarget
= NULL
;
2395 IDataObject_Release(This
->pCurDataObject
);
2396 This
->pCurDataObject
= NULL
;
2397 This
->iDragOverItem
= 0;
2402 static HRESULT WINAPI
ISVDropTarget_Drop(IDropTarget
*iface
, IDataObject
* pDataObject
,
2403 DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2405 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2407 if (This
->pCurDropTarget
)
2409 IDropTarget_Drop(This
->pCurDropTarget
, pDataObject
, grfKeyState
, pt
, pdwEffect
);
2410 IDropTarget_Release(This
->pCurDropTarget
);
2411 This
->pCurDropTarget
= NULL
;
2414 IDataObject_Release(This
->pCurDataObject
);
2415 This
->pCurDataObject
= NULL
;
2416 This
->iDragOverItem
= 0;
2421 static const IDropTargetVtbl dtvt
=
2423 ISVDropTarget_QueryInterface
,
2424 ISVDropTarget_AddRef
,
2425 ISVDropTarget_Release
,
2426 ISVDropTarget_DragEnter
,
2427 ISVDropTarget_DragOver
,
2428 ISVDropTarget_DragLeave
,
2432 /**********************************************************
2433 * ISVDropSource implementation
2436 static HRESULT WINAPI
ISVDropSource_QueryInterface(
2441 IShellViewImpl
*This
= impl_from_IDropSource(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
ISVDropSource_AddRef( IDropSource
*iface
)
2450 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2452 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2454 return IShellFolder_AddRef((IShellFolder
*)This
);
2457 static ULONG WINAPI
ISVDropSource_Release( IDropSource
*iface
)
2459 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2461 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2463 return IShellFolder_Release((IShellFolder
*)This
);
2465 static HRESULT WINAPI
ISVDropSource_QueryContinueDrag(
2467 BOOL fEscapePressed
,
2470 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2471 TRACE("(%p)\n",This
);
2474 return DRAGDROP_S_CANCEL
;
2475 else if (!(grfKeyState
& MK_LBUTTON
) && !(grfKeyState
& MK_RBUTTON
))
2476 return DRAGDROP_S_DROP
;
2481 static HRESULT WINAPI
ISVDropSource_GiveFeedback(
2485 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2486 TRACE("(%p)\n",This
);
2488 return DRAGDROP_S_USEDEFAULTCURSORS
;
2491 static const IDropSourceVtbl dsvt
=
2493 ISVDropSource_QueryInterface
,
2494 ISVDropSource_AddRef
,
2495 ISVDropSource_Release
,
2496 ISVDropSource_QueryContinueDrag
,
2497 ISVDropSource_GiveFeedback
2499 /**********************************************************
2500 * ISVViewObject implementation
2503 static HRESULT WINAPI
ISVViewObject_QueryInterface(
2508 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2510 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2512 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2515 static ULONG WINAPI
ISVViewObject_AddRef( IViewObject
*iface
)
2517 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2519 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2521 return IShellFolder_AddRef((IShellFolder
*)This
);
2524 static ULONG WINAPI
ISVViewObject_Release( IViewObject
*iface
)
2526 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2528 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2530 return IShellFolder_Release((IShellFolder
*)This
);
2533 static HRESULT WINAPI
ISVViewObject_Draw(
2538 DVTARGETDEVICE
* ptd
,
2541 LPCRECTL lprcBounds
,
2542 LPCRECTL lprcWBounds
,
2543 BOOL (CALLBACK
*pfnContinue
)(ULONG_PTR dwContinue
),
2544 ULONG_PTR dwContinue
)
2547 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2549 FIXME("Stub: This=%p\n",This
);
2553 static HRESULT WINAPI
ISVViewObject_GetColorSet(
2558 DVTARGETDEVICE
* ptd
,
2559 HDC hicTargetDevice
,
2560 LOGPALETTE
** ppColorSet
)
2563 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2565 FIXME("Stub: This=%p\n",This
);
2569 static HRESULT WINAPI
ISVViewObject_Freeze(
2577 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2579 FIXME("Stub: This=%p\n",This
);
2583 static HRESULT WINAPI
ISVViewObject_Unfreeze(
2588 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2590 FIXME("Stub: This=%p\n",This
);
2594 static HRESULT WINAPI
ISVViewObject_SetAdvise(
2598 IAdviseSink
* pAdvSink
)
2601 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2603 FIXME("partial stub: %p %08x %08x %p\n",
2604 This
, aspects
, advf
, pAdvSink
);
2606 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2607 This
->pAdvSink
= pAdvSink
;
2608 This
->dwAspects
= aspects
;
2609 This
->dwAdvf
= advf
;
2614 static HRESULT WINAPI
ISVViewObject_GetAdvise(
2618 IAdviseSink
** ppAdvSink
)
2621 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2623 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2624 This
, pAspects
, pAdvf
, ppAdvSink
);
2628 IAdviseSink_AddRef( This
->pAdvSink
);
2629 *ppAdvSink
= This
->pAdvSink
;
2632 *pAspects
= This
->dwAspects
;
2634 *pAdvf
= This
->dwAdvf
;
2640 static const IViewObjectVtbl vovt
=
2642 ISVViewObject_QueryInterface
,
2643 ISVViewObject_AddRef
,
2644 ISVViewObject_Release
,
2646 ISVViewObject_GetColorSet
,
2647 ISVViewObject_Freeze
,
2648 ISVViewObject_Unfreeze
,
2649 ISVViewObject_SetAdvise
,
2650 ISVViewObject_GetAdvise