4 * Copyright 1998,1999 <juergen.schmied@debitel.net>
6 * This is the view visualizing the data provied by the shellfolder.
7 * No direct access to data from pidls should be done from here.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * FIXME: The order by part of the background context menu should be
24 * buily according to the columns shown.
26 * FIXME: Load/Save the view state from/into the stream provied by
29 * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
31 * FIXME: ShellView_FillList: consider sort orders
33 * FIXME: implement the drag and drop in the old (msg-based) way
35 * FIXME: when the ShellView_WndProc gets a WM_NCDESTROY should we do a
40 #include "wine/port.h"
47 #define NONAMELESSUNION
48 #define NONAMELESSSTRUCT
60 #include "undocshell.h"
62 #include "wine/debug.h"
66 #include "shell32_main.h"
67 #include "shellfolder.h"
69 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
75 }LISTVIEW_SORT_INFO
, *LPLISTVIEW_SORT_INFO
;
79 const IShellViewVtbl
* lpVtbl
;
81 const IOleCommandTargetVtbl
* lpvtblOleCommandTarget
;
82 const IDropTargetVtbl
* lpvtblDropTarget
;
83 const IDropSourceVtbl
* lpvtblDropSource
;
84 const IViewObjectVtbl
* lpvtblViewObject
;
85 IShellFolder
* pSFParent
;
86 IShellFolder2
* pSF2Parent
;
87 IShellBrowser
* pShellBrowser
;
88 ICommDlgBrowser
* pCommDlgBrowser
;
89 HWND hWnd
; /* SHELLDLL_DefView */
90 HWND hWndList
; /* ListView control */
92 FOLDERSETTINGS FolderSettings
;
97 LISTVIEW_SORT_INFO ListViewSortInfo
;
98 ULONG hNotify
; /* change notification handle */
102 IAdviseSink
*pAdvSink
;
103 IDropTarget
* pCurDropTarget
; /* The sub-item, which is currently dragged over */
104 IDataObject
* pCurDataObject
; /* The dragged data-object */
105 LONG iDragOverItem
; /* Dragged over item's index, iff pCurDropTarget != NULL */
106 UINT cScrollDelay
; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
107 POINT ptLastMousePos
; /* Mouse position at last DragOver call */
110 static const IShellViewVtbl svvt
;
111 static const IOleCommandTargetVtbl ctvt
;
112 static const IDropTargetVtbl dtvt
;
113 static const IDropSourceVtbl dsvt
;
114 static const IViewObjectVtbl vovt
;
117 static inline IShellViewImpl
*impl_from_IOleCommandTarget( IOleCommandTarget
*iface
)
119 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblOleCommandTarget
));
122 static inline IShellViewImpl
*impl_from_IDropTarget( IDropTarget
*iface
)
124 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblDropTarget
));
127 static inline IShellViewImpl
*impl_from_IDropSource( IDropSource
*iface
)
129 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblDropSource
));
132 static inline IShellViewImpl
*impl_from_IViewObject( IViewObject
*iface
)
134 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblViewObject
));
137 /* ListView Header ID's */
138 #define LISTVIEW_COLUMN_NAME 0
139 #define LISTVIEW_COLUMN_SIZE 1
140 #define LISTVIEW_COLUMN_TYPE 2
141 #define LISTVIEW_COLUMN_TIME 3
142 #define LISTVIEW_COLUMN_ATTRIB 4
145 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
146 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
147 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
149 #define ID_LISTVIEW 2000
151 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
154 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
155 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
156 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
159 Items merged into the toolbar and and the filemenu
168 } MYTOOLINFO
, *LPMYTOOLINFO
;
172 { FCIDM_SHVIEW_BIGICON
, 0, 0, IDS_VIEW_LARGE
, TBSTATE_ENABLED
, BTNS_BUTTON
},
173 { FCIDM_SHVIEW_SMALLICON
, 0, 0, IDS_VIEW_SMALL
, TBSTATE_ENABLED
, BTNS_BUTTON
},
174 { FCIDM_SHVIEW_LISTVIEW
, 0, 0, IDS_VIEW_LIST
, TBSTATE_ENABLED
, BTNS_BUTTON
},
175 { FCIDM_SHVIEW_REPORTVIEW
, 0, 0, IDS_VIEW_DETAILS
, TBSTATE_ENABLED
, BTNS_BUTTON
},
179 typedef void (CALLBACK
*PFNSHGETSETTINGSPROC
)(LPSHELLFLAGSTATE lpsfs
, DWORD dwMask
);
181 /**********************************************************
182 * IShellView_Constructor
184 IShellView
* IShellView_Constructor( IShellFolder
* pFolder
)
185 { IShellViewImpl
* sv
;
186 sv
=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IShellViewImpl
));
189 sv
->lpvtblOleCommandTarget
=&ctvt
;
190 sv
->lpvtblDropTarget
=&dtvt
;
191 sv
->lpvtblDropSource
=&dsvt
;
192 sv
->lpvtblViewObject
=&vovt
;
194 sv
->pSFParent
= pFolder
;
195 if(pFolder
) IShellFolder_AddRef(pFolder
);
196 IShellFolder_QueryInterface(sv
->pSFParent
, &IID_IShellFolder2
, (LPVOID
*)&sv
->pSF2Parent
);
198 sv
->pCurDropTarget
= NULL
;
199 sv
->pCurDataObject
= NULL
;
200 sv
->iDragOverItem
= 0;
201 sv
->cScrollDelay
= 0;
202 sv
->ptLastMousePos
.x
= 0;
203 sv
->ptLastMousePos
.y
= 0;
205 TRACE("(%p)->(%p)\n",sv
, pFolder
);
206 return (IShellView
*) sv
;
209 /**********************************************************
211 * ##### helperfunctions for communication with ICommDlgBrowser #####
213 static BOOL
IsInCommDlg(IShellViewImpl
* This
)
214 { return(This
->pCommDlgBrowser
!= NULL
);
217 static HRESULT
IncludeObject(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
221 if ( IsInCommDlg(This
) )
223 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl
);
224 ret
= ICommDlgBrowser_IncludeObject(This
->pCommDlgBrowser
, (IShellView
*)This
, pidl
);
225 TRACE("--0x%08lx\n", ret
);
230 static HRESULT
OnDefaultCommand(IShellViewImpl
* This
)
232 HRESULT ret
= S_FALSE
;
234 if (IsInCommDlg(This
))
236 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
237 ret
= ICommDlgBrowser_OnDefaultCommand(This
->pCommDlgBrowser
, (IShellView
*)This
);
238 TRACE("-- returns %08lx\n", ret
);
243 static HRESULT
OnStateChange(IShellViewImpl
* This
, UINT uFlags
)
245 HRESULT ret
= S_FALSE
;
247 if (IsInCommDlg(This
))
249 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags
);
250 ret
= ICommDlgBrowser_OnStateChange(This
->pCommDlgBrowser
, (IShellView
*)This
, uFlags
);
255 /**********************************************************
256 * set the toolbar of the filedialog buttons
258 * - activates the buttons from the shellbrowser according to
261 static void CheckToolbar(IShellViewImpl
* This
)
267 if (IsInCommDlg(This
))
269 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_CHECKBUTTON
,
270 FCIDM_TB_SMALLICON
, (This
->FolderSettings
.ViewMode
==FVM_LIST
)? TRUE
: FALSE
, &result
);
271 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_CHECKBUTTON
,
272 FCIDM_TB_REPORTVIEW
, (This
->FolderSettings
.ViewMode
==FVM_DETAILS
)? TRUE
: FALSE
, &result
);
273 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_ENABLEBUTTON
,
274 FCIDM_TB_SMALLICON
, TRUE
, &result
);
275 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_ENABLEBUTTON
,
276 FCIDM_TB_REPORTVIEW
, TRUE
, &result
);
280 /**********************************************************
282 * ##### helperfunctions for initializing the view #####
284 /**********************************************************
285 * change the style of the listview control
287 static void SetStyle(IShellViewImpl
* This
, DWORD dwAdd
, DWORD dwRemove
)
291 TRACE("(%p)\n", This
);
293 tmpstyle
= GetWindowLongA(This
->hWndList
, GWL_STYLE
);
294 SetWindowLongA(This
->hWndList
, GWL_STYLE
, dwAdd
| (tmpstyle
& ~dwRemove
));
297 /**********************************************************
298 * ShellView_CreateList()
300 * - creates the list view window
302 static BOOL
ShellView_CreateList (IShellViewImpl
* This
)
303 { DWORD dwStyle
, dwExStyle
;
307 dwStyle
= WS_TABSTOP
| WS_VISIBLE
| WS_CHILDWINDOW
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
308 LVS_SHAREIMAGELISTS
| LVS_EDITLABELS
| LVS_ALIGNLEFT
| LVS_AUTOARRANGE
;
309 dwExStyle
= WS_EX_CLIENTEDGE
;
311 switch (This
->FolderSettings
.ViewMode
)
313 case FVM_ICON
: dwStyle
|= LVS_ICON
; break;
314 case FVM_DETAILS
: dwStyle
|= LVS_REPORT
; break;
315 case FVM_SMALLICON
: dwStyle
|= LVS_SMALLICON
; break;
316 case FVM_LIST
: dwStyle
|= LVS_LIST
; break;
317 default: dwStyle
|= LVS_LIST
; break;
320 if (This
->FolderSettings
.fFlags
& FWF_AUTOARRANGE
) dwStyle
|= LVS_AUTOARRANGE
;
321 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
)
322 This
->FolderSettings
.fFlags
|= FWF_NOCLIENTEDGE
| FWF_NOSCROLL
;
323 if (This
->FolderSettings
.fFlags
& FWF_SINGLESEL
) dwStyle
|= LVS_SINGLESEL
;
324 if (This
->FolderSettings
.fFlags
& FWF_NOCLIENTEDGE
)
325 dwExStyle
&= ~WS_EX_CLIENTEDGE
;
327 This
->hWndList
=CreateWindowExA( dwExStyle
,
340 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
341 This
->ListViewSortInfo
.nHeaderID
= -1;
342 This
->ListViewSortInfo
.nLastHeaderID
= -1;
344 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
) {
345 if (0) /* FIXME: look into registry vale HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow and activate drop shadows */
346 ListView_SetTextBkColor(This
->hWndList
, CLR_NONE
);
348 ListView_SetTextBkColor(This
->hWndList
, GetSysColor(COLOR_DESKTOP
));
350 ListView_SetTextColor(This
->hWndList
, RGB(255,255,255));
353 /* UpdateShellSettings(); */
357 /**********************************************************
358 * ShellView_InitList()
360 * - adds all needed columns to the shellview
362 static BOOL
ShellView_InitList(IShellViewImpl
* This
)
371 ListView_DeleteAllItems(This
->hWndList
);
373 lvColumn
.mask
= LVCF_FMT
| LVCF_WIDTH
| LVCF_TEXT
;
374 lvColumn
.pszText
= szTemp
;
376 if (This
->pSF2Parent
)
380 if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This
->pSF2Parent
, NULL
, i
, &sd
)))
382 lvColumn
.fmt
= sd
.fmt
;
383 lvColumn
.cx
= sd
.cxChar
*8; /* chars->pixel */
384 StrRetToStrNA( szTemp
, 50, &sd
.str
, NULL
);
385 ListView_InsertColumnA(This
->hWndList
, i
, &lvColumn
);
393 ListView_SetImageList(This
->hWndList
, ShellSmallIconList
, LVSIL_SMALL
);
394 ListView_SetImageList(This
->hWndList
, ShellBigIconList
, LVSIL_NORMAL
);
398 /**********************************************************
399 * ShellView_CompareItems()
402 * internal, CALLBACK for DSA_Sort
404 static INT CALLBACK
ShellView_CompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
)
407 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1
, lParam2
, (LPVOID
) lpData
);
409 if(!lpData
) return 0;
411 ret
= (SHORT
) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER
)lpData
, 0, (LPITEMIDLIST
)lParam1
, (LPITEMIDLIST
)lParam2
));
412 TRACE("ret=%i\n",ret
);
416 /*************************************************************************
417 * ShellView_ListViewCompareItems
419 * Compare Function for the Listview (FileOpen Dialog)
422 * lParam1 [I] the first ItemIdList to compare with
423 * lParam2 [I] the second ItemIdList to compare with
424 * lpData [I] The column ID for the header Ctrl to process
427 * A negative value if the first item should precede the second,
428 * a positive value if the first item should follow the second,
429 * or zero if the two items are equivalent
432 * FIXME: function does what ShellView_CompareItems is supposed to do.
433 * unify it and figure out how to use the undocumented first parameter
434 * of IShellFolder_CompareIDs to do the job this function does and
435 * move this code to IShellFolder.
436 * make LISTVIEW_SORT_INFO obsolete
437 * the way this function works is only usable if we had only
438 * filesystemfolders (25/10/99 jsch)
440 static INT CALLBACK
ShellView_ListViewCompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
)
444 char strName1
[MAX_PATH
], strName2
[MAX_PATH
];
445 BOOL bIsFolder1
, bIsFolder2
,bIsBothFolder
;
446 LPITEMIDLIST pItemIdList1
= (LPITEMIDLIST
) lParam1
;
447 LPITEMIDLIST pItemIdList2
= (LPITEMIDLIST
) lParam2
;
448 LISTVIEW_SORT_INFO
*pSortInfo
= (LPLISTVIEW_SORT_INFO
) lpData
;
451 bIsFolder1
= _ILIsFolder(pItemIdList1
);
452 bIsFolder2
= _ILIsFolder(pItemIdList2
);
453 bIsBothFolder
= bIsFolder1
&& bIsFolder2
;
455 /* When sorting between a File and a Folder, the Folder gets sorted first */
456 if( (bIsFolder1
|| bIsFolder2
) && !bIsBothFolder
)
458 nDiff
= bIsFolder1
? -1 : 1;
462 /* Sort by Time: Folders or Files can be sorted */
464 if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_TIME
)
466 _ILGetFileDateTime(pItemIdList1
, &fd1
);
467 _ILGetFileDateTime(pItemIdList2
, &fd2
);
468 nDiff
= CompareFileTime(&fd2
, &fd1
);
470 /* Sort by Attribute: Folder or Files can be sorted */
471 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_ATTRIB
)
473 _ILGetFileAttributes(pItemIdList1
, strName1
, MAX_PATH
);
474 _ILGetFileAttributes(pItemIdList2
, strName2
, MAX_PATH
);
475 nDiff
= lstrcmpiA(strName1
, strName2
);
477 /* Sort by FileName: Folder or Files can be sorted */
478 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_NAME
|| bIsBothFolder
)
481 _ILSimpleGetText(pItemIdList1
, strName1
, MAX_PATH
);
482 _ILSimpleGetText(pItemIdList2
, strName2
, MAX_PATH
);
483 nDiff
= lstrcmpiA(strName1
, strName2
);
485 /* Sort by File Size, Only valid for Files */
486 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_SIZE
)
488 nDiff
= (INT
)(_ILGetFileSize(pItemIdList1
, NULL
, 0) - _ILGetFileSize(pItemIdList2
, NULL
, 0));
490 /* Sort by File Type, Only valid for Files */
491 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_TYPE
)
494 _ILGetFileType(pItemIdList1
, strName1
, MAX_PATH
);
495 _ILGetFileType(pItemIdList2
, strName2
, MAX_PATH
);
496 nDiff
= lstrcmpiA(strName1
, strName2
);
499 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
503 _ILSimpleGetText(pItemIdList1
, strName1
, MAX_PATH
);
504 _ILSimpleGetText(pItemIdList2
, strName2
, MAX_PATH
);
505 nDiff
= lstrcmpiA(strName1
, strName2
);
508 if(!pSortInfo
->bIsAscending
)
517 /**********************************************************
518 * LV_FindItemByPidl()
520 static int LV_FindItemByPidl(
521 IShellViewImpl
* This
,
525 ZeroMemory(&lvItem
, sizeof(LVITEMA
));
526 lvItem
.mask
= LVIF_PARAM
;
527 for(lvItem
.iItem
= 0; ListView_GetItemA(This
->hWndList
, &lvItem
); lvItem
.iItem
++)
529 LPITEMIDLIST currentpidl
= (LPITEMIDLIST
) lvItem
.lParam
;
530 HRESULT hr
= IShellFolder_CompareIDs(This
->pSFParent
, 0, pidl
, currentpidl
);
531 if(SUCCEEDED(hr
) && !HRESULT_CODE(hr
))
539 /**********************************************************
542 static BOOLEAN
LV_AddItem(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
546 TRACE("(%p)(pidl=%p)\n", This
, pidl
);
548 ZeroMemory(&lvItem
, sizeof(lvItem
)); /* create the listview item*/
549 lvItem
.mask
= LVIF_TEXT
| LVIF_IMAGE
| LVIF_PARAM
; /*set the mask*/
550 lvItem
.iItem
= ListView_GetItemCount(This
->hWndList
); /*add the item to the end of the list*/
551 lvItem
.lParam
= (LPARAM
) ILClone(ILFindLastID(pidl
)); /*set the item's data*/
552 lvItem
.pszText
= LPSTR_TEXTCALLBACKA
; /*get text on a callback basis*/
553 lvItem
.iImage
= I_IMAGECALLBACK
; /*get the image on a callback basis*/
554 return (-1==ListView_InsertItemA(This
->hWndList
, &lvItem
))? FALSE
: TRUE
;
557 /**********************************************************
560 static BOOLEAN
LV_DeleteItem(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
564 TRACE("(%p)(pidl=%p)\n", This
, pidl
);
566 nIndex
= LV_FindItemByPidl(This
, ILFindLastID(pidl
));
567 return (-1==ListView_DeleteItem(This
->hWndList
, nIndex
))? FALSE
: TRUE
;
570 /**********************************************************
573 static BOOLEAN
LV_RenameItem(IShellViewImpl
* This
, LPCITEMIDLIST pidlOld
, LPCITEMIDLIST pidlNew
)
578 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This
, pidlOld
, pidlNew
);
580 nItem
= LV_FindItemByPidl(This
, ILFindLastID(pidlOld
));
583 ZeroMemory(&lvItem
, sizeof(lvItem
)); /* create the listview item*/
584 lvItem
.mask
= LVIF_PARAM
; /* only the pidl */
585 lvItem
.iItem
= nItem
;
586 ListView_GetItemA(This
->hWndList
, &lvItem
);
588 SHFree((LPITEMIDLIST
)lvItem
.lParam
);
589 lvItem
.mask
= LVIF_PARAM
;
590 lvItem
.iItem
= nItem
;
591 lvItem
.lParam
= (LPARAM
) ILClone(ILFindLastID(pidlNew
)); /* set the item's data */
592 ListView_SetItemA(This
->hWndList
, &lvItem
);
593 ListView_Update(This
->hWndList
, nItem
);
594 return TRUE
; /* FIXME: better handling */
598 /**********************************************************
599 * ShellView_FillList()
601 * - gets the objectlist from the shellfolder
603 * - fills the list into the view
606 static INT CALLBACK
fill_list( LPVOID ptr
, LPVOID arg
)
608 LPITEMIDLIST pidl
= ptr
;
609 IShellViewImpl
*This
= arg
;
610 /* in a commdlg This works as a filemask*/
611 if ( IncludeObject(This
, pidl
)==S_OK
) LV_AddItem(This
, pidl
);
616 static HRESULT
ShellView_FillList(IShellViewImpl
* This
)
618 LPENUMIDLIST pEnumIDList
;
626 /* get the itemlist from the shfolder*/
627 hRes
= IShellFolder_EnumObjects(This
->pSFParent
,This
->hWnd
, SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
, &pEnumIDList
);
635 /* create a pointer array */
636 hdpa
= DPA_Create(16);
639 return(E_OUTOFMEMORY
);
642 /* copy the items into the array*/
643 while((S_OK
== IEnumIDList_Next(pEnumIDList
,1, &pidl
, &dwFetched
)) && dwFetched
)
645 if (DPA_InsertPtr(hdpa
, 0x7fff, pidl
) == -1)
652 DPA_Sort(hdpa
, ShellView_CompareItems
, (LPARAM
)This
->pSFParent
);
654 /*turn the listview's redrawing off*/
655 SendMessageA(This
->hWndList
, WM_SETREDRAW
, FALSE
, 0);
657 DPA_DestroyCallback( hdpa
, fill_list
, This
);
659 /*turn the listview's redrawing back on and force it to draw*/
660 SendMessageA(This
->hWndList
, WM_SETREDRAW
, TRUE
, 0);
662 IEnumIDList_Release(pEnumIDList
); /* destroy the list*/
667 /**********************************************************
668 * ShellView_OnCreate()
670 static LRESULT
ShellView_OnCreate(IShellViewImpl
* This
)
673 SHChangeNotifyEntry ntreg
;
674 IPersistFolder2
* ppf2
= NULL
;
678 if(ShellView_CreateList(This
))
680 if(ShellView_InitList(This
))
682 ShellView_FillList(This
);
686 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown
*)&This
->lpVtbl
, &IID_IDropTarget
, (LPVOID
*)&pdt
)))
688 RegisterDragDrop(This
->hWnd
, pdt
);
689 IDropTarget_Release(pdt
);
692 /* register for receiving notifications */
693 IShellFolder_QueryInterface(This
->pSFParent
, &IID_IPersistFolder2
, (LPVOID
*)&ppf2
);
696 IPersistFolder2_GetCurFolder(ppf2
, (LPITEMIDLIST
*)&ntreg
.pidl
);
697 ntreg
.fRecursive
= TRUE
;
698 This
->hNotify
= SHChangeNotifyRegister(This
->hWnd
, SHCNF_IDLIST
, SHCNE_ALLEVENTS
, SHV_CHANGE_NOTIFY
, 1, &ntreg
);
699 SHFree((LPITEMIDLIST
)ntreg
.pidl
);
700 IPersistFolder2_Release(ppf2
);
703 This
->hAccel
= LoadAcceleratorsA(shell32_hInstance
, "shv_accel");
708 /**********************************************************
709 * #### Handling of the menus ####
712 /**********************************************************
713 * ShellView_BuildFileMenu()
715 static HMENU
ShellView_BuildFileMenu(IShellViewImpl
* This
)
716 { CHAR szText
[MAX_PATH
];
721 TRACE("(%p)\n",This
);
723 hSubMenu
= CreatePopupMenu();
725 { /*get the number of items in our global array*/
726 for(nTools
= 0; Tools
[nTools
].idCommand
!= -1; nTools
++){}
728 /*add the menu items*/
729 for(i
= 0; i
< nTools
; i
++)
731 LoadStringA(shell32_hInstance
, Tools
[i
].idMenuString
, szText
, MAX_PATH
);
733 ZeroMemory(&mii
, sizeof(mii
));
734 mii
.cbSize
= sizeof(mii
);
735 mii
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
737 if(BTNS_SEP
!= Tools
[i
].bStyle
) /* no separator*/
739 mii
.fType
= MFT_STRING
;
740 mii
.fState
= MFS_ENABLED
;
741 mii
.dwTypeData
= szText
;
742 mii
.wID
= Tools
[i
].idCommand
;
746 mii
.fType
= MFT_SEPARATOR
;
748 /* tack This item onto the end of the menu */
749 InsertMenuItemA(hSubMenu
, (UINT
)-1, TRUE
, &mii
);
752 TRACE("-- return (menu=%p)\n",hSubMenu
);
755 /**********************************************************
756 * ShellView_MergeFileMenu()
758 static void ShellView_MergeFileMenu(IShellViewImpl
* This
, HMENU hSubMenu
)
759 { TRACE("(%p)->(submenu=%p) stub\n",This
,hSubMenu
);
762 { /*insert This item at the beginning of the menu */
763 _InsertMenuItem(hSubMenu
, 0, TRUE
, 0, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
764 _InsertMenuItem(hSubMenu
, 0, TRUE
, IDM_MYFILEITEM
, MFT_STRING
, "dummy45", MFS_ENABLED
);
770 /**********************************************************
771 * ShellView_MergeViewMenu()
774 static void ShellView_MergeViewMenu(IShellViewImpl
* This
, HMENU hSubMenu
)
777 TRACE("(%p)->(submenu=%p)\n",This
,hSubMenu
);
780 { /*add a separator at the correct position in the menu*/
781 _InsertMenuItem(hSubMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
, FALSE
, 0, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
783 ZeroMemory(&mii
, sizeof(mii
));
784 mii
.cbSize
= sizeof(mii
);
785 mii
.fMask
= MIIM_SUBMENU
| MIIM_TYPE
| MIIM_DATA
;
786 mii
.fType
= MFT_STRING
;
787 mii
.dwTypeData
= "View";
788 mii
.hSubMenu
= LoadMenuA(shell32_hInstance
, "MENU_001");
789 InsertMenuItemA(hSubMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
, FALSE
, &mii
);
793 /**********************************************************
794 * ShellView_GetSelections()
796 * - fills the this->apidl list with the selected objects
799 * number of selected items
801 static UINT
ShellView_GetSelections(IShellViewImpl
* This
)
811 This
->cidl
= ListView_GetSelectedCount(This
->hWndList
);
812 This
->apidl
= (LPITEMIDLIST
*)SHAlloc(This
->cidl
* sizeof(LPITEMIDLIST
));
814 TRACE("selected=%i\n", This
->cidl
);
818 TRACE("-- Items selected =%u\n", This
->cidl
);
820 ZeroMemory(&lvItem
, sizeof(lvItem
));
821 lvItem
.mask
= LVIF_STATE
| LVIF_PARAM
;
822 lvItem
.stateMask
= LVIS_SELECTED
;
824 while(ListView_GetItemA(This
->hWndList
, &lvItem
) && (i
< This
->cidl
))
826 if(lvItem
.state
& LVIS_SELECTED
)
828 This
->apidl
[i
] = (LPITEMIDLIST
)lvItem
.lParam
;
830 TRACE("-- selected Item found\n");
839 /**********************************************************
840 * ShellView_OpenSelectedItems()
842 static HRESULT
ShellView_OpenSelectedItems(IShellViewImpl
* This
)
844 static UINT CF_IDLIST
= 0;
846 IDataObject
* selection
;
850 LPCITEMIDLIST parent_pidl
;
853 if (0 == ShellView_GetSelections(This
))
857 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
,
858 (LPCITEMIDLIST
*)This
->apidl
, &IID_IDataObject
,
859 0, (LPVOID
*)&selection
);
865 CF_IDLIST
= RegisterClipboardFormatA(CFSTR_SHELLIDLIST
);
867 fetc
.cfFormat
= CF_IDLIST
;
869 fetc
.dwAspect
= DVASPECT_CONTENT
;
871 fetc
.tymed
= TYMED_HGLOBAL
;
873 hr
= IDataObject_QueryGetData(selection
, &fetc
);
877 hr
= IDataObject_GetData(selection
, &fetc
, &stgm
);
881 pIDList
= GlobalLock(stgm
.u
.hGlobal
);
883 parent_pidl
= (LPCITEMIDLIST
) ((LPBYTE
)pIDList
+pIDList
->aoffset
[0]);
884 for (i
= pIDList
->cidl
; i
> 0; --i
)
889 pidl
= (LPCITEMIDLIST
)((LPBYTE
)pIDList
+pIDList
->aoffset
[i
]);
891 attribs
= SFGAO_FOLDER
;
892 hr
= IShellFolder_GetAttributesOf(This
->pSFParent
, 1, &pidl
, &attribs
);
894 if (SUCCEEDED(hr
) && ! (attribs
& SFGAO_FOLDER
))
896 SHELLEXECUTEINFOA shexinfo
;
898 shexinfo
.cbSize
= sizeof(SHELLEXECUTEINFOA
);
899 shexinfo
.fMask
= SEE_MASK_INVOKEIDLIST
; /* SEE_MASK_IDLIST is also possible. */
900 shexinfo
.hwnd
= NULL
;
901 shexinfo
.lpVerb
= NULL
;
902 shexinfo
.lpFile
= NULL
;
903 shexinfo
.lpParameters
= NULL
;
904 shexinfo
.lpDirectory
= NULL
;
905 shexinfo
.nShow
= SW_NORMAL
;
906 shexinfo
.lpIDList
= ILCombine(parent_pidl
, pidl
);
908 ShellExecuteExA(&shexinfo
); /* Discard error/success info */
910 ILFree((LPITEMIDLIST
)shexinfo
.lpIDList
);
914 GlobalUnlock(stgm
.u
.hGlobal
);
915 ReleaseStgMedium(&stgm
);
917 IDataObject_Release(selection
);
922 /**********************************************************
923 * ShellView_DoContextMenu()
925 static void ShellView_DoContextMenu(IShellViewImpl
* This
, WORD x
, WORD y
, BOOL bDefault
)
929 BOOL fExplore
= FALSE
;
931 LPCONTEXTMENU pContextMenu
= NULL
;
932 IContextMenu2
*pCM
= NULL
;
933 CMINVOKECOMMANDINFO cmi
;
935 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This
, x
, y
, bDefault
);
937 /* look, what's selected and create a context menu object of it*/
938 if( ShellView_GetSelections(This
) )
940 IShellFolder_GetUIObjectOf( This
->pSFParent
, This
->hWndParent
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
,
941 (REFIID
)&IID_IContextMenu
, NULL
, (LPVOID
*)&pContextMenu
);
945 TRACE("-- pContextMenu\n");
946 hMenu
= CreatePopupMenu();
950 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
951 if(SUCCEEDED(IShellBrowser_GetControlWindow(This
->pShellBrowser
,FCW_TREE
, &hwndTree
)) && hwndTree
)
953 TRACE("-- explore mode\n");
957 /* build the flags depending on what we can do with the selected item */
958 wFlags
= CMF_NORMAL
| (This
->cidl
!= 1 ? 0 : CMF_CANRENAME
) | (fExplore
? CMF_EXPLORE
: 0);
960 /* let the ContextMenu merge its items in */
961 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu
, hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, wFlags
)))
963 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
)
964 SetMenuDefaultItem(hMenu
, FCIDM_SHVIEW_OPEN
, MF_BYCOMMAND
);
968 TRACE("-- get menu default command\n");
969 uCommand
= GetMenuDefaultItem(hMenu
, FALSE
, GMDI_GOINTOPOPUPS
);
973 TRACE("-- track popup\n");
974 uCommand
= TrackPopupMenu( hMenu
,TPM_LEFTALIGN
| TPM_RETURNCMD
,x
,y
,0,This
->hWnd
,NULL
);
979 TRACE("-- uCommand=%u\n", uCommand
);
980 if (uCommand
==FCIDM_SHVIEW_OPEN
&& IsInCommDlg(This
))
982 TRACE("-- dlg: OnDefaultCommand\n");
983 if (OnDefaultCommand(This
) != S_OK
)
985 ShellView_OpenSelectedItems(This
);
990 TRACE("-- explore -- invoke command\n");
991 ZeroMemory(&cmi
, sizeof(cmi
));
992 cmi
.cbSize
= sizeof(cmi
);
993 cmi
.hwnd
= This
->hWndParent
; /* this window has to answer CWM_GETISHELLBROWSER */
994 cmi
.lpVerb
= (LPCSTR
)MAKEINTRESOURCEA(uCommand
);
995 IContextMenu_InvokeCommand(pContextMenu
, &cmi
);
1002 IContextMenu_Release(pContextMenu
);
1005 else /* background context menu */
1007 hMenu
= CreatePopupMenu();
1009 pCM
= ISvBgCm_Constructor(This
->pSFParent
, FALSE
);
1010 IContextMenu2_QueryContextMenu(pCM
, hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, 0);
1012 uCommand
= TrackPopupMenu( hMenu
, TPM_LEFTALIGN
| TPM_RETURNCMD
,x
,y
,0,This
->hWnd
,NULL
);
1015 TRACE("-- (%p)->(uCommand=0x%08x )\n",This
, uCommand
);
1017 ZeroMemory(&cmi
, sizeof(cmi
));
1018 cmi
.cbSize
= sizeof(cmi
);
1019 cmi
.lpVerb
= (LPCSTR
)MAKEINTRESOURCEA(uCommand
);
1020 cmi
.hwnd
= This
->hWndParent
;
1021 IContextMenu2_InvokeCommand(pCM
, &cmi
);
1023 IContextMenu2_Release(pCM
);
1027 /**********************************************************
1028 * ##### message handling #####
1031 /**********************************************************
1032 * ShellView_OnSize()
1034 static LRESULT
ShellView_OnSize(IShellViewImpl
* This
, WORD wWidth
, WORD wHeight
)
1036 TRACE("%p width=%u height=%u\n",This
, wWidth
,wHeight
);
1038 /*resize the ListView to fit our window*/
1041 MoveWindow(This
->hWndList
, 0, 0, wWidth
, wHeight
, TRUE
);
1046 /**********************************************************
1047 * ShellView_OnDeactivate()
1052 static void ShellView_OnDeactivate(IShellViewImpl
* This
)
1056 if(This
->uState
!= SVUIA_DEACTIVATE
)
1060 IShellBrowser_SetMenuSB(This
->pShellBrowser
,0, 0, 0);
1061 IShellBrowser_RemoveMenusSB(This
->pShellBrowser
,This
->hMenu
);
1062 DestroyMenu(This
->hMenu
);
1066 This
->uState
= SVUIA_DEACTIVATE
;
1070 /**********************************************************
1071 * ShellView_OnActivate()
1073 static LRESULT
ShellView_OnActivate(IShellViewImpl
* This
, UINT uState
)
1074 { OLEMENUGROUPWIDTHS omw
= { {0, 0, 0, 0, 0, 0} };
1076 CHAR szText
[MAX_PATH
];
1078 TRACE("%p uState=%x\n",This
,uState
);
1080 /*don't do anything if the state isn't really changing */
1081 if(This
->uState
== uState
)
1086 ShellView_OnDeactivate(This
);
1088 /*only do This if we are active */
1089 if(uState
!= SVUIA_DEACTIVATE
)
1091 /*merge the menus */
1092 This
->hMenu
= CreateMenu();
1096 IShellBrowser_InsertMenusSB(This
->pShellBrowser
, This
->hMenu
, &omw
);
1097 TRACE("-- after fnInsertMenusSB\n");
1099 /*build the top level menu get the menu item's text*/
1100 strcpy(szText
,"dummy 31");
1102 ZeroMemory(&mii
, sizeof(mii
));
1103 mii
.cbSize
= sizeof(mii
);
1104 mii
.fMask
= MIIM_SUBMENU
| MIIM_TYPE
| MIIM_STATE
;
1105 mii
.fType
= MFT_STRING
;
1106 mii
.fState
= MFS_ENABLED
;
1107 mii
.dwTypeData
= szText
;
1108 mii
.hSubMenu
= ShellView_BuildFileMenu(This
);
1110 /*insert our menu into the menu bar*/
1113 InsertMenuItemA(This
->hMenu
, FCIDM_MENU_HELP
, FALSE
, &mii
);
1116 /*get the view menu so we can merge with it*/
1117 ZeroMemory(&mii
, sizeof(mii
));
1118 mii
.cbSize
= sizeof(mii
);
1119 mii
.fMask
= MIIM_SUBMENU
;
1121 if(GetMenuItemInfoA(This
->hMenu
, FCIDM_MENU_VIEW
, FALSE
, &mii
))
1123 ShellView_MergeViewMenu(This
, mii
.hSubMenu
);
1126 /*add the items that should only be added if we have the focus*/
1127 if(SVUIA_ACTIVATE_FOCUS
== uState
)
1129 /*get the file menu so we can merge with it */
1130 ZeroMemory(&mii
, sizeof(mii
));
1131 mii
.cbSize
= sizeof(mii
);
1132 mii
.fMask
= MIIM_SUBMENU
;
1134 if(GetMenuItemInfoA(This
->hMenu
, FCIDM_MENU_FILE
, FALSE
, &mii
))
1136 ShellView_MergeFileMenu(This
, mii
.hSubMenu
);
1139 TRACE("-- before fnSetMenuSB\n");
1140 IShellBrowser_SetMenuSB(This
->pShellBrowser
, This
->hMenu
, 0, This
->hWnd
);
1143 This
->uState
= uState
;
1148 /**********************************************************
1149 * ShellView_OnSetFocus()
1152 static LRESULT
ShellView_OnSetFocus(IShellViewImpl
* This
)
1156 /* Tell the browser one of our windows has received the focus. This
1157 should always be done before merging menus (OnActivate merges the
1158 menus) if one of our windows has the focus.*/
1160 IShellBrowser_OnViewWindowActive(This
->pShellBrowser
,(IShellView
*) This
);
1161 ShellView_OnActivate(This
, SVUIA_ACTIVATE_FOCUS
);
1163 /* Set the focus to the listview */
1164 SetFocus(This
->hWndList
);
1166 /* Notify the ICommDlgBrowser interface */
1167 OnStateChange(This
,CDBOSC_SETFOCUS
);
1172 /**********************************************************
1173 * ShellView_OnKillFocus()
1175 static LRESULT
ShellView_OnKillFocus(IShellViewImpl
* This
)
1177 TRACE("(%p) stub\n",This
);
1179 ShellView_OnActivate(This
, SVUIA_ACTIVATE_NOFOCUS
);
1180 /* Notify the ICommDlgBrowser */
1181 OnStateChange(This
,CDBOSC_KILLFOCUS
);
1186 /**********************************************************
1187 * ShellView_OnCommand()
1190 * the CmdID's are the ones from the context menu
1192 static LRESULT
ShellView_OnCommand(IShellViewImpl
* This
,DWORD dwCmdID
, DWORD dwCmd
, HWND hwndCmd
)
1194 TRACE("(%p)->(0x%08lx 0x%08lx %p) stub\n",This
, dwCmdID
, dwCmd
, hwndCmd
);
1198 case FCIDM_SHVIEW_SMALLICON
:
1199 This
->FolderSettings
.ViewMode
= FVM_SMALLICON
;
1200 SetStyle (This
, LVS_SMALLICON
, LVS_TYPEMASK
);
1204 case FCIDM_SHVIEW_BIGICON
:
1205 This
->FolderSettings
.ViewMode
= FVM_ICON
;
1206 SetStyle (This
, LVS_ICON
, LVS_TYPEMASK
);
1210 case FCIDM_SHVIEW_LISTVIEW
:
1211 This
->FolderSettings
.ViewMode
= FVM_LIST
;
1212 SetStyle (This
, LVS_LIST
, LVS_TYPEMASK
);
1216 case FCIDM_SHVIEW_REPORTVIEW
:
1217 This
->FolderSettings
.ViewMode
= FVM_DETAILS
;
1218 SetStyle (This
, LVS_REPORT
, LVS_TYPEMASK
);
1222 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1227 This
->ListViewSortInfo
.nHeaderID
= (LPARAM
) (dwCmdID
- 0x30);
1228 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
1229 This
->ListViewSortInfo
.nLastHeaderID
= This
->ListViewSortInfo
.nHeaderID
;
1230 ListView_SortItems(This
->hWndList
, ShellView_ListViewCompareItems
, (LPARAM
) (&(This
->ListViewSortInfo
)));
1234 TRACE("-- COMMAND 0x%04lx unhandled\n", dwCmdID
);
1239 /**********************************************************
1240 * ShellView_OnNotify()
1243 static LRESULT
ShellView_OnNotify(IShellViewImpl
* This
, UINT CtlID
, LPNMHDR lpnmh
)
1244 { LPNMLISTVIEW lpnmlv
= (LPNMLISTVIEW
)lpnmh
;
1245 NMLVDISPINFOA
*lpdi
= (NMLVDISPINFOA
*)lpnmh
;
1248 TRACE("%p CtlID=%u lpnmh->code=%x\n",This
,CtlID
,lpnmh
->code
);
1253 TRACE("-- NM_SETFOCUS %p\n",This
);
1254 ShellView_OnSetFocus(This
);
1258 TRACE("-- NM_KILLFOCUS %p\n",This
);
1259 ShellView_OnDeactivate(This
);
1260 /* Notify the ICommDlgBrowser interface */
1261 OnStateChange(This
,CDBOSC_KILLFOCUS
);
1265 TRACE("-- NM_CUSTOMDRAW %p\n",This
);
1266 return CDRF_DODEFAULT
;
1268 case NM_RELEASEDCAPTURE
:
1269 TRACE("-- NM_RELEASEDCAPTURE %p\n",This
);
1273 TRACE("-- NM_CLICK %p\n",This
);
1277 TRACE("-- NM_RCLICK %p\n",This
);
1281 TRACE("-- NM_DBLCLK %p\n",This
);
1282 if (OnDefaultCommand(This
) != S_OK
) ShellView_OpenSelectedItems(This
);
1286 TRACE("-- NM_DBLCLK %p\n",This
);
1287 if (OnDefaultCommand(This
) != S_OK
) ShellView_OpenSelectedItems(This
);
1291 TRACE("-- HDN_ENDTRACKA %p\n",This
);
1292 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1293 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1296 case LVN_DELETEITEM
:
1297 TRACE("-- LVN_DELETEITEM %p\n",This
);
1298 SHFree((LPITEMIDLIST
)lpnmlv
->lParam
); /*delete the pidl because we made a copy of it*/
1301 case LVN_DELETEALLITEMS
:
1302 TRACE("-- LVN_DELETEALLITEMS %p\n",This
);
1305 case LVN_INSERTITEM
:
1306 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This
);
1309 case LVN_ITEMACTIVATE
:
1310 TRACE("-- LVN_ITEMACTIVATE %p\n",This
);
1311 OnStateChange(This
, CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1314 case LVN_COLUMNCLICK
:
1315 This
->ListViewSortInfo
.nHeaderID
= lpnmlv
->iSubItem
;
1316 if(This
->ListViewSortInfo
.nLastHeaderID
== This
->ListViewSortInfo
.nHeaderID
)
1318 This
->ListViewSortInfo
.bIsAscending
= !This
->ListViewSortInfo
.bIsAscending
;
1322 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
1324 This
->ListViewSortInfo
.nLastHeaderID
= This
->ListViewSortInfo
.nHeaderID
;
1326 ListView_SortItems(lpnmlv
->hdr
.hwndFrom
, ShellView_ListViewCompareItems
, (LPARAM
) (&(This
->ListViewSortInfo
)));
1329 case LVN_GETDISPINFOA
:
1330 case LVN_GETDISPINFOW
:
1331 TRACE("-- LVN_GETDISPINFO %p\n",This
);
1332 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1334 if(lpdi
->item
.mask
& LVIF_TEXT
) /* text requested */
1336 if (This
->pSF2Parent
)
1339 IShellFolder2_GetDetailsOf(This
->pSF2Parent
, pidl
, lpdi
->item
.iSubItem
, &sd
);
1340 if (lpnmh
->code
== LVN_GETDISPINFOA
)
1342 StrRetToStrNA( lpdi
->item
.pszText
, lpdi
->item
.cchTextMax
, &sd
.str
, NULL
);
1343 TRACE("-- text=%s\n",lpdi
->item
.pszText
);
1345 else /* LVN_GETDISPINFOW */
1347 StrRetToStrNW( ((NMLVDISPINFOW
*)lpdi
)->item
.pszText
, lpdi
->item
.cchTextMax
, &sd
.str
, NULL
);
1348 TRACE("-- text=%s\n",debugstr_w((WCHAR
*)(lpdi
->item
.pszText
)));
1356 if(lpdi
->item
.mask
& LVIF_IMAGE
) /* image requested */
1358 lpdi
->item
.iImage
= SHMapPIDLToSystemImageListIndex(This
->pSFParent
, pidl
, 0);
1362 case LVN_ITEMCHANGED
:
1363 TRACE("-- LVN_ITEMCHANGED %p\n",This
);
1364 OnStateChange(This
, CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1368 case LVN_BEGINRDRAG
:
1369 TRACE("-- LVN_BEGINDRAG\n");
1371 if (ShellView_GetSelections(This
))
1374 DWORD dwAttributes
= SFGAO_CANLINK
;
1375 DWORD dwEffect
= DROPEFFECT_COPY
| DROPEFFECT_MOVE
;
1377 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, &IID_IDataObject
,0,(LPVOID
*)&pda
)))
1379 IDropSource
* pds
= (IDropSource
*)&(This
->lpvtblDropSource
); /* own DropSource interface */
1381 if (SUCCEEDED(IShellFolder_GetAttributesOf(This
->pSFParent
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, &dwAttributes
)))
1383 if (dwAttributes
& SFGAO_CANLINK
)
1385 dwEffect
|= DROPEFFECT_LINK
;
1392 DoDragDrop(pda
, pds
, dwEffect
, &dwEffect
);
1394 IDataObject_Release(pda
);
1399 case LVN_BEGINLABELEDITA
:
1401 DWORD dwAttr
= SFGAO_CANRENAME
;
1402 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1404 TRACE("-- LVN_BEGINLABELEDITA %p\n",This
);
1406 IShellFolder_GetAttributesOf(This
->pSFParent
, 1, (LPCITEMIDLIST
*)&pidl
, &dwAttr
);
1407 if (SFGAO_CANRENAME
& dwAttr
)
1414 case LVN_ENDLABELEDITA
:
1416 TRACE("-- LVN_ENDLABELEDITA %p\n",This
);
1417 if (lpdi
->item
.pszText
)
1420 WCHAR wszNewName
[MAX_PATH
];
1423 ZeroMemory(&lvItem
, sizeof(LVITEMA
));
1424 lvItem
.iItem
= lpdi
->item
.iItem
;
1425 lvItem
.mask
= LVIF_PARAM
;
1426 ListView_GetItemA(This
->hWndList
, &lvItem
);
1428 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1429 if (!MultiByteToWideChar( CP_ACP
, 0, lpdi
->item
.pszText
, -1, wszNewName
, MAX_PATH
))
1430 wszNewName
[MAX_PATH
-1] = 0;
1431 hr
= IShellFolder_SetNameOf(This
->pSFParent
, 0, pidl
, wszNewName
, SHGDN_INFOLDER
, &pidl
);
1433 if(SUCCEEDED(hr
) && pidl
)
1435 lvItem
.mask
= LVIF_PARAM
;
1436 lvItem
.lParam
= (LPARAM
)pidl
;
1437 ListView_SetItemA(This
->hWndList
, &lvItem
);
1447 msg.hwnd = This->hWnd;
1448 msg.message = WM_KEYDOWN;
1449 msg.wParam = plvKeyDown->wVKey;
1454 LPNMLVKEYDOWN plvKeyDown
= (LPNMLVKEYDOWN
) lpnmh
;
1456 /* initiate a rename of the selected file or directory */
1457 if(plvKeyDown
->wVKey
== VK_F2
)
1459 /* see how many files are selected */
1460 int i
= ListView_GetSelectedCount(This
->hWndList
);
1462 /* get selected item */
1465 /* get selected item */
1466 i
= ListView_GetNextItem(This
->hWndList
, -1,
1469 ListView_EnsureVisible(This
->hWndList
, i
, 0);
1470 ListView_EditLabelA(This
->hWndList
, i
);
1474 TranslateAccelerator(This
->hWnd
, This
->hAccel
, &msg
)
1476 else if(plvKeyDown
->wVKey
== VK_DELETE
)
1481 LPITEMIDLIST
* pItems
;
1484 IShellFolder_QueryInterface(This
->pSFParent
, &IID_ISFHelper
,
1490 if(!(i
= ListView_GetSelectedCount(This
->hWndList
)))
1493 /* allocate memory for the pidl array */
1494 pItems
= HeapAlloc(GetProcessHeap(), 0,
1495 sizeof(LPITEMIDLIST
) * i
);
1497 /* retrieve all selected items */
1500 while(ListView_GetSelectedCount(This
->hWndList
) > i
)
1502 /* get selected item */
1503 item_index
= ListView_GetNextItem(This
->hWndList
,
1504 item_index
, LVNI_SELECTED
);
1505 item
.iItem
= item_index
;
1506 item
.mask
|= LVIF_PARAM
;
1507 ListView_GetItemA(This
->hWndList
, &item
);
1510 pItems
[i
] = (LPITEMIDLIST
)item
.lParam
;
1515 /* perform the item deletion */
1516 ISFHelper_DeleteItems(psfhlp
, i
, (LPCITEMIDLIST
*)pItems
);
1518 /* free pidl array memory */
1519 HeapFree(GetProcessHeap(), 0, pItems
);
1522 /* Initiate a refresh */
1523 else if(plvKeyDown
->wVKey
== VK_F5
)
1525 IShellView_Refresh((IShellView
*)This
);
1529 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown
->wVKey
);
1534 TRACE("-- %p WM_COMMAND %x unhandled\n", This
, lpnmh
->code
);
1540 /**********************************************************
1541 * ShellView_OnChange()
1544 static LRESULT
ShellView_OnChange(IShellViewImpl
* This
, LPITEMIDLIST
* Pidls
, LONG wEventId
)
1547 TRACE("(%p)(%p,%p,0x%08lx)\n", This
, Pidls
[0], Pidls
[1], wEventId
);
1552 LV_AddItem(This
, Pidls
[0]);
1556 LV_DeleteItem(This
, Pidls
[0]);
1558 case SHCNE_RENAMEFOLDER
:
1559 case SHCNE_RENAMEITEM
:
1560 LV_RenameItem(This
, Pidls
[0], Pidls
[1]);
1562 case SHCNE_UPDATEITEM
:
1567 /**********************************************************
1571 static LRESULT CALLBACK
ShellView_WndProc(HWND hWnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
)
1573 IShellViewImpl
* pThis
= (IShellViewImpl
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
1574 LPCREATESTRUCTA lpcs
;
1576 TRACE("(hwnd=%p msg=%x wparm=%x lparm=%lx)\n",hWnd
, uMessage
, wParam
, lParam
);
1581 lpcs
= (LPCREATESTRUCTA
)lParam
;
1582 pThis
= (IShellViewImpl
*)(lpcs
->lpCreateParams
);
1583 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (ULONG_PTR
)pThis
);
1584 pThis
->hWnd
= hWnd
; /*set the window handle*/
1587 case WM_SIZE
: return ShellView_OnSize(pThis
,LOWORD(lParam
), HIWORD(lParam
));
1588 case WM_SETFOCUS
: return ShellView_OnSetFocus(pThis
);
1589 case WM_KILLFOCUS
: return ShellView_OnKillFocus(pThis
);
1590 case WM_CREATE
: return ShellView_OnCreate(pThis
);
1591 case WM_ACTIVATE
: return ShellView_OnActivate(pThis
, SVUIA_ACTIVATE_FOCUS
);
1592 case WM_NOTIFY
: return ShellView_OnNotify(pThis
,(UINT
)wParam
, (LPNMHDR
)lParam
);
1593 case WM_COMMAND
: return ShellView_OnCommand(pThis
,
1594 GET_WM_COMMAND_ID(wParam
, lParam
),
1595 GET_WM_COMMAND_CMD(wParam
, lParam
),
1596 GET_WM_COMMAND_HWND(wParam
, lParam
));
1597 case SHV_CHANGE_NOTIFY
: return ShellView_OnChange(pThis
, (LPITEMIDLIST
*)wParam
, (LONG
)lParam
);
1599 case WM_CONTEXTMENU
: ShellView_DoContextMenu(pThis
, LOWORD(lParam
), HIWORD(lParam
), FALSE
);
1602 case WM_SHOWWINDOW
: UpdateWindow(pThis
->hWndList
);
1605 case WM_GETDLGCODE
: return SendMessageA(pThis
->hWndList
,uMessage
,0,0);
1608 RevokeDragDrop(pThis
->hWnd
);
1609 SHChangeNotifyDeregister(pThis
->hNotify
);
1613 if ((pThis
->FolderSettings
.fFlags
& FWF_DESKTOP
) ||
1614 (pThis
->FolderSettings
.fFlags
& FWF_TRANSPARENT
))
1619 return DefWindowProcA (hWnd
, uMessage
, wParam
, lParam
);
1621 /**********************************************************
1624 * The INTERFACE of the IShellView object
1627 **********************************************************
1628 * IShellView_QueryInterface
1630 static HRESULT WINAPI
IShellView_fnQueryInterface(IShellView
* iface
,REFIID riid
, LPVOID
*ppvObj
)
1632 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1634 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
1638 if(IsEqualIID(riid
, &IID_IUnknown
))
1642 else if(IsEqualIID(riid
, &IID_IShellView
))
1644 *ppvObj
= (IShellView
*)This
;
1646 else if(IsEqualIID(riid
, &IID_IOleCommandTarget
))
1648 *ppvObj
= (IOleCommandTarget
*)&(This
->lpvtblOleCommandTarget
);
1650 else if(IsEqualIID(riid
, &IID_IDropTarget
))
1652 *ppvObj
= (IDropTarget
*)&(This
->lpvtblDropTarget
);
1654 else if(IsEqualIID(riid
, &IID_IDropSource
))
1656 *ppvObj
= (IDropSource
*)&(This
->lpvtblDropSource
);
1658 else if(IsEqualIID(riid
, &IID_IViewObject
))
1660 *ppvObj
= (IViewObject
*)&(This
->lpvtblViewObject
);
1665 IUnknown_AddRef( (IUnknown
*)*ppvObj
);
1666 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
1669 TRACE("-- Interface: E_NOINTERFACE\n");
1670 return E_NOINTERFACE
;
1673 /**********************************************************
1676 static ULONG WINAPI
IShellView_fnAddRef(IShellView
* iface
)
1678 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1679 ULONG refCount
= InterlockedIncrement(&This
->ref
);
1681 TRACE("(%p)->(count=%lu)\n", This
, refCount
- 1);
1685 /**********************************************************
1686 * IShellView_Release
1688 static ULONG WINAPI
IShellView_fnRelease(IShellView
* iface
)
1690 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1691 ULONG refCount
= InterlockedDecrement(&This
->ref
);
1693 TRACE("(%p)->(count=%li)\n", This
, refCount
+ 1);
1697 TRACE(" destroying IShellView(%p)\n",This
);
1699 DestroyWindow(This
->hWndList
);
1702 IShellFolder_Release(This
->pSFParent
);
1704 if(This
->pSF2Parent
)
1705 IShellFolder2_Release(This
->pSF2Parent
);
1708 SHFree(This
->apidl
);
1711 IAdviseSink_Release(This
->pAdvSink
);
1713 HeapFree(GetProcessHeap(),0,This
);
1718 /**********************************************************
1719 * ShellView_GetWindow
1721 static HRESULT WINAPI
IShellView_fnGetWindow(IShellView
* iface
,HWND
* phWnd
)
1723 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1725 TRACE("(%p)\n",This
);
1727 *phWnd
= This
->hWnd
;
1732 static HRESULT WINAPI
IShellView_fnContextSensitiveHelp(IShellView
* iface
,BOOL fEnterMode
)
1734 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1736 FIXME("(%p) stub\n",This
);
1741 /**********************************************************
1742 * IShellView_TranslateAccelerator
1745 * use the accel functions
1747 static HRESULT WINAPI
IShellView_fnTranslateAccelerator(IShellView
* iface
,LPMSG lpmsg
)
1750 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1752 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%lx wp=%x) stub\n",This
,lpmsg
, lpmsg
->hwnd
, lpmsg
->message
, lpmsg
->lParam
, lpmsg
->wParam
);
1755 if ((lpmsg
->message
>=WM_KEYFIRST
) && (lpmsg
->message
>=WM_KEYLAST
))
1757 TRACE("-- key=0x04%x\n",lpmsg
->wParam
) ;
1759 return S_FALSE
; /* not handled */
1762 static HRESULT WINAPI
IShellView_fnEnableModeless(IShellView
* iface
,BOOL fEnable
)
1764 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1766 FIXME("(%p) stub\n",This
);
1771 static HRESULT WINAPI
IShellView_fnUIActivate(IShellView
* iface
,UINT uState
)
1773 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1776 CHAR szName[MAX_PATH];
1779 int nPartArray
[1] = {-1};
1781 TRACE("(%p)->(state=%x) stub\n",This
, uState
);
1783 /*don't do anything if the state isn't really changing*/
1784 if(This
->uState
== uState
)
1789 /*OnActivate handles the menu merging and internal state*/
1790 ShellView_OnActivate(This
, uState
);
1792 /*only do This if we are active*/
1793 if(uState
!= SVUIA_DEACTIVATE
)
1797 GetFolderPath is not a method of IShellFolder
1798 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1800 /* set the number of parts */
1801 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_STATUS
, SB_SETPARTS
, 1,
1802 (LPARAM
)nPartArray
, &lResult
);
1804 /* set the text for the parts */
1806 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1807 0, (LPARAM)szName, &lResult);
1814 static HRESULT WINAPI
IShellView_fnRefresh(IShellView
* iface
)
1816 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1818 TRACE("(%p)\n",This
);
1820 ListView_DeleteAllItems(This
->hWndList
);
1821 ShellView_FillList(This
);
1826 static HRESULT WINAPI
IShellView_fnCreateViewWindow(
1828 IShellView
*lpPrevView
,
1829 LPCFOLDERSETTINGS lpfs
,
1830 IShellBrowser
* psb
,
1834 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1840 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This
, lpPrevView
,lpfs
, psb
, prcView
, phWnd
);
1841 TRACE("-- vmode=%x flags=%x left=%li top=%li right=%li bottom=%li\n",lpfs
->ViewMode
, lpfs
->fFlags
,prcView
->left
,prcView
->top
, prcView
->right
, prcView
->bottom
);
1843 /*set up the member variables*/
1844 This
->pShellBrowser
= psb
;
1845 This
->FolderSettings
= *lpfs
;
1847 /*get our parent window*/
1848 IShellBrowser_AddRef(This
->pShellBrowser
);
1849 IShellBrowser_GetWindow(This
->pShellBrowser
, &(This
->hWndParent
));
1851 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1852 This
->pCommDlgBrowser
=NULL
;
1853 if ( SUCCEEDED (IShellBrowser_QueryInterface( This
->pShellBrowser
,
1854 (REFIID
)&IID_ICommDlgBrowser
, (LPVOID
*) &This
->pCommDlgBrowser
)))
1856 TRACE("-- CommDlgBrowser\n");
1859 /*if our window class has not been registered, then do so*/
1860 if(!GetClassInfoA(shell32_hInstance
, SV_CLASS_NAME
, &wc
))
1862 ZeroMemory(&wc
, sizeof(wc
));
1863 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1864 wc
.lpfnWndProc
= ShellView_WndProc
;
1867 wc
.hInstance
= shell32_hInstance
;
1869 wc
.hCursor
= LoadCursorA (0, (LPSTR
)IDC_ARROW
);
1870 wc
.hbrBackground
= (HBRUSH
) (COLOR_WINDOW
+ 1);
1871 wc
.lpszMenuName
= NULL
;
1872 wc
.lpszClassName
= SV_CLASS_NAME
;
1874 if(!RegisterClassA(&wc
))
1878 *phWnd
= CreateWindowExA(0,
1881 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
,
1884 prcView
->right
- prcView
->left
,
1885 prcView
->bottom
- prcView
->top
,
1893 if(!*phWnd
) return E_FAIL
;
1898 static HRESULT WINAPI
IShellView_fnDestroyViewWindow(IShellView
* iface
)
1900 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1902 TRACE("(%p)\n",This
);
1904 /*Make absolutely sure all our UI is cleaned up.*/
1905 IShellView_UIActivate((IShellView
*)This
, SVUIA_DEACTIVATE
);
1909 DestroyMenu(This
->hMenu
);
1912 DestroyWindow(This
->hWnd
);
1913 if(This
->pShellBrowser
) IShellBrowser_Release(This
->pShellBrowser
);
1914 if(This
->pCommDlgBrowser
) ICommDlgBrowser_Release(This
->pCommDlgBrowser
);
1920 static HRESULT WINAPI
IShellView_fnGetCurrentInfo(IShellView
* iface
, LPFOLDERSETTINGS lpfs
)
1922 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1924 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This
, lpfs
,
1925 This
->FolderSettings
.ViewMode
, This
->FolderSettings
.fFlags
);
1927 if (!lpfs
) return E_INVALIDARG
;
1929 *lpfs
= This
->FolderSettings
;
1933 static HRESULT WINAPI
IShellView_fnAddPropertySheetPages(IShellView
* iface
, DWORD dwReserved
,LPFNADDPROPSHEETPAGE lpfn
, LPARAM lparam
)
1935 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1937 FIXME("(%p) stub\n",This
);
1942 static HRESULT WINAPI
IShellView_fnSaveViewState(IShellView
* iface
)
1944 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1946 FIXME("(%p) stub\n",This
);
1951 static HRESULT WINAPI
IShellView_fnSelectItem(
1956 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1959 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This
, pidl
, uFlags
);
1961 i
= LV_FindItemByPidl(This
, pidl
);
1967 if(uFlags
& SVSI_ENSUREVISIBLE
)
1968 ListView_EnsureVisible(This
->hWndList
, i
, 0);
1970 ZeroMemory(&lvItem
, sizeof(LVITEMA
));
1971 lvItem
.mask
= LVIF_STATE
;
1974 while(ListView_GetItemA(This
->hWndList
, &lvItem
))
1976 if (lvItem
.iItem
== i
)
1978 if (uFlags
& SVSI_SELECT
)
1979 lvItem
.state
|= LVIS_SELECTED
;
1981 lvItem
.state
&= ~LVIS_SELECTED
;
1983 if(uFlags
& SVSI_FOCUSED
)
1984 lvItem
.state
&= ~LVIS_FOCUSED
;
1988 if (uFlags
& SVSI_DESELECTOTHERS
)
1989 lvItem
.state
&= ~LVIS_SELECTED
;
1991 ListView_SetItemA(This
->hWndList
, &lvItem
);
1996 if(uFlags
& SVSI_EDIT
)
1997 ListView_EditLabelA(This
->hWndList
, i
);
2003 static HRESULT WINAPI
IShellView_fnGetItemObject(IShellView
* iface
, UINT uItem
, REFIID riid
, LPVOID
*ppvOut
)
2005 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2007 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This
, uItem
, debugstr_guid(riid
), ppvOut
);
2013 case SVGIO_BACKGROUND
:
2014 *ppvOut
= ISvBgCm_Constructor(This
->pSFParent
, FALSE
);
2017 case SVGIO_SELECTION
:
2018 ShellView_GetSelections(This
);
2019 IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, riid
, 0, ppvOut
);
2022 TRACE("-- (%p)->(interface=%p)\n",This
, *ppvOut
);
2024 if(!*ppvOut
) return E_OUTOFMEMORY
;
2029 static const IShellViewVtbl svvt
=
2031 IShellView_fnQueryInterface
,
2032 IShellView_fnAddRef
,
2033 IShellView_fnRelease
,
2034 IShellView_fnGetWindow
,
2035 IShellView_fnContextSensitiveHelp
,
2036 IShellView_fnTranslateAccelerator
,
2037 IShellView_fnEnableModeless
,
2038 IShellView_fnUIActivate
,
2039 IShellView_fnRefresh
,
2040 IShellView_fnCreateViewWindow
,
2041 IShellView_fnDestroyViewWindow
,
2042 IShellView_fnGetCurrentInfo
,
2043 IShellView_fnAddPropertySheetPages
,
2044 IShellView_fnSaveViewState
,
2045 IShellView_fnSelectItem
,
2046 IShellView_fnGetItemObject
2050 /**********************************************************
2051 * ISVOleCmdTarget_QueryInterface (IUnknown)
2053 static HRESULT WINAPI
ISVOleCmdTarget_QueryInterface(
2054 IOleCommandTarget
* iface
,
2058 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2060 return IShellFolder_QueryInterface((IShellFolder
*)This
, iid
, ppvObj
);
2063 /**********************************************************
2064 * ISVOleCmdTarget_AddRef (IUnknown)
2066 static ULONG WINAPI
ISVOleCmdTarget_AddRef(
2067 IOleCommandTarget
* iface
)
2069 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2071 return IShellFolder_AddRef((IShellFolder
*)This
);
2074 /**********************************************************
2075 * ISVOleCmdTarget_Release (IUnknown)
2077 static ULONG WINAPI
ISVOleCmdTarget_Release(
2078 IOleCommandTarget
* iface
)
2080 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2082 return IShellFolder_Release((IShellFolder
*)This
);
2085 /**********************************************************
2086 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2088 static HRESULT WINAPI
ISVOleCmdTarget_QueryStatus(
2089 IOleCommandTarget
*iface
,
2090 const GUID
* pguidCmdGroup
,
2093 OLECMDTEXT
* pCmdText
)
2096 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2098 FIXME("(%p)->(%p(%s) 0x%08lx %p %p\n",
2099 This
, pguidCmdGroup
, debugstr_guid(pguidCmdGroup
), cCmds
, prgCmds
, pCmdText
);
2103 for (i
= 0; i
< cCmds
; i
++)
2105 FIXME("\tprgCmds[%d].cmdID = %ld\n", i
, prgCmds
[i
].cmdID
);
2106 prgCmds
[i
].cmdf
= 0;
2108 return OLECMDERR_E_UNKNOWNGROUP
;
2111 /**********************************************************
2112 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2114 * nCmdID is the OLECMDID_* enumeration
2116 static HRESULT WINAPI
ISVOleCmdTarget_Exec(
2117 IOleCommandTarget
*iface
,
2118 const GUID
* pguidCmdGroup
,
2124 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2126 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08lx Opt:0x%08lx %p %p)\n",
2127 This
, debugstr_guid(pguidCmdGroup
), nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
2129 if (IsEqualIID(pguidCmdGroup
, &CGID_Explorer
) &&
2131 (nCmdexecopt
== 4) && pvaOut
)
2133 if (IsEqualIID(pguidCmdGroup
, &CGID_ShellDocView
) &&
2138 return OLECMDERR_E_UNKNOWNGROUP
;
2141 static const IOleCommandTargetVtbl ctvt
=
2143 ISVOleCmdTarget_QueryInterface
,
2144 ISVOleCmdTarget_AddRef
,
2145 ISVOleCmdTarget_Release
,
2146 ISVOleCmdTarget_QueryStatus
,
2147 ISVOleCmdTarget_Exec
2150 /**********************************************************
2151 * ISVDropTarget implementation
2154 static HRESULT WINAPI
ISVDropTarget_QueryInterface(
2159 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2161 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2163 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2166 static ULONG WINAPI
ISVDropTarget_AddRef( IDropTarget
*iface
)
2168 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2170 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
2172 return IShellFolder_AddRef((IShellFolder
*)This
);
2175 static ULONG WINAPI
ISVDropTarget_Release( IDropTarget
*iface
)
2177 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2179 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
2181 return IShellFolder_Release((IShellFolder
*)This
);
2184 /******************************************************************************
2185 * drag_notify_subitem [Internal]
2187 * Figure out the shellfolder object, which is currently under the mouse cursor
2188 * and notify it via the IDropTarget interface.
2191 #define SCROLLAREAWIDTH 20
2193 static HRESULT
drag_notify_subitem(IShellViewImpl
*This
, DWORD grfKeyState
, POINTL pt
,
2196 LVHITTESTINFO htinfo
;
2202 /* Map from global to client coordinates and query the index of the listview-item, which is
2203 * currently under the mouse cursor. */
2206 htinfo
.flags
= LVHT_ONITEM
;
2207 ScreenToClient(This
->hWndList
, &htinfo
.pt
);
2208 lResult
= SendMessageW(This
->hWndList
, LVM_HITTEST
, 0, (LPARAM
)&htinfo
);
2210 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2211 GetClientRect(This
->hWndList
, &clientRect
);
2212 if (htinfo
.pt
.x
== This
->ptLastMousePos
.x
&& htinfo
.pt
.y
== This
->ptLastMousePos
.y
&&
2213 (htinfo
.pt
.x
< SCROLLAREAWIDTH
|| htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
||
2214 htinfo
.pt
.y
< SCROLLAREAWIDTH
|| htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
))
2216 This
->cScrollDelay
= (This
->cScrollDelay
+ 1) % 5; /* DragOver is called every 50 ms */
2217 if (This
->cScrollDelay
== 0) { /* Mouse did hover another 250 ms over the scroll-area */
2218 if (htinfo
.pt
.x
< SCROLLAREAWIDTH
)
2219 SendMessageW(This
->hWndList
, WM_HSCROLL
, SB_LINEUP
, 0);
2220 if (htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
)
2221 SendMessageW(This
->hWndList
, WM_HSCROLL
, SB_LINEDOWN
, 0);
2222 if (htinfo
.pt
.y
< SCROLLAREAWIDTH
)
2223 SendMessageW(This
->hWndList
, WM_VSCROLL
, SB_LINEUP
, 0);
2224 if (htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
)
2225 SendMessageW(This
->hWndList
, WM_VSCROLL
, SB_LINEDOWN
, 0);
2228 This
->cScrollDelay
= 0; /* Reset, if the cursor is not over the listview's scroll-area */
2230 This
->ptLastMousePos
= htinfo
.pt
;
2232 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2233 if (This
->pCurDropTarget
&& lResult
== This
->iDragOverItem
)
2234 return IDropTarget_DragOver(This
->pCurDropTarget
, grfKeyState
, pt
, pdwEffect
);
2236 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2237 if (This
->pCurDropTarget
) {
2238 IDropTarget_DragLeave(This
->pCurDropTarget
);
2239 IDropTarget_Release(This
->pCurDropTarget
);
2240 This
->pCurDropTarget
= NULL
;
2243 This
->iDragOverItem
= lResult
;
2244 if (lResult
== -1) {
2245 /* We are not above one of the listview's subitems. Bind to the parent folder's
2246 * DropTarget interface. */
2247 hr
= IShellFolder_QueryInterface(This
->pSFParent
, &IID_IDropTarget
,
2248 (LPVOID
*)&This
->pCurDropTarget
);
2250 /* Query the relative PIDL of the shellfolder object represented by the currently
2251 * dragged over listview-item ... */
2252 ZeroMemory(&lvItem
, sizeof(lvItem
));
2253 lvItem
.mask
= LVIF_PARAM
;
2254 lvItem
.iItem
= lResult
;
2255 ListView_GetItemA(This
->hWndList
, &lvItem
);
2257 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2258 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWndList
, 1,
2259 (LPCITEMIDLIST
*)&lvItem
.lParam
, &IID_IDropTarget
, NULL
, (LPVOID
*)&This
->pCurDropTarget
);
2262 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2266 /* Notify the item just entered via DragEnter. */
2267 return IDropTarget_DragEnter(This
->pCurDropTarget
, This
->pCurDataObject
, grfKeyState
, pt
, pdwEffect
);
2270 static HRESULT WINAPI
ISVDropTarget_DragEnter(IDropTarget
*iface
, IDataObject
*pDataObject
,
2271 DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2273 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2275 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2276 This
->pCurDataObject
= pDataObject
;
2277 IDataObject_AddRef(pDataObject
);
2279 return drag_notify_subitem(This
, grfKeyState
, pt
, pdwEffect
);
2282 static HRESULT WINAPI
ISVDropTarget_DragOver(IDropTarget
*iface
, DWORD grfKeyState
, POINTL pt
,
2285 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2286 return drag_notify_subitem(This
, grfKeyState
, pt
, pdwEffect
);
2289 static HRESULT WINAPI
ISVDropTarget_DragLeave(IDropTarget
*iface
) {
2290 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2292 IDropTarget_DragLeave(This
->pCurDropTarget
);
2294 IDropTarget_Release(This
->pCurDropTarget
);
2295 IDataObject_Release(This
->pCurDataObject
);
2296 This
->pCurDataObject
= NULL
;
2297 This
->pCurDropTarget
= NULL
;
2298 This
->iDragOverItem
= 0;
2303 static HRESULT WINAPI
ISVDropTarget_Drop(IDropTarget
*iface
, IDataObject
* pDataObject
,
2304 DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2306 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2308 IDropTarget_Drop(This
->pCurDropTarget
, pDataObject
, grfKeyState
, pt
, pdwEffect
);
2310 IDropTarget_Release(This
->pCurDropTarget
);
2311 IDataObject_Release(This
->pCurDataObject
);
2312 This
->pCurDataObject
= NULL
;
2313 This
->pCurDropTarget
= NULL
;
2314 This
->iDragOverItem
= 0;
2319 static const IDropTargetVtbl dtvt
=
2321 ISVDropTarget_QueryInterface
,
2322 ISVDropTarget_AddRef
,
2323 ISVDropTarget_Release
,
2324 ISVDropTarget_DragEnter
,
2325 ISVDropTarget_DragOver
,
2326 ISVDropTarget_DragLeave
,
2330 /**********************************************************
2331 * ISVDropSource implementation
2334 static HRESULT WINAPI
ISVDropSource_QueryInterface(
2339 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2341 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2343 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2346 static ULONG WINAPI
ISVDropSource_AddRef( IDropSource
*iface
)
2348 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2350 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
2352 return IShellFolder_AddRef((IShellFolder
*)This
);
2355 static ULONG WINAPI
ISVDropSource_Release( IDropSource
*iface
)
2357 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2359 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
2361 return IShellFolder_Release((IShellFolder
*)This
);
2363 static HRESULT WINAPI
ISVDropSource_QueryContinueDrag(
2365 BOOL fEscapePressed
,
2368 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2369 TRACE("(%p)\n",This
);
2372 return DRAGDROP_S_CANCEL
;
2373 else if (!(grfKeyState
& MK_LBUTTON
) && !(grfKeyState
& MK_RBUTTON
))
2374 return DRAGDROP_S_DROP
;
2379 static HRESULT WINAPI
ISVDropSource_GiveFeedback(
2383 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2384 TRACE("(%p)\n",This
);
2386 return DRAGDROP_S_USEDEFAULTCURSORS
;
2389 static const IDropSourceVtbl dsvt
=
2391 ISVDropSource_QueryInterface
,
2392 ISVDropSource_AddRef
,
2393 ISVDropSource_Release
,
2394 ISVDropSource_QueryContinueDrag
,
2395 ISVDropSource_GiveFeedback
2397 /**********************************************************
2398 * ISVViewObject implementation
2401 static HRESULT WINAPI
ISVViewObject_QueryInterface(
2406 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2408 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2410 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2413 static ULONG WINAPI
ISVViewObject_AddRef( IViewObject
*iface
)
2415 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2417 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
2419 return IShellFolder_AddRef((IShellFolder
*)This
);
2422 static ULONG WINAPI
ISVViewObject_Release( IViewObject
*iface
)
2424 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2426 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
2428 return IShellFolder_Release((IShellFolder
*)This
);
2431 static HRESULT WINAPI
ISVViewObject_Draw(
2436 DVTARGETDEVICE
* ptd
,
2439 LPCRECTL lprcBounds
,
2440 LPCRECTL lprcWBounds
,
2441 BOOL (CALLBACK
*pfnContinue
)(ULONG_PTR dwContinue
),
2442 ULONG_PTR dwContinue
)
2445 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2447 FIXME("Stub: This=%p\n",This
);
2451 static HRESULT WINAPI
ISVViewObject_GetColorSet(
2456 DVTARGETDEVICE
* ptd
,
2457 HDC hicTargetDevice
,
2458 LOGPALETTE
** ppColorSet
)
2461 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2463 FIXME("Stub: This=%p\n",This
);
2467 static HRESULT WINAPI
ISVViewObject_Freeze(
2475 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2477 FIXME("Stub: This=%p\n",This
);
2481 static HRESULT WINAPI
ISVViewObject_Unfreeze(
2486 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2488 FIXME("Stub: This=%p\n",This
);
2492 static HRESULT WINAPI
ISVViewObject_SetAdvise(
2496 IAdviseSink
* pAdvSink
)
2499 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2501 FIXME("partial stub: %p %08lx %08lx %p\n",
2502 This
, aspects
, advf
, pAdvSink
);
2504 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2505 This
->pAdvSink
= pAdvSink
;
2506 This
->dwAspects
= aspects
;
2507 This
->dwAdvf
= advf
;
2512 static HRESULT WINAPI
ISVViewObject_GetAdvise(
2516 IAdviseSink
** ppAdvSink
)
2519 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2521 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2522 This
, pAspects
, pAdvf
, ppAdvSink
);
2526 IAdviseSink_AddRef( This
->pAdvSink
);
2527 *ppAdvSink
= This
->pAdvSink
;
2530 *pAspects
= This
->dwAspects
;
2532 *pAdvf
= This
->dwAdvf
;
2538 static const IViewObjectVtbl vovt
=
2540 ISVViewObject_QueryInterface
,
2541 ISVViewObject_AddRef
,
2542 ISVViewObject_Release
,
2544 ISVViewObject_GetColorSet
,
2545 ISVViewObject_Freeze
,
2546 ISVViewObject_Unfreeze
,
2547 ISVViewObject_SetAdvise
,
2548 ISVViewObject_GetAdvise