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 if (ShellView_GetSelections(This
))
1601 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, &IID_IDataObject
,0,(LPVOID
*)&pda
)))
1603 HRESULT hr
= OleSetClipboard(pda
);
1606 WARN("OleSetClipboard failed");
1608 IDataObject_Release(pda
);
1613 else if(plvKeyDown
->wVKey
== 'V' && ctrl
)
1617 FORMATETC formatetc
;
1618 LPITEMIDLIST
* apidl
;
1620 IShellFolder
*psfFrom
= NULL
, *psfDesktop
, *psfTarget
= NULL
;
1622 ISFHelper
*psfhlpdst
, *psfhlpsrc
;
1625 hr
= OleGetClipboard(&pda
);
1628 ERR("Failed to get clipboard with %lx\n", hr
);
1632 InitFormatEtc(formatetc
, RegisterClipboardFormatW(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
1633 hr
= IDataObject_GetData(pda
,&formatetc
,&medium
);
1637 ERR("Failed to get clipboard data with %lx\n", hr
);
1638 IDataObject_Release(pda
);
1642 /* lock the handle */
1643 lpcida
= GlobalLock(medium
.u
.hGlobal
);
1646 ERR("failed to lock pidl\n");
1647 ReleaseStgMedium(&medium
);
1648 IDataObject_Release(pda
);
1652 /* convert the data into pidl */
1653 apidl
= _ILCopyCidaToaPidl(&pidl
, lpcida
);
1657 ERR("failed to copy pidl\n");
1661 if (FAILED(SHGetDesktopFolder(&psfDesktop
)))
1663 ERR("failed to get desktop folder\n");
1665 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1666 ReleaseStgMedium(&medium
);
1667 IDataObject_Release(pda
);
1671 if (_ILIsDesktop(pidl
))
1673 /* use desktop shellfolder */
1674 psfFrom
= psfDesktop
;
1676 else if (FAILED(IShellFolder_BindToObject(psfDesktop
, pidl
, NULL
, &IID_IShellFolder
, (LPVOID
*)&psfFrom
)))
1678 ERR("no IShellFolder\n");
1680 IShellFolder_Release(psfDesktop
);
1682 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1683 ReleaseStgMedium(&medium
);
1684 IDataObject_Release(pda
);
1689 psfTarget
= This
->pSFParent
;
1692 /* get source and destination shellfolder */
1693 if (FAILED(IShellFolder_QueryInterface(psfTarget
, &IID_ISFHelper
, (LPVOID
*)&psfhlpdst
)))
1695 ERR("no IID_ISFHelper for destination\n");
1697 IShellFolder_Release(psfFrom
);
1698 IShellFolder_Release(psfTarget
);
1700 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1701 ReleaseStgMedium(&medium
);
1702 IDataObject_Release(pda
);
1707 if (FAILED(IShellFolder_QueryInterface(psfFrom
, &IID_ISFHelper
, (LPVOID
*)&psfhlpsrc
)))
1709 ERR("no IID_ISFHelper for source\n");
1711 ISFHelper_Release(psfhlpdst
);
1712 IShellFolder_Release(psfFrom
);
1713 IShellFolder_Release(psfTarget
);
1715 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1716 ReleaseStgMedium(&medium
);
1717 IDataObject_Release(pda
);
1722 * do we want to perform a copy or move ???
1724 hr
= ISFHelper_CopyItems(psfhlpdst
, psfFrom
, lpcida
->cidl
, (LPCITEMIDLIST
*)apidl
);
1726 ISFHelper_Release(psfhlpdst
);
1727 ISFHelper_Release(psfhlpsrc
);
1728 IShellFolder_Release(psfFrom
);
1730 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1731 ReleaseStgMedium(&medium
);
1732 IDataObject_Release(pda
);
1733 TRACE("paste end hr %x\n", hr
);
1737 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown
->wVKey
);
1742 TRACE("-- %p WM_COMMAND %x unhandled\n", This
, lpnmh
->code
);
1748 /**********************************************************
1749 * ShellView_OnChange()
1752 static LRESULT
ShellView_OnChange(IShellViewImpl
* This
, LPITEMIDLIST
* Pidls
, LONG wEventId
)
1755 TRACE("(%p)(%p,%p,0x%08x)\n", This
, Pidls
[0], Pidls
[1], wEventId
);
1760 LV_AddItem(This
, Pidls
[0]);
1764 LV_DeleteItem(This
, Pidls
[0]);
1766 case SHCNE_RENAMEFOLDER
:
1767 case SHCNE_RENAMEITEM
:
1768 LV_RenameItem(This
, Pidls
[0], Pidls
[1]);
1770 case SHCNE_UPDATEITEM
:
1776 /**********************************************************
1777 * ShellView_DoMeasureItem
1780 static LRESULT
ShellView_DoCustomItem(IShellViewImpl
* pThis
, HWND hWnd
, UINT uMsg
, LPARAM lParam
)
1785 ERR("no menu!!!\n");
1789 if (pThis
->pCM
->lpVtbl
->HandleMenuMsg(pThis
->pCM
, uMsg
, (WPARAM
)hWnd
, lParam
) == S_OK
)
1795 /**********************************************************
1799 static LRESULT CALLBACK
ShellView_WndProc(HWND hWnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
)
1801 IShellViewImpl
* pThis
= (IShellViewImpl
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
1802 LPCREATESTRUCTW lpcs
;
1804 TRACE("(hwnd=%p msg=%x wparm=%lx lparm=%lx)\n",hWnd
, uMessage
, wParam
, lParam
);
1809 lpcs
= (LPCREATESTRUCTW
)lParam
;
1810 pThis
= (IShellViewImpl
*)(lpcs
->lpCreateParams
);
1811 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (ULONG_PTR
)pThis
);
1812 pThis
->hWnd
= hWnd
; /*set the window handle*/
1815 case WM_SIZE
: return ShellView_OnSize(pThis
,LOWORD(lParam
), HIWORD(lParam
));
1816 case WM_SETFOCUS
: return ShellView_OnSetFocus(pThis
);
1817 case WM_KILLFOCUS
: return ShellView_OnKillFocus(pThis
);
1818 case WM_CREATE
: return ShellView_OnCreate(pThis
);
1819 case WM_ACTIVATE
: return ShellView_OnActivate(pThis
, SVUIA_ACTIVATE_FOCUS
);
1820 case WM_NOTIFY
: return ShellView_OnNotify(pThis
,(UINT
)wParam
, (LPNMHDR
)lParam
);
1821 case WM_COMMAND
: return ShellView_OnCommand(pThis
,
1822 GET_WM_COMMAND_ID(wParam
, lParam
),
1823 GET_WM_COMMAND_CMD(wParam
, lParam
),
1824 GET_WM_COMMAND_HWND(wParam
, lParam
));
1825 case SHV_CHANGE_NOTIFY
: return ShellView_OnChange(pThis
, (LPITEMIDLIST
*)wParam
, (LONG
)lParam
);
1827 case WM_CONTEXTMENU
: ShellView_DoContextMenu(pThis
, LOWORD(lParam
), HIWORD(lParam
), FALSE
);
1830 case WM_MEASUREITEM
:
1831 return ShellView_DoCustomItem(pThis
, hWnd
, uMessage
, lParam
);
1833 case WM_SHOWWINDOW
: UpdateWindow(pThis
->hWndList
);
1836 case WM_GETDLGCODE
: return SendMessageA(pThis
->hWndList
,uMessage
,0,0);
1839 RevokeDragDrop(pThis
->hWnd
);
1840 SHChangeNotifyDeregister(pThis
->hNotify
);
1844 if ((pThis
->FolderSettings
.fFlags
& FWF_DESKTOP
) ||
1845 (pThis
->FolderSettings
.fFlags
& FWF_TRANSPARENT
))
1848 case CWM_GETISHELLBROWSER
:
1849 return (LRESULT
)pThis
->pShellBrowser
;
1851 return DefWindowProcW(hWnd
, uMessage
, wParam
, lParam
);
1853 /**********************************************************
1856 * The INTERFACE of the IShellView object
1859 **********************************************************
1860 * IShellView_QueryInterface
1862 static HRESULT WINAPI
IShellView_fnQueryInterface(IShellView
* iface
,REFIID riid
, LPVOID
*ppvObj
)
1864 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1866 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
1870 if(IsEqualIID(riid
, &IID_IUnknown
))
1874 else if(IsEqualIID(riid
, &IID_IShellView
))
1876 *ppvObj
= (IShellView
*)This
;
1878 else if(IsEqualIID(riid
, &IID_IOleCommandTarget
))
1880 *ppvObj
= (IOleCommandTarget
*)&(This
->lpvtblOleCommandTarget
);
1882 else if(IsEqualIID(riid
, &IID_IDropTarget
))
1884 *ppvObj
= (IDropTarget
*)&(This
->lpvtblDropTarget
);
1886 else if(IsEqualIID(riid
, &IID_IDropSource
))
1888 *ppvObj
= (IDropSource
*)&(This
->lpvtblDropSource
);
1890 else if(IsEqualIID(riid
, &IID_IViewObject
))
1892 *ppvObj
= (IViewObject
*)&(This
->lpvtblViewObject
);
1897 IUnknown_AddRef( (IUnknown
*)*ppvObj
);
1898 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
1901 TRACE("-- Interface: E_NOINTERFACE\n");
1902 return E_NOINTERFACE
;
1905 /**********************************************************
1908 static ULONG WINAPI
IShellView_fnAddRef(IShellView
* iface
)
1910 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1911 ULONG refCount
= InterlockedIncrement(&This
->ref
);
1913 TRACE("(%p)->(count=%u)\n", This
, refCount
- 1);
1917 /**********************************************************
1918 * IShellView_Release
1920 static ULONG WINAPI
IShellView_fnRelease(IShellView
* iface
)
1922 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1923 ULONG refCount
= InterlockedDecrement(&This
->ref
);
1925 TRACE("(%p)->(count=%i)\n", This
, refCount
+ 1);
1929 TRACE(" destroying IShellView(%p)\n",This
);
1931 DestroyWindow(This
->hWndList
);
1934 IShellFolder_Release(This
->pSFParent
);
1936 if(This
->pSF2Parent
)
1937 IShellFolder2_Release(This
->pSF2Parent
);
1939 SHFree(This
->apidl
);
1942 IAdviseSink_Release(This
->pAdvSink
);
1945 IContextMenu_Release(This
->pCM
);
1947 HeapFree(GetProcessHeap(),0,This
);
1952 /**********************************************************
1953 * ShellView_GetWindow
1955 static HRESULT WINAPI
IShellView_fnGetWindow(IShellView
* iface
,HWND
* phWnd
)
1957 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1959 TRACE("(%p)\n",This
);
1961 *phWnd
= This
->hWnd
;
1966 static HRESULT WINAPI
IShellView_fnContextSensitiveHelp(IShellView
* iface
,BOOL fEnterMode
)
1968 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1970 FIXME("(%p) stub\n",This
);
1975 /**********************************************************
1976 * IShellView_TranslateAccelerator
1979 * use the accel functions
1981 static HRESULT WINAPI
IShellView_fnTranslateAccelerator(IShellView
* iface
,LPMSG lpmsg
)
1984 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1986 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",This
,lpmsg
, lpmsg
->hwnd
, lpmsg
->message
, lpmsg
->lParam
, lpmsg
->wParam
);
1989 if ((lpmsg
->message
>=WM_KEYFIRST
) && (lpmsg
->message
>=WM_KEYLAST
))
1991 TRACE("-- key=0x04%lx\n",lpmsg
->wParam
) ;
1993 return S_FALSE
; /* not handled */
1996 static HRESULT WINAPI
IShellView_fnEnableModeless(IShellView
* iface
,BOOL fEnable
)
1998 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2000 FIXME("(%p) stub\n",This
);
2005 static HRESULT WINAPI
IShellView_fnUIActivate(IShellView
* iface
,UINT uState
)
2007 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2010 CHAR szName[MAX_PATH];
2013 int nPartArray
[1] = {-1};
2015 TRACE("(%p)->(state=%x) stub\n",This
, uState
);
2017 /*don't do anything if the state isn't really changing*/
2018 if(This
->uState
== uState
)
2023 /*OnActivate handles the menu merging and internal state*/
2024 ShellView_OnActivate(This
, uState
);
2026 /*only do This if we are active*/
2027 if(uState
!= SVUIA_DEACTIVATE
)
2031 GetFolderPath is not a method of IShellFolder
2032 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
2034 /* set the number of parts */
2035 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_STATUS
, SB_SETPARTS
, 1,
2036 (LPARAM
)nPartArray
, &lResult
);
2038 /* set the text for the parts */
2040 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
2041 0, (LPARAM)szName, &lResult);
2048 static HRESULT WINAPI
IShellView_fnRefresh(IShellView
* iface
)
2050 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2052 TRACE("(%p)\n",This
);
2054 SendMessageW(This
->hWndList
, LVM_DELETEALLITEMS
, 0, 0);
2055 ShellView_FillList(This
);
2060 static HRESULT WINAPI
IShellView_fnCreateViewWindow(
2062 IShellView
*lpPrevView
,
2063 LPCFOLDERSETTINGS lpfs
,
2064 IShellBrowser
* psb
,
2068 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2074 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This
, lpPrevView
,lpfs
, psb
, prcView
, phWnd
);
2076 TRACE("-- vmode=%x flags=%x\n", lpfs
->ViewMode
, lpfs
->fFlags
);
2077 if (prcView
!= NULL
)
2078 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView
->left
, prcView
->top
, prcView
->right
, prcView
->bottom
);
2080 /* Validate the Shell Browser */
2082 return E_UNEXPECTED
;
2084 /*set up the member variables*/
2085 This
->pShellBrowser
= psb
;
2086 This
->FolderSettings
= *lpfs
;
2088 /*get our parent window*/
2089 IShellBrowser_AddRef(This
->pShellBrowser
);
2090 IShellBrowser_GetWindow(This
->pShellBrowser
, &(This
->hWndParent
));
2092 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
2093 This
->pCommDlgBrowser
=NULL
;
2094 if ( SUCCEEDED (IShellBrowser_QueryInterface( This
->pShellBrowser
,
2095 (REFIID
)&IID_ICommDlgBrowser
, (LPVOID
*) &This
->pCommDlgBrowser
)))
2097 TRACE("-- CommDlgBrowser\n");
2100 /*if our window class has not been registered, then do so*/
2101 if(!GetClassInfoW(shell32_hInstance
, SV_CLASS_NAME
, &wc
))
2103 ZeroMemory(&wc
, sizeof(wc
));
2104 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
2105 wc
.lpfnWndProc
= ShellView_WndProc
;
2108 wc
.hInstance
= shell32_hInstance
;
2110 wc
.hCursor
= LoadCursorW(0, (LPWSTR
)IDC_ARROW
);
2111 wc
.hbrBackground
= (HBRUSH
) (COLOR_BACKGROUND
+1);
2112 wc
.lpszMenuName
= NULL
;
2113 wc
.lpszClassName
= SV_CLASS_NAME
;
2115 if(!RegisterClassW(&wc
))
2119 *phWnd
= CreateWindowExW(0,
2122 WS_CHILD
| WS_TABSTOP
,
2125 prcView
->right
- prcView
->left
,
2126 prcView
->bottom
- prcView
->top
,
2134 if(!*phWnd
) return E_FAIL
;
2136 SetWindowPos(*phWnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_SHOWWINDOW
);
2137 UpdateWindow(*phWnd
);
2142 static HRESULT WINAPI
IShellView_fnDestroyViewWindow(IShellView
* iface
)
2144 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2146 TRACE("(%p)\n",This
);
2148 /*Make absolutely sure all our UI is cleaned up.*/
2149 IShellView_UIActivate((IShellView
*)This
, SVUIA_DEACTIVATE
);
2153 DestroyMenu(This
->hMenu
);
2156 DestroyWindow(This
->hWnd
);
2157 if(This
->pShellBrowser
) IShellBrowser_Release(This
->pShellBrowser
);
2158 if(This
->pCommDlgBrowser
) ICommDlgBrowser_Release(This
->pCommDlgBrowser
);
2164 static HRESULT WINAPI
IShellView_fnGetCurrentInfo(IShellView
* iface
, LPFOLDERSETTINGS lpfs
)
2166 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2168 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This
, lpfs
,
2169 This
->FolderSettings
.ViewMode
, This
->FolderSettings
.fFlags
);
2171 if (!lpfs
) return E_INVALIDARG
;
2173 *lpfs
= This
->FolderSettings
;
2177 static HRESULT WINAPI
IShellView_fnAddPropertySheetPages(IShellView
* iface
, DWORD dwReserved
,LPFNADDPROPSHEETPAGE lpfn
, LPARAM lparam
)
2179 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2181 FIXME("(%p) stub\n",This
);
2186 static HRESULT WINAPI
IShellView_fnSaveViewState(IShellView
* iface
)
2188 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2190 FIXME("(%p) stub\n",This
);
2195 static HRESULT WINAPI
IShellView_fnSelectItem(
2200 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2203 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This
, pidl
, uFlags
);
2205 i
= LV_FindItemByPidl(This
, pidl
);
2211 if(uFlags
& SVSI_ENSUREVISIBLE
)
2212 SendMessageW(This
->hWndList
, LVM_ENSUREVISIBLE
, i
, 0);
2214 lvItem
.mask
= LVIF_STATE
;
2215 lvItem
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
2217 lvItem
.iSubItem
= 0;
2219 while(SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
))
2221 if (lvItem
.iItem
== i
)
2223 if (uFlags
& SVSI_SELECT
)
2224 lvItem
.state
|= LVIS_SELECTED
;
2226 lvItem
.state
&= ~LVIS_SELECTED
;
2228 if(uFlags
& SVSI_FOCUSED
)
2229 lvItem
.state
&= ~LVIS_FOCUSED
;
2233 if (uFlags
& SVSI_DESELECTOTHERS
)
2234 lvItem
.state
&= ~LVIS_SELECTED
;
2236 SendMessageW(This
->hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
2241 if(uFlags
& SVSI_EDIT
)
2242 SendMessageW(This
->hWndList
, LVM_EDITLABELW
, i
, 0);
2248 static HRESULT WINAPI
IShellView_fnGetItemObject(IShellView
* iface
, UINT uItem
, REFIID riid
, LPVOID
*ppvOut
)
2250 HRESULT hr
= E_FAIL
;
2251 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2253 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This
, uItem
, debugstr_guid(riid
), ppvOut
);
2259 case SVGIO_BACKGROUND
:
2260 //*ppvOut = ISvBgCm_Constructor(This->pSFParent, FALSE);
2261 CDefFolderMenu_Create2(NULL
, NULL
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, This
->pSFParent
, NULL
, 0, NULL
, (IContextMenu
**)ppvOut
);
2262 if (!ppvOut
) hr
= E_OUTOFMEMORY
;
2265 case SVGIO_SELECTION
:
2266 ShellView_GetSelections(This
);
2267 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, riid
, 0, ppvOut
);
2270 TRACE("-- (%p)->(interface=%p)\n",This
, *ppvOut
);
2275 static const IShellViewVtbl svvt
=
2277 IShellView_fnQueryInterface
,
2278 IShellView_fnAddRef
,
2279 IShellView_fnRelease
,
2280 IShellView_fnGetWindow
,
2281 IShellView_fnContextSensitiveHelp
,
2282 IShellView_fnTranslateAccelerator
,
2283 IShellView_fnEnableModeless
,
2284 IShellView_fnUIActivate
,
2285 IShellView_fnRefresh
,
2286 IShellView_fnCreateViewWindow
,
2287 IShellView_fnDestroyViewWindow
,
2288 IShellView_fnGetCurrentInfo
,
2289 IShellView_fnAddPropertySheetPages
,
2290 IShellView_fnSaveViewState
,
2291 IShellView_fnSelectItem
,
2292 IShellView_fnGetItemObject
2296 /**********************************************************
2297 * ISVOleCmdTarget_QueryInterface (IUnknown)
2299 static HRESULT WINAPI
ISVOleCmdTarget_QueryInterface(
2300 IOleCommandTarget
* iface
,
2304 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2306 return IShellFolder_QueryInterface((IShellFolder
*)This
, iid
, ppvObj
);
2309 /**********************************************************
2310 * ISVOleCmdTarget_AddRef (IUnknown)
2312 static ULONG WINAPI
ISVOleCmdTarget_AddRef(
2313 IOleCommandTarget
* iface
)
2315 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2317 return IShellFolder_AddRef((IShellFolder
*)This
);
2320 /**********************************************************
2321 * ISVOleCmdTarget_Release (IUnknown)
2323 static ULONG WINAPI
ISVOleCmdTarget_Release(
2324 IOleCommandTarget
* iface
)
2326 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2328 return IShellFolder_Release((IShellFolder
*)This
);
2331 /**********************************************************
2332 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2334 static HRESULT WINAPI
ISVOleCmdTarget_QueryStatus(
2335 IOleCommandTarget
*iface
,
2336 const GUID
* pguidCmdGroup
,
2339 OLECMDTEXT
* pCmdText
)
2342 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2344 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2345 This
, pguidCmdGroup
, debugstr_guid(pguidCmdGroup
), cCmds
, prgCmds
, pCmdText
);
2349 for (i
= 0; i
< cCmds
; i
++)
2351 FIXME("\tprgCmds[%d].cmdID = %d\n", i
, prgCmds
[i
].cmdID
);
2352 prgCmds
[i
].cmdf
= 0;
2354 return OLECMDERR_E_UNKNOWNGROUP
;
2357 /**********************************************************
2358 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2360 * nCmdID is the OLECMDID_* enumeration
2362 static HRESULT WINAPI
ISVOleCmdTarget_Exec(
2363 IOleCommandTarget
*iface
,
2364 const GUID
* pguidCmdGroup
,
2370 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2372 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2373 This
, debugstr_guid(pguidCmdGroup
), nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
2375 if (IsEqualIID(pguidCmdGroup
, &CGID_Explorer
) &&
2377 (nCmdexecopt
== 4) && pvaOut
)
2379 if (IsEqualIID(pguidCmdGroup
, &CGID_ShellDocView
) &&
2384 return OLECMDERR_E_UNKNOWNGROUP
;
2387 static const IOleCommandTargetVtbl ctvt
=
2389 ISVOleCmdTarget_QueryInterface
,
2390 ISVOleCmdTarget_AddRef
,
2391 ISVOleCmdTarget_Release
,
2392 ISVOleCmdTarget_QueryStatus
,
2393 ISVOleCmdTarget_Exec
2396 /**********************************************************
2397 * ISVDropTarget implementation
2400 static HRESULT WINAPI
ISVDropTarget_QueryInterface(
2405 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2407 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2409 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2412 static ULONG WINAPI
ISVDropTarget_AddRef( IDropTarget
*iface
)
2414 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2416 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2418 return IShellFolder_AddRef((IShellFolder
*)This
);
2421 static ULONG WINAPI
ISVDropTarget_Release( IDropTarget
*iface
)
2423 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2425 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2427 return IShellFolder_Release((IShellFolder
*)This
);
2430 /******************************************************************************
2431 * drag_notify_subitem [Internal]
2433 * Figure out the shellfolder object, which is currently under the mouse cursor
2434 * and notify it via the IDropTarget interface.
2437 #define SCROLLAREAWIDTH 20
2439 static HRESULT
drag_notify_subitem(IShellViewImpl
*This
, DWORD grfKeyState
, POINTL pt
,
2442 LVHITTESTINFO htinfo
;
2448 /* Map from global to client coordinates and query the index of the listview-item, which is
2449 * currently under the mouse cursor. */
2452 htinfo
.flags
= LVHT_ONITEM
;
2453 ScreenToClient(This
->hWndList
, &htinfo
.pt
);
2454 lResult
= SendMessageW(This
->hWndList
, LVM_HITTEST
, 0, (LPARAM
)&htinfo
);
2456 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2457 GetClientRect(This
->hWndList
, &clientRect
);
2458 if (htinfo
.pt
.x
== This
->ptLastMousePos
.x
&& htinfo
.pt
.y
== This
->ptLastMousePos
.y
&&
2459 (htinfo
.pt
.x
< SCROLLAREAWIDTH
|| htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
||
2460 htinfo
.pt
.y
< SCROLLAREAWIDTH
|| htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
))
2462 This
->cScrollDelay
= (This
->cScrollDelay
+ 1) % 5; /* DragOver is called every 50 ms */
2463 if (This
->cScrollDelay
== 0) { /* Mouse did hover another 250 ms over the scroll-area */
2464 if (htinfo
.pt
.x
< SCROLLAREAWIDTH
)
2465 SendMessageW(This
->hWndList
, WM_HSCROLL
, SB_LINEUP
, 0);
2466 if (htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
)
2467 SendMessageW(This
->hWndList
, WM_HSCROLL
, SB_LINEDOWN
, 0);
2468 if (htinfo
.pt
.y
< SCROLLAREAWIDTH
)
2469 SendMessageW(This
->hWndList
, WM_VSCROLL
, SB_LINEUP
, 0);
2470 if (htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
)
2471 SendMessageW(This
->hWndList
, WM_VSCROLL
, SB_LINEDOWN
, 0);
2474 This
->cScrollDelay
= 0; /* Reset, if the cursor is not over the listview's scroll-area */
2476 This
->ptLastMousePos
= htinfo
.pt
;
2478 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2479 if (This
->pCurDropTarget
&& lResult
== This
->iDragOverItem
)
2480 return IDropTarget_DragOver(This
->pCurDropTarget
, grfKeyState
, pt
, pdwEffect
);
2482 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2483 if (This
->pCurDropTarget
) {
2484 IDropTarget_DragLeave(This
->pCurDropTarget
);
2485 IDropTarget_Release(This
->pCurDropTarget
);
2486 This
->pCurDropTarget
= NULL
;
2489 This
->iDragOverItem
= lResult
;
2490 if (lResult
== -1) {
2491 /* We are not above one of the listview's subitems. Bind to the parent folder's
2492 * DropTarget interface. */
2493 hr
= IShellFolder_QueryInterface(This
->pSFParent
, &IID_IDropTarget
,
2494 (LPVOID
*)&This
->pCurDropTarget
);
2496 /* Query the relative PIDL of the shellfolder object represented by the currently
2497 * dragged over listview-item ... */
2498 lvItem
.mask
= LVIF_PARAM
;
2499 lvItem
.iItem
= lResult
;
2500 lvItem
.iSubItem
= 0;
2501 SendMessageW(This
->hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
2503 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2504 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWndList
, 1,
2505 (LPCITEMIDLIST
*)&lvItem
.lParam
, &IID_IDropTarget
, NULL
, (LPVOID
*)&This
->pCurDropTarget
);
2508 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2512 /* Notify the item just entered via DragEnter. */
2513 return IDropTarget_DragEnter(This
->pCurDropTarget
, This
->pCurDataObject
, grfKeyState
, pt
, pdwEffect
);
2516 static HRESULT WINAPI
ISVDropTarget_DragEnter(IDropTarget
*iface
, IDataObject
*pDataObject
,
2517 DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2519 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2521 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2522 This
->pCurDataObject
= pDataObject
;
2523 IDataObject_AddRef(pDataObject
);
2525 return drag_notify_subitem(This
, grfKeyState
, pt
, pdwEffect
);
2528 static HRESULT WINAPI
ISVDropTarget_DragOver(IDropTarget
*iface
, DWORD grfKeyState
, POINTL pt
,
2531 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2532 return drag_notify_subitem(This
, grfKeyState
, pt
, pdwEffect
);
2535 static HRESULT WINAPI
ISVDropTarget_DragLeave(IDropTarget
*iface
) {
2536 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2538 if (This
->pCurDropTarget
)
2540 IDropTarget_DragLeave(This
->pCurDropTarget
);
2541 IDropTarget_Release(This
->pCurDropTarget
);
2542 This
->pCurDropTarget
= NULL
;
2545 if (This
->pCurDataObject
!= NULL
)
2547 IDataObject_Release(This
->pCurDataObject
);
2548 This
->pCurDataObject
= NULL
;
2551 This
->iDragOverItem
= 0;
2556 static HRESULT WINAPI
ISVDropTarget_Drop(IDropTarget
*iface
, IDataObject
* pDataObject
,
2557 DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2559 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2561 if (This
->pCurDropTarget
)
2563 IDropTarget_Drop(This
->pCurDropTarget
, pDataObject
, grfKeyState
, pt
, pdwEffect
);
2564 IDropTarget_Release(This
->pCurDropTarget
);
2565 This
->pCurDropTarget
= NULL
;
2568 if (This
->pCurDataObject
!= NULL
)
2570 IDataObject_Release(This
->pCurDataObject
);
2571 This
->pCurDataObject
= NULL
;
2574 This
->iDragOverItem
= 0;
2579 static const IDropTargetVtbl dtvt
=
2581 ISVDropTarget_QueryInterface
,
2582 ISVDropTarget_AddRef
,
2583 ISVDropTarget_Release
,
2584 ISVDropTarget_DragEnter
,
2585 ISVDropTarget_DragOver
,
2586 ISVDropTarget_DragLeave
,
2590 /**********************************************************
2591 * ISVDropSource implementation
2594 static HRESULT WINAPI
ISVDropSource_QueryInterface(
2599 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2601 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2603 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2606 static ULONG WINAPI
ISVDropSource_AddRef( IDropSource
*iface
)
2608 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2610 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2612 return IShellFolder_AddRef((IShellFolder
*)This
);
2615 static ULONG WINAPI
ISVDropSource_Release( IDropSource
*iface
)
2617 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2619 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2621 return IShellFolder_Release((IShellFolder
*)This
);
2623 static HRESULT WINAPI
ISVDropSource_QueryContinueDrag(
2625 BOOL fEscapePressed
,
2628 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2629 TRACE("(%p)\n",This
);
2632 return DRAGDROP_S_CANCEL
;
2633 else if (!(grfKeyState
& MK_LBUTTON
) && !(grfKeyState
& MK_RBUTTON
))
2634 return DRAGDROP_S_DROP
;
2639 static HRESULT WINAPI
ISVDropSource_GiveFeedback(
2643 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2644 TRACE("(%p)\n",This
);
2646 return DRAGDROP_S_USEDEFAULTCURSORS
;
2649 static const IDropSourceVtbl dsvt
=
2651 ISVDropSource_QueryInterface
,
2652 ISVDropSource_AddRef
,
2653 ISVDropSource_Release
,
2654 ISVDropSource_QueryContinueDrag
,
2655 ISVDropSource_GiveFeedback
2657 /**********************************************************
2658 * ISVViewObject implementation
2661 static HRESULT WINAPI
ISVViewObject_QueryInterface(
2666 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2668 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2670 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2673 static ULONG WINAPI
ISVViewObject_AddRef( IViewObject
*iface
)
2675 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2677 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2679 return IShellFolder_AddRef((IShellFolder
*)This
);
2682 static ULONG WINAPI
ISVViewObject_Release( IViewObject
*iface
)
2684 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2686 TRACE("(%p)->(count=%u)\n",This
,This
->ref
);
2688 return IShellFolder_Release((IShellFolder
*)This
);
2691 static HRESULT WINAPI
ISVViewObject_Draw(
2696 DVTARGETDEVICE
* ptd
,
2699 LPCRECTL lprcBounds
,
2700 LPCRECTL lprcWBounds
,
2701 BOOL (CALLBACK
*pfnContinue
)(ULONG_PTR dwContinue
),
2702 ULONG_PTR dwContinue
)
2705 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2707 FIXME("Stub: This=%p\n",This
);
2711 static HRESULT WINAPI
ISVViewObject_GetColorSet(
2716 DVTARGETDEVICE
* ptd
,
2717 HDC hicTargetDevice
,
2718 LOGPALETTE
** ppColorSet
)
2721 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2723 FIXME("Stub: This=%p\n",This
);
2727 static HRESULT WINAPI
ISVViewObject_Freeze(
2735 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2737 FIXME("Stub: This=%p\n",This
);
2741 static HRESULT WINAPI
ISVViewObject_Unfreeze(
2746 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2748 FIXME("Stub: This=%p\n",This
);
2752 static HRESULT WINAPI
ISVViewObject_SetAdvise(
2756 IAdviseSink
* pAdvSink
)
2759 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2761 FIXME("partial stub: %p %08x %08x %p\n",
2762 This
, aspects
, advf
, pAdvSink
);
2764 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2765 This
->pAdvSink
= pAdvSink
;
2766 This
->dwAspects
= aspects
;
2767 This
->dwAdvf
= advf
;
2772 static HRESULT WINAPI
ISVViewObject_GetAdvise(
2776 IAdviseSink
** ppAdvSink
)
2779 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2781 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2782 This
, pAspects
, pAdvf
, ppAdvSink
);
2786 IAdviseSink_AddRef( This
->pAdvSink
);
2787 *ppAdvSink
= This
->pAdvSink
;
2790 *pAspects
= This
->dwAspects
;
2792 *pAdvf
= This
->dwAdvf
;
2798 static const IViewObjectVtbl vovt
=
2800 ISVViewObject_QueryInterface
,
2801 ISVViewObject_AddRef
,
2802 ISVViewObject_Release
,
2804 ISVViewObject_GetColorSet
,
2805 ISVViewObject_Freeze
,
2806 ISVViewObject_Unfreeze
,
2807 ISVViewObject_SetAdvise
,
2808 ISVViewObject_GetAdvise