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
;
1514 SHORT ctrl
= GetKeyState(VK_CONTROL
) & 0x8000;
1516 /* initiate a rename of the selected file or directory */
1517 if(plvKeyDown
->wVKey
== VK_F2
)
1519 /* see how many files are selected */
1520 int i
= ListView_GetSelectedCount(This
->hWndList
);
1522 /* get selected item */
1525 /* get selected item */
1526 i
= ListView_GetNextItem(This
->hWndList
, -1,
1529 SendMessageW(This
->hWndList
, LVM_ENSUREVISIBLE
, i
, 0);
1530 SendMessageW(This
->hWndList
, LVM_EDITLABELW
, i
, 0);
1534 TranslateAccelerator(This
->hWnd
, This
->hAccel
, &msg
)
1536 else if(plvKeyDown
->wVKey
== VK_DELETE
)
1541 LPITEMIDLIST
* pItems
;
1544 IShellFolder_QueryInterface(This
->pSFParent
, &IID_ISFHelper
,
1550 if(!(i
= ListView_GetSelectedCount(This
->hWndList
)))
1553 /* allocate memory for the pidl array */
1554 pItems
= HeapAlloc(GetProcessHeap(), 0,
1555 sizeof(LPITEMIDLIST
) * i
);
1557 /* retrieve all selected items */
1560 while(ListView_GetSelectedCount(This
->hWndList
) > i
)
1562 /* get selected item */
1563 item_index
= ListView_GetNextItem(This
->hWndList
,
1564 item_index
, LVNI_SELECTED
);
1565 item
.iItem
= item_index
;
1566 item
.mask
= LVIF_PARAM
;
1567 SendMessageA(This
->hWndList
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1570 pItems
[i
] = (LPITEMIDLIST
)item
.lParam
;
1575 /* perform the item deletion */
1576 ISFHelper_DeleteItems(psfhlp
, i
, (LPCITEMIDLIST
*)pItems
);
1578 /* free pidl array memory */
1579 HeapFree(GetProcessHeap(), 0, pItems
);
1582 /* Initiate a refresh */
1583 else if(plvKeyDown
->wVKey
== VK_F5
)
1585 IShellView_Refresh((IShellView
*)This
);
1587 else if(plvKeyDown
->wVKey
== VK_BACK
)
1589 LPSHELLBROWSER lpSb
;
1590 if((lpSb
= (LPSHELLBROWSER
)SendMessageW(This
->hWndParent
, CWM_GETISHELLBROWSER
, 0, 0)))
1592 IShellBrowser_BrowseObject(lpSb
, NULL
, SBSP_PARENT
);
1595 else if(plvKeyDown
->wVKey
== 'C' && ctrl
)
1597 FIXME("Need to copy\n");
1599 else if(plvKeyDown
->wVKey
== 'V' && ctrl
)
1601 FIXME("Need to paste\n");
1604 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown
->wVKey
);
1609 TRACE("-- %p WM_COMMAND %x unhandled\n", This
, lpnmh
->code
);
1615 /**********************************************************
1616 * ShellView_OnChange()
1619 static LRESULT
ShellView_OnChange(IShellViewImpl
* This
, LPITEMIDLIST
* Pidls
, LONG wEventId
)
1622 TRACE("(%p)(%p,%p,0x%08x)\n", This
, Pidls
[0], Pidls
[1], wEventId
);
1627 LV_AddItem(This
, Pidls
[0]);
1631 LV_DeleteItem(This
, Pidls
[0]);
1633 case SHCNE_RENAMEFOLDER
:
1634 case SHCNE_RENAMEITEM
:
1635 LV_RenameItem(This
, Pidls
[0], Pidls
[1]);
1637 case SHCNE_UPDATEITEM
:
1643 /**********************************************************
1644 * ShellView_DoMeasureItem
1647 static LRESULT
ShellView_DoCustomItem(IShellViewImpl
* pThis
, HWND hWnd
, UINT uMsg
, LPARAM lParam
)
1652 ERR("no menu!!!\n");
1656 if (pThis
->pCM
->lpVtbl
->HandleMenuMsg(pThis
->pCM
, uMsg
, (WPARAM
)hWnd
, lParam
) == S_OK
)
1662 /**********************************************************
1666 static LRESULT CALLBACK
ShellView_WndProc(HWND hWnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
)
1668 IShellViewImpl
* pThis
= (IShellViewImpl
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
1669 LPCREATESTRUCTW lpcs
;
1671 TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd
, uMessage
, wParam
, lParam
);
1676 lpcs
= (LPCREATESTRUCTW
)lParam
;
1677 pThis
= (IShellViewImpl
*)(lpcs
->lpCreateParams
);
1678 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (ULONG_PTR
)pThis
);
1679 pThis
->hWnd
= hWnd
; /*set the window handle*/
1682 case WM_SIZE
: return ShellView_OnSize(pThis
,LOWORD(lParam
), HIWORD(lParam
));
1683 case WM_SETFOCUS
: return ShellView_OnSetFocus(pThis
);
1684 case WM_KILLFOCUS
: return ShellView_OnKillFocus(pThis
);
1685 case WM_CREATE
: return ShellView_OnCreate(pThis
);
1686 case WM_ACTIVATE
: return ShellView_OnActivate(pThis
, SVUIA_ACTIVATE_FOCUS
);
1687 case WM_NOTIFY
: return ShellView_OnNotify(pThis
,(UINT
)wParam
, (LPNMHDR
)lParam
);
1688 case WM_COMMAND
: return ShellView_OnCommand(pThis
,
1689 GET_WM_COMMAND_ID(wParam
, lParam
),
1690 GET_WM_COMMAND_CMD(wParam
, lParam
),
1691 GET_WM_COMMAND_HWND(wParam
, lParam
));
1692 case SHV_CHANGE_NOTIFY
: return ShellView_OnChange(pThis
, (LPITEMIDLIST
*)wParam
, (LONG
)lParam
);
1694 case WM_CONTEXTMENU
: ShellView_DoContextMenu(pThis
, LOWORD(lParam
), HIWORD(lParam
), FALSE
);
1697 case WM_MEASUREITEM
:
1698 return ShellView_DoCustomItem(pThis
, hWnd
, uMessage
, lParam
);
1700 case WM_SHOWWINDOW
: UpdateWindow(pThis
->hWndList
);
1703 case WM_GETDLGCODE
: return SendMessageA(pThis
->hWndList
,uMessage
,0,0);
1706 RevokeDragDrop(pThis
->hWnd
);
1707 SHChangeNotifyDeregister(pThis
->hNotify
);
1711 if ((pThis
->FolderSettings
.fFlags
& FWF_DESKTOP
) ||
1712 (pThis
->FolderSettings
.fFlags
& FWF_TRANSPARENT
))
1715 case CWM_GETISHELLBROWSER
:
1716 return (LRESULT
)pThis
->pShellBrowser
;
1718 return DefWindowProcW(hWnd
, uMessage
, wParam
, lParam
);
1720 /**********************************************************
1723 * The INTERFACE of the IShellView object
1726 **********************************************************
1727 * IShellView_QueryInterface
1729 static HRESULT WINAPI
IShellView_fnQueryInterface(IShellView
* iface
,REFIID riid
, LPVOID
*ppvObj
)
1731 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1733 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
1737 if(IsEqualIID(riid
, &IID_IUnknown
))
1741 else if(IsEqualIID(riid
, &IID_IShellView
))
1743 *ppvObj
= (IShellView
*)This
;
1745 else if(IsEqualIID(riid
, &IID_IOleCommandTarget
))
1747 *ppvObj
= (IOleCommandTarget
*)&(This
->lpvtblOleCommandTarget
);
1749 else if(IsEqualIID(riid
, &IID_IDropTarget
))
1751 *ppvObj
= (IDropTarget
*)&(This
->lpvtblDropTarget
);
1753 else if(IsEqualIID(riid
, &IID_IDropSource
))
1755 *ppvObj
= (IDropSource
*)&(This
->lpvtblDropSource
);
1757 else if(IsEqualIID(riid
, &IID_IViewObject
))
1759 *ppvObj
= (IViewObject
*)&(This
->lpvtblViewObject
);
1764 IUnknown_AddRef( (IUnknown
*)*ppvObj
);
1765 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
1768 TRACE("-- Interface: E_NOINTERFACE\n");
1769 return E_NOINTERFACE
;
1772 /**********************************************************
1775 static ULONG WINAPI
IShellView_fnAddRef(IShellView
* iface
)
1777 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1778 ULONG refCount
= InterlockedIncrement(&This
->ref
);
1780 TRACE("(%p)->(count=%u)\n", This
, refCount
- 1);
1784 /**********************************************************
1785 * IShellView_Release
1787 static ULONG WINAPI
IShellView_fnRelease(IShellView
* iface
)
1789 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1790 ULONG refCount
= InterlockedDecrement(&This
->ref
);
1792 TRACE("(%p)->(count=%i)\n", This
, refCount
+ 1);
1796 TRACE(" destroying IShellView(%p)\n",This
);
1798 DestroyWindow(This
->hWndList
);
1801 IShellFolder_Release(This
->pSFParent
);
1803 if(This
->pSF2Parent
)
1804 IShellFolder2_Release(This
->pSF2Parent
);
1806 SHFree(This
->apidl
);
1809 IAdviseSink_Release(This
->pAdvSink
);
1812 IContextMenu_Release(This
->pCM
);
1814 HeapFree(GetProcessHeap(),0,This
);
1819 /**********************************************************
1820 * ShellView_GetWindow
1822 static HRESULT WINAPI
IShellView_fnGetWindow(IShellView
* iface
,HWND
* phWnd
)
1824 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1826 TRACE("(%p)\n",This
);
1828 *phWnd
= This
->hWnd
;
1833 static HRESULT WINAPI
IShellView_fnContextSensitiveHelp(IShellView
* iface
,BOOL fEnterMode
)
1835 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1837 FIXME("(%p) stub\n",This
);
1842 /**********************************************************
1843 * IShellView_TranslateAccelerator
1846 * use the accel functions
1848 static HRESULT WINAPI
IShellView_fnTranslateAccelerator(IShellView
* iface
,LPMSG lpmsg
)
1851 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1853 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This
,lpmsg
, lpmsg
->hwnd
, lpmsg
->message
, lpmsg
->lParam
, lpmsg
->wParam
);
1856 if ((lpmsg
->message
>=WM_KEYFIRST
) && (lpmsg
->message
>=WM_KEYLAST
))
1858 TRACE("-- key=0x04%lx\n",lpmsg
->wParam
) ;
1860 return S_FALSE
; /* not handled */
1863 static HRESULT WINAPI
IShellView_fnEnableModeless(IShellView
* iface
,BOOL fEnable
)
1865 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1867 FIXME("(%p) stub\n",This
);
1872 static HRESULT WINAPI
IShellView_fnUIActivate(IShellView
* iface
,UINT uState
)
1874 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1877 CHAR szName[MAX_PATH];
1880 int nPartArray
[1] = {-1};
1882 TRACE("(%p)->(state=%x) stub\n",This
, uState
);
1884 /*don't do anything if the state isn't really changing*/
1885 if(This
->uState
== uState
)
1890 /*OnActivate handles the menu merging and internal state*/
1891 ShellView_OnActivate(This
, uState
);
1893 /*only do This if we are active*/
1894 if(uState
!= SVUIA_DEACTIVATE
)
1898 GetFolderPath is not a method of IShellFolder
1899 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1901 /* set the number of parts */
1902 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_STATUS
, SB_SETPARTS
, 1,
1903 (LPARAM
)nPartArray
, &lResult
);
1905 /* set the text for the parts */
1907 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1908 0, (LPARAM)szName, &lResult);
1915 static HRESULT WINAPI
IShellView_fnRefresh(IShellView
* iface
)
1917 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1919 TRACE("(%p)\n",This
);
1921 SendMessageW(This
->hWndList
, LVM_DELETEALLITEMS
, 0, 0);
1922 ShellView_FillList(This
);
1927 static HRESULT WINAPI
IShellView_fnCreateViewWindow(
1929 IShellView
*lpPrevView
,
1930 LPCFOLDERSETTINGS lpfs
,
1931 IShellBrowser
* psb
,
1935 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1941 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This
, lpPrevView
,lpfs
, psb
, prcView
, phWnd
);
1942 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
);
1944 /*set up the member variables*/
1945 This
->pShellBrowser
= psb
;
1946 This
->FolderSettings
= *lpfs
;
1948 /*get our parent window*/
1949 IShellBrowser_AddRef(This
->pShellBrowser
);
1950 IShellBrowser_GetWindow(This
->pShellBrowser
, &(This
->hWndParent
));
1952 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1953 This
->pCommDlgBrowser
=NULL
;
1954 if ( SUCCEEDED (IShellBrowser_QueryInterface( This
->pShellBrowser
,
1955 (REFIID
)&IID_ICommDlgBrowser
, (LPVOID
*) &This
->pCommDlgBrowser
)))
1957 TRACE("-- CommDlgBrowser\n");
1960 /*if our window class has not been registered, then do so*/
1961 if(!GetClassInfoW(shell32_hInstance
, SV_CLASS_NAME
, &wc
))
1963 ZeroMemory(&wc
, sizeof(wc
));
1964 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1965 wc
.lpfnWndProc
= ShellView_WndProc
;
1968 wc
.hInstance
= shell32_hInstance
;
1970 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
1971 wc
.hbrBackground
= (HBRUSH
) (COLOR_BACKGROUND
+1);
1972 wc
.lpszMenuName
= NULL
;
1973 wc
.lpszClassName
= SV_CLASS_NAME
;
1975 if(!RegisterClassW(&wc
))
1979 *phWnd
= CreateWindowExW(0,
1982 WS_CHILD
| WS_TABSTOP
,
1985 prcView
->right
- prcView
->left
,
1986 prcView
->bottom
- prcView
->top
,
1994 if(!*phWnd
) return E_FAIL
;
1996 SetWindowPos(*phWnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_SHOWWINDOW
);
1997 UpdateWindow(*phWnd
);
2002 static HRESULT WINAPI
IShellView_fnDestroyViewWindow(IShellView
* iface
)
2004 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2006 TRACE("(%p)\n",This
);
2008 /*Make absolutely sure all our UI is cleaned up.*/
2009 IShellView_UIActivate((IShellView
*)This
, SVUIA_DEACTIVATE
);
2013 DestroyMenu(This
->hMenu
);
2016 DestroyWindow(This
->hWnd
);
2017 if(This
->pShellBrowser
) IShellBrowser_Release(This
->pShellBrowser
);
2018 if(This
->pCommDlgBrowser
) ICommDlgBrowser_Release(This
->pCommDlgBrowser
);
2024 static HRESULT WINAPI
IShellView_fnGetCurrentInfo(IShellView
* iface
, LPFOLDERSETTINGS lpfs
)
2026 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2028 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This
, lpfs
,
2029 This
->FolderSettings
.ViewMode
, This
->FolderSettings
.fFlags
);
2031 if (!lpfs
) return E_INVALIDARG
;
2033 *lpfs
= This
->FolderSettings
;
2037 static HRESULT WINAPI
IShellView_fnAddPropertySheetPages(IShellView
* iface
, DWORD dwReserved
,LPFNADDPROPSHEETPAGE lpfn
, LPARAM lparam
)
2039 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2041 FIXME("(%p) stub\n",This
);
2046 static HRESULT WINAPI
IShellView_fnSaveViewState(IShellView
* iface
)
2048 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2050 FIXME("(%p) stub\n",This
);
2055 static HRESULT WINAPI
IShellView_fnSelectItem(
2060 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2063 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This
, pidl
, uFlags
);
2065 i
= LV_FindItemByPidl(This
, pidl
);
2071 if(uFlags
& SVSI_ENSUREVISIBLE
)
2072 SendMessageW(This
->hWndList
, LVM_ENSUREVISIBLE
, i
, 0);
2074 lvItem
.mask
= LVIF_STATE
;
2075 lvItem
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
2077 lvItem
.iSubItem
= 0;
2079 while(SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
))
2081 if (lvItem
.iItem
== i
)
2083 if (uFlags
& SVSI_SELECT
)
2084 lvItem
.state
|= LVIS_SELECTED
;
2086 lvItem
.state
&= ~LVIS_SELECTED
;
2088 if(uFlags
& SVSI_FOCUSED
)
2089 lvItem
.state
&= ~LVIS_FOCUSED
;
2093 if (uFlags
& SVSI_DESELECTOTHERS
)
2094 lvItem
.state
&= ~LVIS_SELECTED
;
2096 SendMessageW(This
->hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
2101 if(uFlags
& SVSI_EDIT
)
2102 SendMessageW(This
->hWndList
, LVM_EDITLABELW
, i
, 0);
2108 static HRESULT WINAPI
IShellView_fnGetItemObject(IShellView
* iface
, UINT uItem
, REFIID riid
, LPVOID
*ppvOut
)
2110 HRESULT hr
= E_FAIL
;
2111 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2113 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This
, uItem
, debugstr_guid(riid
), ppvOut
);
2119 case SVGIO_BACKGROUND
:
2120 //*ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2121 CDefFolderMenu_Create2(NULL
, NULL
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, This
->pSFParent
, NULL
, 0, NULL
, (IContextMenu
**)ppvOut
);
2122 if (!ppvOut
) hr
= E_OUTOFMEMORY
;
2125 case SVGIO_SELECTION
:
2126 ShellView_GetSelections(This
);
2127 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, riid
, 0, ppvOut
);
2130 TRACE("-- (%p)->(interface=%p)\n",This
, *ppvOut
);
2135 static const IShellViewVtbl svvt
=
2137 IShellView_fnQueryInterface
,
2138 IShellView_fnAddRef
,
2139 IShellView_fnRelease
,
2140 IShellView_fnGetWindow
,
2141 IShellView_fnContextSensitiveHelp
,
2142 IShellView_fnTranslateAccelerator
,
2143 IShellView_fnEnableModeless
,
2144 IShellView_fnUIActivate
,
2145 IShellView_fnRefresh
,
2146 IShellView_fnCreateViewWindow
,
2147 IShellView_fnDestroyViewWindow
,
2148 IShellView_fnGetCurrentInfo
,
2149 IShellView_fnAddPropertySheetPages
,
2150 IShellView_fnSaveViewState
,
2151 IShellView_fnSelectItem
,
2152 IShellView_fnGetItemObject
2156 /**********************************************************
2157 * ISVOleCmdTarget_QueryInterface (IUnknown)
2159 static HRESULT WINAPI
ISVOleCmdTarget_QueryInterface(
2160 IOleCommandTarget
* iface
,
2164 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2166 return IShellFolder_QueryInterface((IShellFolder
*)This
, iid
, ppvObj
);
2169 /**********************************************************
2170 * ISVOleCmdTarget_AddRef (IUnknown)
2172 static ULONG WINAPI
ISVOleCmdTarget_AddRef(
2173 IOleCommandTarget
* iface
)
2175 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2177 return IShellFolder_AddRef((IShellFolder
*)This
);
2180 /**********************************************************
2181 * ISVOleCmdTarget_Release (IUnknown)
2183 static ULONG WINAPI
ISVOleCmdTarget_Release(
2184 IOleCommandTarget
* iface
)
2186 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2188 return IShellFolder_Release((IShellFolder
*)This
);
2191 /**********************************************************
2192 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2194 static HRESULT WINAPI
ISVOleCmdTarget_QueryStatus(
2195 IOleCommandTarget
*iface
,
2196 const GUID
* pguidCmdGroup
,
2199 OLECMDTEXT
* pCmdText
)
2202 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2204 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2205 This
, pguidCmdGroup
, debugstr_guid(pguidCmdGroup
), cCmds
, prgCmds
, pCmdText
);
2209 for (i
= 0; i
< cCmds
; i
++)
2211 FIXME("\tprgCmds[%d].cmdID = %d\n", i
, prgCmds
[i
].cmdID
);
2212 prgCmds
[i
].cmdf
= 0;
2214 return OLECMDERR_E_UNKNOWNGROUP
;
2217 /**********************************************************
2218 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2220 * nCmdID is the OLECMDID_* enumeration
2222 static HRESULT WINAPI
ISVOleCmdTarget_Exec(
2223 IOleCommandTarget
*iface
,
2224 const GUID
* pguidCmdGroup
,
2230 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2232 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2233 This
, debugstr_guid(pguidCmdGroup
), nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
2235 if (IsEqualIID(pguidCmdGroup
, &CGID_Explorer
) &&
2237 (nCmdexecopt
== 4) && pvaOut
)
2239 if (IsEqualIID(pguidCmdGroup
, &CGID_ShellDocView
) &&
2244 return OLECMDERR_E_UNKNOWNGROUP
;
2247 static const IOleCommandTargetVtbl ctvt
=
2249 ISVOleCmdTarget_QueryInterface
,
2250 ISVOleCmdTarget_AddRef
,
2251 ISVOleCmdTarget_Release
,
2252 ISVOleCmdTarget_QueryStatus
,
2253 ISVOleCmdTarget_Exec
2256 /**********************************************************
2257 * ISVDropTarget implementation
2260 static HRESULT WINAPI
ISVDropTarget_QueryInterface(
2265 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2267 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2269 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2272 static ULONG WINAPI
ISVDropTarget_AddRef( IDropTarget
*iface
)
2274 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2276 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2278 return IShellFolder_AddRef((IShellFolder
*)This
);
2281 static ULONG WINAPI
ISVDropTarget_Release( IDropTarget
*iface
)
2283 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2285 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2287 return IShellFolder_Release((IShellFolder
*)This
);
2290 /******************************************************************************
2291 * drag_notify_subitem [Internal]
2293 * Figure out the shellfolder object, which is currently under the mouse cursor
2294 * and notify it via the IDropTarget interface.
2297 #define SCROLLAREAWIDTH 20
2299 static HRESULT
drag_notify_subitem(IShellViewImpl
*This
, DWORD grfKeyState
, POINTL pt
,
2302 LVHITTESTINFO htinfo
;
2308 /* Map from global to client coordinates and query the index of the listview-item, which is
2309 * currently under the mouse cursor. */
2312 htinfo
.flags
= LVHT_ONITEM
;
2313 ScreenToClient(This
->hWndList
, &htinfo
.pt
);
2314 lResult
= SendMessageW(This
->hWndList
, LVM_HITTEST
, 0, (LPARAM
)&htinfo
);
2316 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2317 GetClientRect(This
->hWndList
, &clientRect
);
2318 if (htinfo
.pt
.x
== This
->ptLastMousePos
.x
&& htinfo
.pt
.y
== This
->ptLastMousePos
.y
&&
2319 (htinfo
.pt
.x
< SCROLLAREAWIDTH
|| htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
||
2320 htinfo
.pt
.y
< SCROLLAREAWIDTH
|| htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
))
2322 This
->cScrollDelay
= (This
->cScrollDelay
+ 1) % 5; /* DragOver is called every 50 ms */
2323 if (This
->cScrollDelay
== 0) { /* Mouse did hover another 250 ms over the scroll-area */
2324 if (htinfo
.pt
.x
< SCROLLAREAWIDTH
)
2325 SendMessageW(This
->hWndList
, WM_HSCROLL
, SB_LINEUP
, 0);
2326 if (htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
)
2327 SendMessageW(This
->hWndList
, WM_HSCROLL
, SB_LINEDOWN
, 0);
2328 if (htinfo
.pt
.y
< SCROLLAREAWIDTH
)
2329 SendMessageW(This
->hWndList
, WM_VSCROLL
, SB_LINEUP
, 0);
2330 if (htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
)
2331 SendMessageW(This
->hWndList
, WM_VSCROLL
, SB_LINEDOWN
, 0);
2334 This
->cScrollDelay
= 0; /* Reset, if the cursor is not over the listview's scroll-area */
2336 This
->ptLastMousePos
= htinfo
.pt
;
2338 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2339 if (This
->pCurDropTarget
&& lResult
== This
->iDragOverItem
)
2340 return IDropTarget_DragOver(This
->pCurDropTarget
, grfKeyState
, pt
, pdwEffect
);
2342 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2343 if (This
->pCurDropTarget
) {
2344 IDropTarget_DragLeave(This
->pCurDropTarget
);
2345 IDropTarget_Release(This
->pCurDropTarget
);
2346 This
->pCurDropTarget
= NULL
;
2349 This
->iDragOverItem
= lResult
;
2350 if (lResult
== -1) {
2351 /* We are not above one of the listview's subitems. Bind to the parent folder's
2352 * DropTarget interface. */
2353 hr
= IShellFolder_QueryInterface(This
->pSFParent
, &IID_IDropTarget
,
2354 (LPVOID
*)&This
->pCurDropTarget
);
2356 /* Query the relative PIDL of the shellfolder object represented by the currently
2357 * dragged over listview-item ... */
2358 lvItem
.mask
= LVIF_PARAM
;
2359 lvItem
.iItem
= lResult
;
2360 lvItem
.iSubItem
= 0;
2361 SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
2363 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2364 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWndList
, 1,
2365 (LPCITEMIDLIST
*)&lvItem
.lParam
, &IID_IDropTarget
, NULL
, (LPVOID
*)&This
->pCurDropTarget
);
2368 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2372 /* Notify the item just entered via DragEnter. */
2373 return IDropTarget_DragEnter(This
->pCurDropTarget
, This
->pCurDataObject
, grfKeyState
, pt
, pdwEffect
);
2376 static HRESULT WINAPI
ISVDropTarget_DragEnter(IDropTarget
*iface
, IDataObject
*pDataObject
,
2377 DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2379 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2381 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2382 This
->pCurDataObject
= pDataObject
;
2383 IDataObject_AddRef(pDataObject
);
2385 return drag_notify_subitem(This
, grfKeyState
, pt
, pdwEffect
);
2388 static HRESULT WINAPI
ISVDropTarget_DragOver(IDropTarget
*iface
, DWORD grfKeyState
, POINTL pt
,
2391 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2392 return drag_notify_subitem(This
, grfKeyState
, pt
, pdwEffect
);
2395 static HRESULT WINAPI
ISVDropTarget_DragLeave(IDropTarget
*iface
) {
2396 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2398 if (This
->pCurDropTarget
)
2400 IDropTarget_DragLeave(This
->pCurDropTarget
);
2401 IDropTarget_Release(This
->pCurDropTarget
);
2402 This
->pCurDropTarget
= NULL
;
2404 IDataObject_Release(This
->pCurDataObject
);
2405 This
->pCurDataObject
= NULL
;
2406 This
->iDragOverItem
= 0;
2411 static HRESULT WINAPI
ISVDropTarget_Drop(IDropTarget
*iface
, IDataObject
* pDataObject
,
2412 DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2414 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2416 if (This
->pCurDropTarget
)
2418 IDropTarget_Drop(This
->pCurDropTarget
, pDataObject
, grfKeyState
, pt
, pdwEffect
);
2419 IDropTarget_Release(This
->pCurDropTarget
);
2420 This
->pCurDropTarget
= NULL
;
2423 IDataObject_Release(This
->pCurDataObject
);
2424 This
->pCurDataObject
= NULL
;
2425 This
->iDragOverItem
= 0;
2430 static const IDropTargetVtbl dtvt
=
2432 ISVDropTarget_QueryInterface
,
2433 ISVDropTarget_AddRef
,
2434 ISVDropTarget_Release
,
2435 ISVDropTarget_DragEnter
,
2436 ISVDropTarget_DragOver
,
2437 ISVDropTarget_DragLeave
,
2441 /**********************************************************
2442 * ISVDropSource implementation
2445 static HRESULT WINAPI
ISVDropSource_QueryInterface(
2450 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2452 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2454 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2457 static ULONG WINAPI
ISVDropSource_AddRef( IDropSource
*iface
)
2459 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2461 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2463 return IShellFolder_AddRef((IShellFolder
*)This
);
2466 static ULONG WINAPI
ISVDropSource_Release( IDropSource
*iface
)
2468 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2470 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2472 return IShellFolder_Release((IShellFolder
*)This
);
2474 static HRESULT WINAPI
ISVDropSource_QueryContinueDrag(
2476 BOOL fEscapePressed
,
2479 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2480 TRACE("(%p)\n",This
);
2483 return DRAGDROP_S_CANCEL
;
2484 else if (!(grfKeyState
& MK_LBUTTON
) && !(grfKeyState
& MK_RBUTTON
))
2485 return DRAGDROP_S_DROP
;
2490 static HRESULT WINAPI
ISVDropSource_GiveFeedback(
2494 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2495 TRACE("(%p)\n",This
);
2497 return DRAGDROP_S_USEDEFAULTCURSORS
;
2500 static const IDropSourceVtbl dsvt
=
2502 ISVDropSource_QueryInterface
,
2503 ISVDropSource_AddRef
,
2504 ISVDropSource_Release
,
2505 ISVDropSource_QueryContinueDrag
,
2506 ISVDropSource_GiveFeedback
2508 /**********************************************************
2509 * ISVViewObject implementation
2512 static HRESULT WINAPI
ISVViewObject_QueryInterface(
2517 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2519 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2521 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2524 static ULONG WINAPI
ISVViewObject_AddRef( IViewObject
*iface
)
2526 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2528 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2530 return IShellFolder_AddRef((IShellFolder
*)This
);
2533 static ULONG WINAPI
ISVViewObject_Release( IViewObject
*iface
)
2535 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2537 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2539 return IShellFolder_Release((IShellFolder
*)This
);
2542 static HRESULT WINAPI
ISVViewObject_Draw(
2547 DVTARGETDEVICE
* ptd
,
2550 LPCRECTL lprcBounds
,
2551 LPCRECTL lprcWBounds
,
2552 BOOL (CALLBACK
*pfnContinue
)(ULONG_PTR dwContinue
),
2553 ULONG_PTR dwContinue
)
2556 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2558 FIXME("Stub: This=%p\n",This
);
2562 static HRESULT WINAPI
ISVViewObject_GetColorSet(
2567 DVTARGETDEVICE
* ptd
,
2568 HDC hicTargetDevice
,
2569 LOGPALETTE
** ppColorSet
)
2572 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2574 FIXME("Stub: This=%p\n",This
);
2578 static HRESULT WINAPI
ISVViewObject_Freeze(
2586 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2588 FIXME("Stub: This=%p\n",This
);
2592 static HRESULT WINAPI
ISVViewObject_Unfreeze(
2597 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2599 FIXME("Stub: This=%p\n",This
);
2603 static HRESULT WINAPI
ISVViewObject_SetAdvise(
2607 IAdviseSink
* pAdvSink
)
2610 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2612 FIXME("partial stub: %p %08x %08x %p\n",
2613 This
, aspects
, advf
, pAdvSink
);
2615 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2616 This
->pAdvSink
= pAdvSink
;
2617 This
->dwAspects
= aspects
;
2618 This
->dwAdvf
= advf
;
2623 static HRESULT WINAPI
ISVViewObject_GetAdvise(
2627 IAdviseSink
** ppAdvSink
)
2630 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2632 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2633 This
, pAspects
, pAdvf
, ppAdvSink
);
2637 IAdviseSink_AddRef( This
->pAdvSink
);
2638 *ppAdvSink
= This
->pAdvSink
;
2641 *pAspects
= This
->dwAspects
;
2643 *pAdvf
= This
->dwAdvf
;
2649 static const IViewObjectVtbl vovt
=
2651 ISVViewObject_QueryInterface
,
2652 ISVViewObject_AddRef
,
2653 ISVViewObject_Release
,
2655 ISVViewObject_GetColorSet
,
2656 ISVViewObject_Freeze
,
2657 ISVViewObject_Unfreeze
,
2658 ISVViewObject_SetAdvise
,
2659 ISVViewObject_GetAdvise