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 iActiveTimersMask
; /* Bookkeeping of activated timers for drag scrolling */
109 static const IShellViewVtbl svvt
;
110 static const IOleCommandTargetVtbl ctvt
;
111 static const IDropTargetVtbl dtvt
;
112 static const IDropSourceVtbl dsvt
;
113 static const IViewObjectVtbl vovt
;
116 static inline IShellViewImpl
*impl_from_IOleCommandTarget( IOleCommandTarget
*iface
)
118 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblOleCommandTarget
));
121 static inline IShellViewImpl
*impl_from_IDropTarget( IDropTarget
*iface
)
123 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblDropTarget
));
126 static inline IShellViewImpl
*impl_from_IDropSource( IDropSource
*iface
)
128 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblDropSource
));
131 static inline IShellViewImpl
*impl_from_IViewObject( IViewObject
*iface
)
133 return (IShellViewImpl
*)((char*)iface
- FIELD_OFFSET(IShellViewImpl
, lpvtblViewObject
));
136 /* ListView Header ID's */
137 #define LISTVIEW_COLUMN_NAME 0
138 #define LISTVIEW_COLUMN_SIZE 1
139 #define LISTVIEW_COLUMN_TYPE 2
140 #define LISTVIEW_COLUMN_TIME 3
141 #define LISTVIEW_COLUMN_ATTRIB 4
144 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
145 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
146 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
148 #define ID_LISTVIEW 2000
150 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
153 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
154 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
155 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
158 Items merged into the toolbar and and the filemenu
167 } MYTOOLINFO
, *LPMYTOOLINFO
;
171 { FCIDM_SHVIEW_BIGICON
, 0, 0, IDS_VIEW_LARGE
, TBSTATE_ENABLED
, BTNS_BUTTON
},
172 { FCIDM_SHVIEW_SMALLICON
, 0, 0, IDS_VIEW_SMALL
, TBSTATE_ENABLED
, BTNS_BUTTON
},
173 { FCIDM_SHVIEW_LISTVIEW
, 0, 0, IDS_VIEW_LIST
, TBSTATE_ENABLED
, BTNS_BUTTON
},
174 { FCIDM_SHVIEW_REPORTVIEW
, 0, 0, IDS_VIEW_DETAILS
, TBSTATE_ENABLED
, BTNS_BUTTON
},
178 typedef void (CALLBACK
*PFNSHGETSETTINGSPROC
)(LPSHELLFLAGSTATE lpsfs
, DWORD dwMask
);
180 /**********************************************************
181 * IShellView_Constructor
183 IShellView
* IShellView_Constructor( IShellFolder
* pFolder
)
184 { IShellViewImpl
* sv
;
185 sv
=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IShellViewImpl
));
188 sv
->lpvtblOleCommandTarget
=&ctvt
;
189 sv
->lpvtblDropTarget
=&dtvt
;
190 sv
->lpvtblDropSource
=&dsvt
;
191 sv
->lpvtblViewObject
=&vovt
;
193 sv
->pSFParent
= pFolder
;
194 if(pFolder
) IShellFolder_AddRef(pFolder
);
195 IShellFolder_QueryInterface(sv
->pSFParent
, &IID_IShellFolder2
, (LPVOID
*)&sv
->pSF2Parent
);
197 sv
->pCurDropTarget
= NULL
;
198 sv
->pCurDataObject
= NULL
;
199 sv
->iDragOverItem
= 0;
200 sv
->iActiveTimersMask
= 0;
202 TRACE("(%p)->(%p)\n",sv
, pFolder
);
203 return (IShellView
*) sv
;
206 /**********************************************************
208 * ##### helperfunctions for communication with ICommDlgBrowser #####
210 static BOOL
IsInCommDlg(IShellViewImpl
* This
)
211 { return(This
->pCommDlgBrowser
!= NULL
);
214 static HRESULT
IncludeObject(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
218 if ( IsInCommDlg(This
) )
220 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl
);
221 ret
= ICommDlgBrowser_IncludeObject(This
->pCommDlgBrowser
, (IShellView
*)This
, pidl
);
222 TRACE("--0x%08lx\n", ret
);
227 static HRESULT
OnDefaultCommand(IShellViewImpl
* This
)
229 HRESULT ret
= S_FALSE
;
231 if (IsInCommDlg(This
))
233 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
234 ret
= ICommDlgBrowser_OnDefaultCommand(This
->pCommDlgBrowser
, (IShellView
*)This
);
235 TRACE("-- returns %08lx\n", ret
);
240 static HRESULT
OnStateChange(IShellViewImpl
* This
, UINT uFlags
)
242 HRESULT ret
= S_FALSE
;
244 if (IsInCommDlg(This
))
246 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags
);
247 ret
= ICommDlgBrowser_OnStateChange(This
->pCommDlgBrowser
, (IShellView
*)This
, uFlags
);
252 /**********************************************************
253 * set the toolbar of the filedialog buttons
255 * - activates the buttons from the shellbrowser according to
258 static void CheckToolbar(IShellViewImpl
* This
)
264 if (IsInCommDlg(This
))
266 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_CHECKBUTTON
,
267 FCIDM_TB_SMALLICON
, (This
->FolderSettings
.ViewMode
==FVM_LIST
)? TRUE
: FALSE
, &result
);
268 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_CHECKBUTTON
,
269 FCIDM_TB_REPORTVIEW
, (This
->FolderSettings
.ViewMode
==FVM_DETAILS
)? TRUE
: FALSE
, &result
);
270 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_ENABLEBUTTON
,
271 FCIDM_TB_SMALLICON
, TRUE
, &result
);
272 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_TOOLBAR
, TB_ENABLEBUTTON
,
273 FCIDM_TB_REPORTVIEW
, TRUE
, &result
);
277 /**********************************************************
279 * ##### helperfunctions for initializing the view #####
281 /**********************************************************
282 * change the style of the listview control
284 static void SetStyle(IShellViewImpl
* This
, DWORD dwAdd
, DWORD dwRemove
)
288 TRACE("(%p)\n", This
);
290 tmpstyle
= GetWindowLongA(This
->hWndList
, GWL_STYLE
);
291 SetWindowLongA(This
->hWndList
, GWL_STYLE
, dwAdd
| (tmpstyle
& ~dwRemove
));
294 /**********************************************************
295 * ShellView_CreateList()
297 * - creates the list view window
299 static BOOL
ShellView_CreateList (IShellViewImpl
* This
)
300 { DWORD dwStyle
, dwExStyle
;
304 dwStyle
= WS_TABSTOP
| WS_VISIBLE
| WS_CHILDWINDOW
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
305 LVS_SHAREIMAGELISTS
| LVS_EDITLABELS
| LVS_ALIGNLEFT
| LVS_AUTOARRANGE
;
306 dwExStyle
= WS_EX_CLIENTEDGE
;
308 switch (This
->FolderSettings
.ViewMode
)
310 case FVM_ICON
: dwStyle
|= LVS_ICON
; break;
311 case FVM_DETAILS
: dwStyle
|= LVS_REPORT
; break;
312 case FVM_SMALLICON
: dwStyle
|= LVS_SMALLICON
; break;
313 case FVM_LIST
: dwStyle
|= LVS_LIST
; break;
314 default: dwStyle
|= LVS_LIST
; break;
317 if (This
->FolderSettings
.fFlags
& FWF_AUTOARRANGE
) dwStyle
|= LVS_AUTOARRANGE
;
318 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
)
319 This
->FolderSettings
.fFlags
|= FWF_NOCLIENTEDGE
| FWF_NOSCROLL
;
320 if (This
->FolderSettings
.fFlags
& FWF_SINGLESEL
) dwStyle
|= LVS_SINGLESEL
;
321 if (This
->FolderSettings
.fFlags
& FWF_NOCLIENTEDGE
)
322 dwExStyle
&= ~WS_EX_CLIENTEDGE
;
324 This
->hWndList
=CreateWindowExA( dwExStyle
,
337 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
338 This
->ListViewSortInfo
.nHeaderID
= -1;
339 This
->ListViewSortInfo
.nLastHeaderID
= -1;
341 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
) {
342 if (0) /* FIXME: look into registry vale HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow and activate drop shadows */
343 ListView_SetTextBkColor(This
->hWndList
, CLR_NONE
);
345 ListView_SetTextBkColor(This
->hWndList
, GetSysColor(COLOR_DESKTOP
));
347 ListView_SetTextColor(This
->hWndList
, RGB(255,255,255));
350 /* UpdateShellSettings(); */
354 /**********************************************************
355 * ShellView_InitList()
357 * - adds all needed columns to the shellview
359 static BOOL
ShellView_InitList(IShellViewImpl
* This
)
368 ListView_DeleteAllItems(This
->hWndList
);
370 lvColumn
.mask
= LVCF_FMT
| LVCF_WIDTH
| LVCF_TEXT
;
371 lvColumn
.pszText
= szTemp
;
373 if (This
->pSF2Parent
)
377 if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This
->pSF2Parent
, NULL
, i
, &sd
)))
379 lvColumn
.fmt
= sd
.fmt
;
380 lvColumn
.cx
= sd
.cxChar
*8; /* chars->pixel */
381 StrRetToStrNA( szTemp
, 50, &sd
.str
, NULL
);
382 ListView_InsertColumnA(This
->hWndList
, i
, &lvColumn
);
390 ListView_SetImageList(This
->hWndList
, ShellSmallIconList
, LVSIL_SMALL
);
391 ListView_SetImageList(This
->hWndList
, ShellBigIconList
, LVSIL_NORMAL
);
395 /**********************************************************
396 * ShellView_CompareItems()
399 * internal, CALLBACK for DSA_Sort
401 static INT CALLBACK
ShellView_CompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
)
404 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1
, lParam2
, (LPVOID
) lpData
);
406 if(!lpData
) return 0;
408 ret
= (SHORT
) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER
)lpData
, 0, (LPITEMIDLIST
)lParam1
, (LPITEMIDLIST
)lParam2
));
409 TRACE("ret=%i\n",ret
);
413 /*************************************************************************
414 * ShellView_ListViewCompareItems
416 * Compare Function for the Listview (FileOpen Dialog)
419 * lParam1 [I] the first ItemIdList to compare with
420 * lParam2 [I] the second ItemIdList to compare with
421 * lpData [I] The column ID for the header Ctrl to process
424 * A negative value if the first item should precede the second,
425 * a positive value if the first item should follow the second,
426 * or zero if the two items are equivalent
429 * FIXME: function does what ShellView_CompareItems is supposed to do.
430 * unify it and figure out how to use the undocumented first parameter
431 * of IShellFolder_CompareIDs to do the job this function does and
432 * move this code to IShellFolder.
433 * make LISTVIEW_SORT_INFO obsolete
434 * the way this function works is only usable if we had only
435 * filesystemfolders (25/10/99 jsch)
437 static INT CALLBACK
ShellView_ListViewCompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
)
441 char strName1
[MAX_PATH
], strName2
[MAX_PATH
];
442 BOOL bIsFolder1
, bIsFolder2
,bIsBothFolder
;
443 LPITEMIDLIST pItemIdList1
= (LPITEMIDLIST
) lParam1
;
444 LPITEMIDLIST pItemIdList2
= (LPITEMIDLIST
) lParam2
;
445 LISTVIEW_SORT_INFO
*pSortInfo
= (LPLISTVIEW_SORT_INFO
) lpData
;
448 bIsFolder1
= _ILIsFolder(pItemIdList1
);
449 bIsFolder2
= _ILIsFolder(pItemIdList2
);
450 bIsBothFolder
= bIsFolder1
&& bIsFolder2
;
452 /* When sorting between a File and a Folder, the Folder gets sorted first */
453 if( (bIsFolder1
|| bIsFolder2
) && !bIsBothFolder
)
455 nDiff
= bIsFolder1
? -1 : 1;
459 /* Sort by Time: Folders or Files can be sorted */
461 if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_TIME
)
463 _ILGetFileDateTime(pItemIdList1
, &fd1
);
464 _ILGetFileDateTime(pItemIdList2
, &fd2
);
465 nDiff
= CompareFileTime(&fd2
, &fd1
);
467 /* Sort by Attribute: Folder or Files can be sorted */
468 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_ATTRIB
)
470 _ILGetFileAttributes(pItemIdList1
, strName1
, MAX_PATH
);
471 _ILGetFileAttributes(pItemIdList2
, strName2
, MAX_PATH
);
472 nDiff
= lstrcmpiA(strName1
, strName2
);
474 /* Sort by FileName: Folder or Files can be sorted */
475 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_NAME
|| bIsBothFolder
)
478 _ILSimpleGetText(pItemIdList1
, strName1
, MAX_PATH
);
479 _ILSimpleGetText(pItemIdList2
, strName2
, MAX_PATH
);
480 nDiff
= lstrcmpiA(strName1
, strName2
);
482 /* Sort by File Size, Only valid for Files */
483 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_SIZE
)
485 nDiff
= (INT
)(_ILGetFileSize(pItemIdList1
, NULL
, 0) - _ILGetFileSize(pItemIdList2
, NULL
, 0));
487 /* Sort by File Type, Only valid for Files */
488 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_TYPE
)
491 _ILGetFileType(pItemIdList1
, strName1
, MAX_PATH
);
492 _ILGetFileType(pItemIdList2
, strName2
, MAX_PATH
);
493 nDiff
= lstrcmpiA(strName1
, strName2
);
496 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
500 _ILSimpleGetText(pItemIdList1
, strName1
, MAX_PATH
);
501 _ILSimpleGetText(pItemIdList2
, strName2
, MAX_PATH
);
502 nDiff
= lstrcmpiA(strName1
, strName2
);
505 if(!pSortInfo
->bIsAscending
)
514 /**********************************************************
515 * LV_FindItemByPidl()
517 static int LV_FindItemByPidl(
518 IShellViewImpl
* This
,
522 ZeroMemory(&lvItem
, sizeof(LVITEMA
));
523 lvItem
.mask
= LVIF_PARAM
;
524 for(lvItem
.iItem
= 0; ListView_GetItemA(This
->hWndList
, &lvItem
); lvItem
.iItem
++)
526 LPITEMIDLIST currentpidl
= (LPITEMIDLIST
) lvItem
.lParam
;
527 HRESULT hr
= IShellFolder_CompareIDs(This
->pSFParent
, 0, pidl
, currentpidl
);
528 if(SUCCEEDED(hr
) && !HRESULT_CODE(hr
))
536 /**********************************************************
539 static BOOLEAN
LV_AddItem(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
543 TRACE("(%p)(pidl=%p)\n", This
, pidl
);
545 ZeroMemory(&lvItem
, sizeof(lvItem
)); /* create the listview item*/
546 lvItem
.mask
= LVIF_TEXT
| LVIF_IMAGE
| LVIF_PARAM
; /*set the mask*/
547 lvItem
.iItem
= ListView_GetItemCount(This
->hWndList
); /*add the item to the end of the list*/
548 lvItem
.lParam
= (LPARAM
) ILClone(ILFindLastID(pidl
)); /*set the item's data*/
549 lvItem
.pszText
= LPSTR_TEXTCALLBACKA
; /*get text on a callback basis*/
550 lvItem
.iImage
= I_IMAGECALLBACK
; /*get the image on a callback basis*/
551 return (-1==ListView_InsertItemA(This
->hWndList
, &lvItem
))? FALSE
: TRUE
;
554 /**********************************************************
557 static BOOLEAN
LV_DeleteItem(IShellViewImpl
* This
, LPCITEMIDLIST pidl
)
561 TRACE("(%p)(pidl=%p)\n", This
, pidl
);
563 nIndex
= LV_FindItemByPidl(This
, ILFindLastID(pidl
));
564 return (-1==ListView_DeleteItem(This
->hWndList
, nIndex
))? FALSE
: TRUE
;
567 /**********************************************************
570 static BOOLEAN
LV_RenameItem(IShellViewImpl
* This
, LPCITEMIDLIST pidlOld
, LPCITEMIDLIST pidlNew
)
575 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", This
, pidlOld
, pidlNew
);
577 nItem
= LV_FindItemByPidl(This
, ILFindLastID(pidlOld
));
580 ZeroMemory(&lvItem
, sizeof(lvItem
)); /* create the listview item*/
581 lvItem
.mask
= LVIF_PARAM
; /* only the pidl */
582 lvItem
.iItem
= nItem
;
583 ListView_GetItemA(This
->hWndList
, &lvItem
);
585 SHFree((LPITEMIDLIST
)lvItem
.lParam
);
586 lvItem
.mask
= LVIF_PARAM
;
587 lvItem
.iItem
= nItem
;
588 lvItem
.lParam
= (LPARAM
) ILClone(ILFindLastID(pidlNew
)); /* set the item's data */
589 ListView_SetItemA(This
->hWndList
, &lvItem
);
590 ListView_Update(This
->hWndList
, nItem
);
591 return TRUE
; /* FIXME: better handling */
595 /**********************************************************
596 * ShellView_FillList()
598 * - gets the objectlist from the shellfolder
600 * - fills the list into the view
603 static INT CALLBACK
fill_list( LPVOID ptr
, LPVOID arg
)
605 LPITEMIDLIST pidl
= ptr
;
606 IShellViewImpl
*This
= arg
;
607 /* in a commdlg This works as a filemask*/
608 if ( IncludeObject(This
, pidl
)==S_OK
) LV_AddItem(This
, pidl
);
613 static HRESULT
ShellView_FillList(IShellViewImpl
* This
)
615 LPENUMIDLIST pEnumIDList
;
623 /* get the itemlist from the shfolder*/
624 hRes
= IShellFolder_EnumObjects(This
->pSFParent
,This
->hWnd
, SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
, &pEnumIDList
);
632 /* create a pointer array */
633 hdpa
= DPA_Create(16);
636 return(E_OUTOFMEMORY
);
639 /* copy the items into the array*/
640 while((S_OK
== IEnumIDList_Next(pEnumIDList
,1, &pidl
, &dwFetched
)) && dwFetched
)
642 if (DPA_InsertPtr(hdpa
, 0x7fff, pidl
) == -1)
649 DPA_Sort(hdpa
, ShellView_CompareItems
, (LPARAM
)This
->pSFParent
);
651 /*turn the listview's redrawing off*/
652 SendMessageA(This
->hWndList
, WM_SETREDRAW
, FALSE
, 0);
654 DPA_DestroyCallback( hdpa
, fill_list
, This
);
656 /*turn the listview's redrawing back on and force it to draw*/
657 SendMessageA(This
->hWndList
, WM_SETREDRAW
, TRUE
, 0);
659 IEnumIDList_Release(pEnumIDList
); /* destroy the list*/
664 /**********************************************************
665 * ShellView_OnCreate()
667 static LRESULT
ShellView_OnCreate(IShellViewImpl
* This
)
670 SHChangeNotifyEntry ntreg
;
671 IPersistFolder2
* ppf2
= NULL
;
675 if(ShellView_CreateList(This
))
677 if(ShellView_InitList(This
))
679 ShellView_FillList(This
);
683 if (SUCCEEDED(IUnknown_QueryInterface((IUnknown
*)&This
->lpVtbl
, &IID_IDropTarget
, (LPVOID
*)&pdt
)))
685 RegisterDragDrop(This
->hWnd
, pdt
);
686 IDropTarget_Release(pdt
);
689 /* register for receiving notifications */
690 IShellFolder_QueryInterface(This
->pSFParent
, &IID_IPersistFolder2
, (LPVOID
*)&ppf2
);
693 IPersistFolder2_GetCurFolder(ppf2
, (LPITEMIDLIST
*)&ntreg
.pidl
);
694 ntreg
.fRecursive
= TRUE
;
695 This
->hNotify
= SHChangeNotifyRegister(This
->hWnd
, SHCNF_IDLIST
, SHCNE_ALLEVENTS
, SHV_CHANGE_NOTIFY
, 1, &ntreg
);
696 SHFree((LPITEMIDLIST
)ntreg
.pidl
);
697 IPersistFolder2_Release(ppf2
);
700 This
->hAccel
= LoadAcceleratorsA(shell32_hInstance
, "shv_accel");
705 /**********************************************************
706 * #### Handling of the menus ####
709 /**********************************************************
710 * ShellView_BuildFileMenu()
712 static HMENU
ShellView_BuildFileMenu(IShellViewImpl
* This
)
713 { CHAR szText
[MAX_PATH
];
718 TRACE("(%p)\n",This
);
720 hSubMenu
= CreatePopupMenu();
722 { /*get the number of items in our global array*/
723 for(nTools
= 0; Tools
[nTools
].idCommand
!= -1; nTools
++){}
725 /*add the menu items*/
726 for(i
= 0; i
< nTools
; i
++)
728 LoadStringA(shell32_hInstance
, Tools
[i
].idMenuString
, szText
, MAX_PATH
);
730 ZeroMemory(&mii
, sizeof(mii
));
731 mii
.cbSize
= sizeof(mii
);
732 mii
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
734 if(BTNS_SEP
!= Tools
[i
].bStyle
) /* no separator*/
736 mii
.fType
= MFT_STRING
;
737 mii
.fState
= MFS_ENABLED
;
738 mii
.dwTypeData
= szText
;
739 mii
.wID
= Tools
[i
].idCommand
;
743 mii
.fType
= MFT_SEPARATOR
;
745 /* tack This item onto the end of the menu */
746 InsertMenuItemA(hSubMenu
, (UINT
)-1, TRUE
, &mii
);
749 TRACE("-- return (menu=%p)\n",hSubMenu
);
752 /**********************************************************
753 * ShellView_MergeFileMenu()
755 static void ShellView_MergeFileMenu(IShellViewImpl
* This
, HMENU hSubMenu
)
756 { TRACE("(%p)->(submenu=%p) stub\n",This
,hSubMenu
);
759 { /*insert This item at the beginning of the menu */
760 _InsertMenuItem(hSubMenu
, 0, TRUE
, 0, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
761 _InsertMenuItem(hSubMenu
, 0, TRUE
, IDM_MYFILEITEM
, MFT_STRING
, "dummy45", MFS_ENABLED
);
767 /**********************************************************
768 * ShellView_MergeViewMenu()
771 static void ShellView_MergeViewMenu(IShellViewImpl
* This
, HMENU hSubMenu
)
774 TRACE("(%p)->(submenu=%p)\n",This
,hSubMenu
);
777 { /*add a separator at the correct position in the menu*/
778 _InsertMenuItem(hSubMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
, FALSE
, 0, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
780 ZeroMemory(&mii
, sizeof(mii
));
781 mii
.cbSize
= sizeof(mii
);
782 mii
.fMask
= MIIM_SUBMENU
| MIIM_TYPE
| MIIM_DATA
;
783 mii
.fType
= MFT_STRING
;
784 mii
.dwTypeData
= "View";
785 mii
.hSubMenu
= LoadMenuA(shell32_hInstance
, "MENU_001");
786 InsertMenuItemA(hSubMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
, FALSE
, &mii
);
790 /**********************************************************
791 * ShellView_GetSelections()
793 * - fills the this->apidl list with the selected objects
796 * number of selected items
798 static UINT
ShellView_GetSelections(IShellViewImpl
* This
)
808 This
->cidl
= ListView_GetSelectedCount(This
->hWndList
);
809 This
->apidl
= (LPITEMIDLIST
*)SHAlloc(This
->cidl
* sizeof(LPITEMIDLIST
));
811 TRACE("selected=%i\n", This
->cidl
);
815 TRACE("-- Items selected =%u\n", This
->cidl
);
817 ZeroMemory(&lvItem
, sizeof(lvItem
));
818 lvItem
.mask
= LVIF_STATE
| LVIF_PARAM
;
819 lvItem
.stateMask
= LVIS_SELECTED
;
821 while(ListView_GetItemA(This
->hWndList
, &lvItem
) && (i
< This
->cidl
))
823 if(lvItem
.state
& LVIS_SELECTED
)
825 This
->apidl
[i
] = (LPITEMIDLIST
)lvItem
.lParam
;
827 TRACE("-- selected Item found\n");
836 /**********************************************************
837 * ShellView_OpenSelectedItems()
839 static HRESULT
ShellView_OpenSelectedItems(IShellViewImpl
* This
)
841 static UINT CF_IDLIST
= 0;
843 IDataObject
* selection
;
847 LPCITEMIDLIST parent_pidl
;
850 if (0 == ShellView_GetSelections(This
))
854 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
,
855 (LPCITEMIDLIST
*)This
->apidl
, &IID_IDataObject
,
856 0, (LPVOID
*)&selection
);
862 CF_IDLIST
= RegisterClipboardFormatA(CFSTR_SHELLIDLIST
);
864 fetc
.cfFormat
= CF_IDLIST
;
866 fetc
.dwAspect
= DVASPECT_CONTENT
;
868 fetc
.tymed
= TYMED_HGLOBAL
;
870 hr
= IDataObject_QueryGetData(selection
, &fetc
);
874 hr
= IDataObject_GetData(selection
, &fetc
, &stgm
);
878 pIDList
= GlobalLock(stgm
.u
.hGlobal
);
880 parent_pidl
= (LPCITEMIDLIST
) ((LPBYTE
)pIDList
+pIDList
->aoffset
[0]);
881 for (i
= pIDList
->cidl
; i
> 0; --i
)
886 pidl
= (LPCITEMIDLIST
)((LPBYTE
)pIDList
+pIDList
->aoffset
[i
]);
888 attribs
= SFGAO_FOLDER
;
889 hr
= IShellFolder_GetAttributesOf(This
->pSFParent
, 1, &pidl
, &attribs
);
891 if (SUCCEEDED(hr
) && ! (attribs
& SFGAO_FOLDER
))
893 SHELLEXECUTEINFOA shexinfo
;
895 shexinfo
.cbSize
= sizeof(SHELLEXECUTEINFOA
);
896 shexinfo
.fMask
= SEE_MASK_INVOKEIDLIST
; /* SEE_MASK_IDLIST is also possible. */
897 shexinfo
.hwnd
= NULL
;
898 shexinfo
.lpVerb
= NULL
;
899 shexinfo
.lpFile
= NULL
;
900 shexinfo
.lpParameters
= NULL
;
901 shexinfo
.lpDirectory
= NULL
;
902 shexinfo
.nShow
= SW_NORMAL
;
903 shexinfo
.lpIDList
= ILCombine(parent_pidl
, pidl
);
905 ShellExecuteExA(&shexinfo
); /* Discard error/success info */
907 ILFree((LPITEMIDLIST
)shexinfo
.lpIDList
);
911 GlobalUnlock(stgm
.u
.hGlobal
);
912 ReleaseStgMedium(&stgm
);
914 IDataObject_Release(selection
);
919 /**********************************************************
920 * ShellView_DoContextMenu()
922 static void ShellView_DoContextMenu(IShellViewImpl
* This
, WORD x
, WORD y
, BOOL bDefault
)
926 BOOL fExplore
= FALSE
;
928 LPCONTEXTMENU pContextMenu
= NULL
;
929 IContextMenu2
*pCM
= NULL
;
930 CMINVOKECOMMANDINFO cmi
;
932 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",This
, x
, y
, bDefault
);
934 /* look, what's selected and create a context menu object of it*/
935 if( ShellView_GetSelections(This
) )
937 IShellFolder_GetUIObjectOf( This
->pSFParent
, This
->hWndParent
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
,
938 (REFIID
)&IID_IContextMenu
, NULL
, (LPVOID
*)&pContextMenu
);
942 TRACE("-- pContextMenu\n");
943 hMenu
= CreatePopupMenu();
947 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
948 if(SUCCEEDED(IShellBrowser_GetControlWindow(This
->pShellBrowser
,FCW_TREE
, &hwndTree
)) && hwndTree
)
950 TRACE("-- explore mode\n");
954 /* build the flags depending on what we can do with the selected item */
955 wFlags
= CMF_NORMAL
| (This
->cidl
!= 1 ? 0 : CMF_CANRENAME
) | (fExplore
? CMF_EXPLORE
: 0);
957 /* let the ContextMenu merge its items in */
958 if (SUCCEEDED(IContextMenu_QueryContextMenu( pContextMenu
, hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, wFlags
)))
960 if (This
->FolderSettings
.fFlags
& FWF_DESKTOP
)
961 SetMenuDefaultItem(hMenu
, FCIDM_SHVIEW_OPEN
, MF_BYCOMMAND
);
965 TRACE("-- get menu default command\n");
966 uCommand
= GetMenuDefaultItem(hMenu
, FALSE
, GMDI_GOINTOPOPUPS
);
970 TRACE("-- track popup\n");
971 uCommand
= TrackPopupMenu( hMenu
,TPM_LEFTALIGN
| TPM_RETURNCMD
,x
,y
,0,This
->hWnd
,NULL
);
976 TRACE("-- uCommand=%u\n", uCommand
);
977 if (uCommand
==FCIDM_SHVIEW_OPEN
&& IsInCommDlg(This
))
979 TRACE("-- dlg: OnDefaultCommand\n");
980 if (OnDefaultCommand(This
) != S_OK
)
982 ShellView_OpenSelectedItems(This
);
987 TRACE("-- explore -- invoke command\n");
988 ZeroMemory(&cmi
, sizeof(cmi
));
989 cmi
.cbSize
= sizeof(cmi
);
990 cmi
.hwnd
= This
->hWndParent
; /* this window has to answer CWM_GETISHELLBROWSER */
991 cmi
.lpVerb
= (LPCSTR
)MAKEINTRESOURCEA(uCommand
);
992 IContextMenu_InvokeCommand(pContextMenu
, &cmi
);
999 IContextMenu_Release(pContextMenu
);
1002 else /* background context menu */
1004 hMenu
= CreatePopupMenu();
1006 pCM
= ISvBgCm_Constructor(This
->pSFParent
, FALSE
);
1007 IContextMenu2_QueryContextMenu(pCM
, hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, 0);
1009 uCommand
= TrackPopupMenu( hMenu
, TPM_LEFTALIGN
| TPM_RETURNCMD
,x
,y
,0,This
->hWnd
,NULL
);
1012 TRACE("-- (%p)->(uCommand=0x%08x )\n",This
, uCommand
);
1014 ZeroMemory(&cmi
, sizeof(cmi
));
1015 cmi
.cbSize
= sizeof(cmi
);
1016 cmi
.lpVerb
= (LPCSTR
)MAKEINTRESOURCEA(uCommand
);
1017 cmi
.hwnd
= This
->hWndParent
;
1018 IContextMenu2_InvokeCommand(pCM
, &cmi
);
1020 IContextMenu2_Release(pCM
);
1024 /**********************************************************
1025 * ##### message handling #####
1028 /**********************************************************
1029 * ShellView_OnSize()
1031 static LRESULT
ShellView_OnSize(IShellViewImpl
* This
, WORD wWidth
, WORD wHeight
)
1033 TRACE("%p width=%u height=%u\n",This
, wWidth
,wHeight
);
1035 /*resize the ListView to fit our window*/
1038 MoveWindow(This
->hWndList
, 0, 0, wWidth
, wHeight
, TRUE
);
1043 /**********************************************************
1044 * ShellView_OnDeactivate()
1049 static void ShellView_OnDeactivate(IShellViewImpl
* This
)
1053 if(This
->uState
!= SVUIA_DEACTIVATE
)
1057 IShellBrowser_SetMenuSB(This
->pShellBrowser
,0, 0, 0);
1058 IShellBrowser_RemoveMenusSB(This
->pShellBrowser
,This
->hMenu
);
1059 DestroyMenu(This
->hMenu
);
1063 This
->uState
= SVUIA_DEACTIVATE
;
1067 /**********************************************************
1068 * ShellView_OnActivate()
1070 static LRESULT
ShellView_OnActivate(IShellViewImpl
* This
, UINT uState
)
1071 { OLEMENUGROUPWIDTHS omw
= { {0, 0, 0, 0, 0, 0} };
1073 CHAR szText
[MAX_PATH
];
1075 TRACE("%p uState=%x\n",This
,uState
);
1077 /*don't do anything if the state isn't really changing */
1078 if(This
->uState
== uState
)
1083 ShellView_OnDeactivate(This
);
1085 /*only do This if we are active */
1086 if(uState
!= SVUIA_DEACTIVATE
)
1088 /*merge the menus */
1089 This
->hMenu
= CreateMenu();
1093 IShellBrowser_InsertMenusSB(This
->pShellBrowser
, This
->hMenu
, &omw
);
1094 TRACE("-- after fnInsertMenusSB\n");
1096 /*build the top level menu get the menu item's text*/
1097 strcpy(szText
,"dummy 31");
1099 ZeroMemory(&mii
, sizeof(mii
));
1100 mii
.cbSize
= sizeof(mii
);
1101 mii
.fMask
= MIIM_SUBMENU
| MIIM_TYPE
| MIIM_STATE
;
1102 mii
.fType
= MFT_STRING
;
1103 mii
.fState
= MFS_ENABLED
;
1104 mii
.dwTypeData
= szText
;
1105 mii
.hSubMenu
= ShellView_BuildFileMenu(This
);
1107 /*insert our menu into the menu bar*/
1110 InsertMenuItemA(This
->hMenu
, FCIDM_MENU_HELP
, FALSE
, &mii
);
1113 /*get the view menu so we can merge with it*/
1114 ZeroMemory(&mii
, sizeof(mii
));
1115 mii
.cbSize
= sizeof(mii
);
1116 mii
.fMask
= MIIM_SUBMENU
;
1118 if(GetMenuItemInfoA(This
->hMenu
, FCIDM_MENU_VIEW
, FALSE
, &mii
))
1120 ShellView_MergeViewMenu(This
, mii
.hSubMenu
);
1123 /*add the items that should only be added if we have the focus*/
1124 if(SVUIA_ACTIVATE_FOCUS
== uState
)
1126 /*get the file menu so we can merge with it */
1127 ZeroMemory(&mii
, sizeof(mii
));
1128 mii
.cbSize
= sizeof(mii
);
1129 mii
.fMask
= MIIM_SUBMENU
;
1131 if(GetMenuItemInfoA(This
->hMenu
, FCIDM_MENU_FILE
, FALSE
, &mii
))
1133 ShellView_MergeFileMenu(This
, mii
.hSubMenu
);
1136 TRACE("-- before fnSetMenuSB\n");
1137 IShellBrowser_SetMenuSB(This
->pShellBrowser
, This
->hMenu
, 0, This
->hWnd
);
1140 This
->uState
= uState
;
1145 /**********************************************************
1146 * ShellView_OnSetFocus()
1149 static LRESULT
ShellView_OnSetFocus(IShellViewImpl
* This
)
1153 /* Tell the browser one of our windows has received the focus. This
1154 should always be done before merging menus (OnActivate merges the
1155 menus) if one of our windows has the focus.*/
1157 IShellBrowser_OnViewWindowActive(This
->pShellBrowser
,(IShellView
*) This
);
1158 ShellView_OnActivate(This
, SVUIA_ACTIVATE_FOCUS
);
1160 /* Set the focus to the listview */
1161 SetFocus(This
->hWndList
);
1163 /* Notify the ICommDlgBrowser interface */
1164 OnStateChange(This
,CDBOSC_SETFOCUS
);
1169 /**********************************************************
1170 * ShellView_OnKillFocus()
1172 static LRESULT
ShellView_OnKillFocus(IShellViewImpl
* This
)
1174 TRACE("(%p) stub\n",This
);
1176 ShellView_OnActivate(This
, SVUIA_ACTIVATE_NOFOCUS
);
1177 /* Notify the ICommDlgBrowser */
1178 OnStateChange(This
,CDBOSC_KILLFOCUS
);
1183 /**********************************************************
1184 * ShellView_OnCommand()
1187 * the CmdID's are the ones from the context menu
1189 static LRESULT
ShellView_OnCommand(IShellViewImpl
* This
,DWORD dwCmdID
, DWORD dwCmd
, HWND hwndCmd
)
1191 TRACE("(%p)->(0x%08lx 0x%08lx %p) stub\n",This
, dwCmdID
, dwCmd
, hwndCmd
);
1195 case FCIDM_SHVIEW_SMALLICON
:
1196 This
->FolderSettings
.ViewMode
= FVM_SMALLICON
;
1197 SetStyle (This
, LVS_SMALLICON
, LVS_TYPEMASK
);
1201 case FCIDM_SHVIEW_BIGICON
:
1202 This
->FolderSettings
.ViewMode
= FVM_ICON
;
1203 SetStyle (This
, LVS_ICON
, LVS_TYPEMASK
);
1207 case FCIDM_SHVIEW_LISTVIEW
:
1208 This
->FolderSettings
.ViewMode
= FVM_LIST
;
1209 SetStyle (This
, LVS_LIST
, LVS_TYPEMASK
);
1213 case FCIDM_SHVIEW_REPORTVIEW
:
1214 This
->FolderSettings
.ViewMode
= FVM_DETAILS
;
1215 SetStyle (This
, LVS_REPORT
, LVS_TYPEMASK
);
1219 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1224 This
->ListViewSortInfo
.nHeaderID
= (LPARAM
) (dwCmdID
- 0x30);
1225 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
1226 This
->ListViewSortInfo
.nLastHeaderID
= This
->ListViewSortInfo
.nHeaderID
;
1227 ListView_SortItems(This
->hWndList
, ShellView_ListViewCompareItems
, (LPARAM
) (&(This
->ListViewSortInfo
)));
1231 TRACE("-- COMMAND 0x%04lx unhandled\n", dwCmdID
);
1236 /**********************************************************
1237 * ShellView_OnNotify()
1240 static LRESULT
ShellView_OnNotify(IShellViewImpl
* This
, UINT CtlID
, LPNMHDR lpnmh
)
1241 { LPNMLISTVIEW lpnmlv
= (LPNMLISTVIEW
)lpnmh
;
1242 NMLVDISPINFOA
*lpdi
= (NMLVDISPINFOA
*)lpnmh
;
1245 TRACE("%p CtlID=%u lpnmh->code=%x\n",This
,CtlID
,lpnmh
->code
);
1250 TRACE("-- NM_SETFOCUS %p\n",This
);
1251 ShellView_OnSetFocus(This
);
1255 TRACE("-- NM_KILLFOCUS %p\n",This
);
1256 ShellView_OnDeactivate(This
);
1257 /* Notify the ICommDlgBrowser interface */
1258 OnStateChange(This
,CDBOSC_KILLFOCUS
);
1262 TRACE("-- NM_CUSTOMDRAW %p\n",This
);
1263 return CDRF_DODEFAULT
;
1265 case NM_RELEASEDCAPTURE
:
1266 TRACE("-- NM_RELEASEDCAPTURE %p\n",This
);
1270 TRACE("-- NM_CLICK %p\n",This
);
1274 TRACE("-- NM_RCLICK %p\n",This
);
1278 TRACE("-- NM_DBLCLK %p\n",This
);
1279 if (OnDefaultCommand(This
) != S_OK
) ShellView_OpenSelectedItems(This
);
1283 TRACE("-- NM_DBLCLK %p\n",This
);
1284 if (OnDefaultCommand(This
) != S_OK
) ShellView_OpenSelectedItems(This
);
1288 TRACE("-- HDN_ENDTRACKA %p\n",This
);
1289 /*nColumn1 = ListView_GetColumnWidth(This->hWndList, 0);
1290 nColumn2 = ListView_GetColumnWidth(This->hWndList, 1);*/
1293 case LVN_DELETEITEM
:
1294 TRACE("-- LVN_DELETEITEM %p\n",This
);
1295 SHFree((LPITEMIDLIST
)lpnmlv
->lParam
); /*delete the pidl because we made a copy of it*/
1298 case LVN_DELETEALLITEMS
:
1299 TRACE("-- LVN_DELETEALLITEMS %p\n",This
);
1302 case LVN_INSERTITEM
:
1303 TRACE("-- LVN_INSERTITEM (STUB)%p\n",This
);
1306 case LVN_ITEMACTIVATE
:
1307 TRACE("-- LVN_ITEMACTIVATE %p\n",This
);
1308 OnStateChange(This
, CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1311 case LVN_COLUMNCLICK
:
1312 This
->ListViewSortInfo
.nHeaderID
= lpnmlv
->iSubItem
;
1313 if(This
->ListViewSortInfo
.nLastHeaderID
== This
->ListViewSortInfo
.nHeaderID
)
1315 This
->ListViewSortInfo
.bIsAscending
= !This
->ListViewSortInfo
.bIsAscending
;
1319 This
->ListViewSortInfo
.bIsAscending
= TRUE
;
1321 This
->ListViewSortInfo
.nLastHeaderID
= This
->ListViewSortInfo
.nHeaderID
;
1323 ListView_SortItems(lpnmlv
->hdr
.hwndFrom
, ShellView_ListViewCompareItems
, (LPARAM
) (&(This
->ListViewSortInfo
)));
1326 case LVN_GETDISPINFOA
:
1327 case LVN_GETDISPINFOW
:
1328 TRACE("-- LVN_GETDISPINFO %p\n",This
);
1329 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1331 if(lpdi
->item
.mask
& LVIF_TEXT
) /* text requested */
1333 if (This
->pSF2Parent
)
1336 IShellFolder2_GetDetailsOf(This
->pSF2Parent
, pidl
, lpdi
->item
.iSubItem
, &sd
);
1337 if (lpnmh
->code
== LVN_GETDISPINFOA
)
1339 StrRetToStrNA( lpdi
->item
.pszText
, lpdi
->item
.cchTextMax
, &sd
.str
, NULL
);
1340 TRACE("-- text=%s\n",lpdi
->item
.pszText
);
1342 else /* LVN_GETDISPINFOW */
1344 StrRetToStrNW( ((NMLVDISPINFOW
*)lpdi
)->item
.pszText
, lpdi
->item
.cchTextMax
, &sd
.str
, NULL
);
1345 TRACE("-- text=%s\n",debugstr_w((WCHAR
*)(lpdi
->item
.pszText
)));
1353 if(lpdi
->item
.mask
& LVIF_IMAGE
) /* image requested */
1355 lpdi
->item
.iImage
= SHMapPIDLToSystemImageListIndex(This
->pSFParent
, pidl
, 0);
1359 case LVN_ITEMCHANGED
:
1360 TRACE("-- LVN_ITEMCHANGED %p\n",This
);
1361 OnStateChange(This
, CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1365 case LVN_BEGINRDRAG
:
1366 TRACE("-- LVN_BEGINDRAG\n");
1368 if (ShellView_GetSelections(This
))
1371 DWORD dwAttributes
= SFGAO_CANLINK
;
1372 DWORD dwEffect
= DROPEFFECT_COPY
| DROPEFFECT_MOVE
;
1374 if (SUCCEEDED(IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, &IID_IDataObject
,0,(LPVOID
*)&pda
)))
1376 IDropSource
* pds
= (IDropSource
*)&(This
->lpvtblDropSource
); /* own DropSource interface */
1378 if (SUCCEEDED(IShellFolder_GetAttributesOf(This
->pSFParent
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, &dwAttributes
)))
1380 if (dwAttributes
& SFGAO_CANLINK
)
1382 dwEffect
|= DROPEFFECT_LINK
;
1389 DoDragDrop(pda
, pds
, dwEffect
, &dwEffect
);
1391 IDataObject_Release(pda
);
1396 case LVN_BEGINLABELEDITA
:
1398 DWORD dwAttr
= SFGAO_CANRENAME
;
1399 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1401 TRACE("-- LVN_BEGINLABELEDITA %p\n",This
);
1403 IShellFolder_GetAttributesOf(This
->pSFParent
, 1, (LPCITEMIDLIST
*)&pidl
, &dwAttr
);
1404 if (SFGAO_CANRENAME
& dwAttr
)
1411 case LVN_ENDLABELEDITA
:
1413 TRACE("-- LVN_ENDLABELEDITA %p\n",This
);
1414 if (lpdi
->item
.pszText
)
1417 WCHAR wszNewName
[MAX_PATH
];
1420 ZeroMemory(&lvItem
, sizeof(LVITEMA
));
1421 lvItem
.iItem
= lpdi
->item
.iItem
;
1422 lvItem
.mask
= LVIF_PARAM
;
1423 ListView_GetItemA(This
->hWndList
, &lvItem
);
1425 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1426 if (!MultiByteToWideChar( CP_ACP
, 0, lpdi
->item
.pszText
, -1, wszNewName
, MAX_PATH
))
1427 wszNewName
[MAX_PATH
-1] = 0;
1428 hr
= IShellFolder_SetNameOf(This
->pSFParent
, 0, pidl
, wszNewName
, SHGDN_INFOLDER
, &pidl
);
1430 if(SUCCEEDED(hr
) && pidl
)
1432 lvItem
.mask
= LVIF_PARAM
;
1433 lvItem
.lParam
= (LPARAM
)pidl
;
1434 ListView_SetItemA(This
->hWndList
, &lvItem
);
1444 msg.hwnd = This->hWnd;
1445 msg.message = WM_KEYDOWN;
1446 msg.wParam = plvKeyDown->wVKey;
1451 LPNMLVKEYDOWN plvKeyDown
= (LPNMLVKEYDOWN
) lpnmh
;
1453 /* initiate a rename of the selected file or directory */
1454 if(plvKeyDown
->wVKey
== VK_F2
)
1456 /* see how many files are selected */
1457 int i
= ListView_GetSelectedCount(This
->hWndList
);
1459 /* get selected item */
1462 /* get selected item */
1463 i
= ListView_GetNextItem(This
->hWndList
, -1,
1466 ListView_EnsureVisible(This
->hWndList
, i
, 0);
1467 ListView_EditLabelA(This
->hWndList
, i
);
1471 TranslateAccelerator(This
->hWnd
, This
->hAccel
, &msg
)
1473 else if(plvKeyDown
->wVKey
== VK_DELETE
)
1478 LPITEMIDLIST
* pItems
;
1481 IShellFolder_QueryInterface(This
->pSFParent
, &IID_ISFHelper
,
1487 if(!(i
= ListView_GetSelectedCount(This
->hWndList
)))
1490 /* allocate memory for the pidl array */
1491 pItems
= HeapAlloc(GetProcessHeap(), 0,
1492 sizeof(LPITEMIDLIST
) * i
);
1494 /* retrieve all selected items */
1497 while(ListView_GetSelectedCount(This
->hWndList
) > i
)
1499 /* get selected item */
1500 item_index
= ListView_GetNextItem(This
->hWndList
,
1501 item_index
, LVNI_SELECTED
);
1502 item
.iItem
= item_index
;
1503 item
.mask
|= LVIF_PARAM
;
1504 ListView_GetItemA(This
->hWndList
, &item
);
1507 pItems
[i
] = (LPITEMIDLIST
)item
.lParam
;
1512 /* perform the item deletion */
1513 ISFHelper_DeleteItems(psfhlp
, i
, (LPCITEMIDLIST
*)pItems
);
1515 /* free pidl array memory */
1516 HeapFree(GetProcessHeap(), 0, pItems
);
1519 /* Initiate a refresh */
1520 else if(plvKeyDown
->wVKey
== VK_F5
)
1522 IShellView_Refresh((IShellView
*)This
);
1526 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown
->wVKey
);
1531 TRACE("-- %p WM_COMMAND %x unhandled\n", This
, lpnmh
->code
);
1537 /**********************************************************
1538 * ShellView_OnChange()
1541 static LRESULT
ShellView_OnChange(IShellViewImpl
* This
, LPITEMIDLIST
* Pidls
, LONG wEventId
)
1544 TRACE("(%p)(%p,%p,0x%08lx)\n", This
, Pidls
[0], Pidls
[1], wEventId
);
1549 LV_AddItem(This
, Pidls
[0]);
1553 LV_DeleteItem(This
, Pidls
[0]);
1555 case SHCNE_RENAMEFOLDER
:
1556 case SHCNE_RENAMEITEM
:
1557 LV_RenameItem(This
, Pidls
[0], Pidls
[1]);
1559 case SHCNE_UPDATEITEM
:
1564 /**********************************************************
1568 static LRESULT CALLBACK
ShellView_WndProc(HWND hWnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
)
1570 IShellViewImpl
* pThis
= (IShellViewImpl
*)GetWindowLongPtrW(hWnd
, GWLP_USERDATA
);
1571 LPCREATESTRUCTA lpcs
;
1573 TRACE("(hwnd=%p msg=%x wparm=%x lparm=%lx)\n",hWnd
, uMessage
, wParam
, lParam
);
1578 lpcs
= (LPCREATESTRUCTA
)lParam
;
1579 pThis
= (IShellViewImpl
*)(lpcs
->lpCreateParams
);
1580 SetWindowLongPtrW(hWnd
, GWLP_USERDATA
, (ULONG_PTR
)pThis
);
1581 pThis
->hWnd
= hWnd
; /*set the window handle*/
1584 case WM_SIZE
: return ShellView_OnSize(pThis
,LOWORD(lParam
), HIWORD(lParam
));
1585 case WM_SETFOCUS
: return ShellView_OnSetFocus(pThis
);
1586 case WM_KILLFOCUS
: return ShellView_OnKillFocus(pThis
);
1587 case WM_CREATE
: return ShellView_OnCreate(pThis
);
1588 case WM_ACTIVATE
: return ShellView_OnActivate(pThis
, SVUIA_ACTIVATE_FOCUS
);
1589 case WM_NOTIFY
: return ShellView_OnNotify(pThis
,(UINT
)wParam
, (LPNMHDR
)lParam
);
1590 case WM_COMMAND
: return ShellView_OnCommand(pThis
,
1591 GET_WM_COMMAND_ID(wParam
, lParam
),
1592 GET_WM_COMMAND_CMD(wParam
, lParam
),
1593 GET_WM_COMMAND_HWND(wParam
, lParam
));
1594 case SHV_CHANGE_NOTIFY
: return ShellView_OnChange(pThis
, (LPITEMIDLIST
*)wParam
, (LONG
)lParam
);
1596 case WM_CONTEXTMENU
: ShellView_DoContextMenu(pThis
, LOWORD(lParam
), HIWORD(lParam
), FALSE
);
1599 case WM_SHOWWINDOW
: UpdateWindow(pThis
->hWndList
);
1602 case WM_GETDLGCODE
: return SendMessageA(pThis
->hWndList
,uMessage
,0,0);
1605 RevokeDragDrop(pThis
->hWnd
);
1606 SHChangeNotifyDeregister(pThis
->hNotify
);
1610 if ((pThis
->FolderSettings
.fFlags
& FWF_DESKTOP
) ||
1611 (pThis
->FolderSettings
.fFlags
& FWF_TRANSPARENT
))
1616 return DefWindowProcA (hWnd
, uMessage
, wParam
, lParam
);
1618 /**********************************************************
1621 * The INTERFACE of the IShellView object
1624 **********************************************************
1625 * IShellView_QueryInterface
1627 static HRESULT WINAPI
IShellView_fnQueryInterface(IShellView
* iface
,REFIID riid
, LPVOID
*ppvObj
)
1629 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1631 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
1635 if(IsEqualIID(riid
, &IID_IUnknown
))
1639 else if(IsEqualIID(riid
, &IID_IShellView
))
1641 *ppvObj
= (IShellView
*)This
;
1643 else if(IsEqualIID(riid
, &IID_IOleCommandTarget
))
1645 *ppvObj
= (IOleCommandTarget
*)&(This
->lpvtblOleCommandTarget
);
1647 else if(IsEqualIID(riid
, &IID_IDropTarget
))
1649 *ppvObj
= (IDropTarget
*)&(This
->lpvtblDropTarget
);
1651 else if(IsEqualIID(riid
, &IID_IDropSource
))
1653 *ppvObj
= (IDropSource
*)&(This
->lpvtblDropSource
);
1655 else if(IsEqualIID(riid
, &IID_IViewObject
))
1657 *ppvObj
= (IViewObject
*)&(This
->lpvtblViewObject
);
1662 IUnknown_AddRef( (IUnknown
*)*ppvObj
);
1663 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
1666 TRACE("-- Interface: E_NOINTERFACE\n");
1667 return E_NOINTERFACE
;
1670 /**********************************************************
1673 static ULONG WINAPI
IShellView_fnAddRef(IShellView
* iface
)
1675 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1676 ULONG refCount
= InterlockedIncrement(&This
->ref
);
1678 TRACE("(%p)->(count=%lu)\n", This
, refCount
- 1);
1682 /**********************************************************
1683 * IShellView_Release
1685 static ULONG WINAPI
IShellView_fnRelease(IShellView
* iface
)
1687 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1688 ULONG refCount
= InterlockedDecrement(&This
->ref
);
1690 TRACE("(%p)->(count=%li)\n", This
, refCount
+ 1);
1694 TRACE(" destroying IShellView(%p)\n",This
);
1696 DestroyWindow(This
->hWndList
);
1699 IShellFolder_Release(This
->pSFParent
);
1701 if(This
->pSF2Parent
)
1702 IShellFolder2_Release(This
->pSF2Parent
);
1705 SHFree(This
->apidl
);
1708 IAdviseSink_Release(This
->pAdvSink
);
1710 HeapFree(GetProcessHeap(),0,This
);
1715 /**********************************************************
1716 * ShellView_GetWindow
1718 static HRESULT WINAPI
IShellView_fnGetWindow(IShellView
* iface
,HWND
* phWnd
)
1720 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1722 TRACE("(%p)\n",This
);
1724 *phWnd
= This
->hWnd
;
1729 static HRESULT WINAPI
IShellView_fnContextSensitiveHelp(IShellView
* iface
,BOOL fEnterMode
)
1731 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1733 FIXME("(%p) stub\n",This
);
1738 /**********************************************************
1739 * IShellView_TranslateAccelerator
1742 * use the accel functions
1744 static HRESULT WINAPI
IShellView_fnTranslateAccelerator(IShellView
* iface
,LPMSG lpmsg
)
1747 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1749 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%lx wp=%x) stub\n",This
,lpmsg
, lpmsg
->hwnd
, lpmsg
->message
, lpmsg
->lParam
, lpmsg
->wParam
);
1752 if ((lpmsg
->message
>=WM_KEYFIRST
) && (lpmsg
->message
>=WM_KEYLAST
))
1754 TRACE("-- key=0x04%x\n",lpmsg
->wParam
) ;
1756 return S_FALSE
; /* not handled */
1759 static HRESULT WINAPI
IShellView_fnEnableModeless(IShellView
* iface
,BOOL fEnable
)
1761 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1763 FIXME("(%p) stub\n",This
);
1768 static HRESULT WINAPI
IShellView_fnUIActivate(IShellView
* iface
,UINT uState
)
1770 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1773 CHAR szName[MAX_PATH];
1776 int nPartArray
[1] = {-1};
1778 TRACE("(%p)->(state=%x) stub\n",This
, uState
);
1780 /*don't do anything if the state isn't really changing*/
1781 if(This
->uState
== uState
)
1786 /*OnActivate handles the menu merging and internal state*/
1787 ShellView_OnActivate(This
, uState
);
1789 /*only do This if we are active*/
1790 if(uState
!= SVUIA_DEACTIVATE
)
1794 GetFolderPath is not a method of IShellFolder
1795 IShellFolder_GetFolderPath( This->pSFParent, szName, sizeof(szName) );
1797 /* set the number of parts */
1798 IShellBrowser_SendControlMsg(This
->pShellBrowser
, FCW_STATUS
, SB_SETPARTS
, 1,
1799 (LPARAM
)nPartArray
, &lResult
);
1801 /* set the text for the parts */
1803 IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_STATUS, SB_SETTEXTA,
1804 0, (LPARAM)szName, &lResult);
1811 static HRESULT WINAPI
IShellView_fnRefresh(IShellView
* iface
)
1813 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1815 TRACE("(%p)\n",This
);
1817 ListView_DeleteAllItems(This
->hWndList
);
1818 ShellView_FillList(This
);
1823 static HRESULT WINAPI
IShellView_fnCreateViewWindow(
1825 IShellView
*lpPrevView
,
1826 LPCFOLDERSETTINGS lpfs
,
1827 IShellBrowser
* psb
,
1831 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1837 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",This
, lpPrevView
,lpfs
, psb
, prcView
, phWnd
);
1838 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
);
1840 /*set up the member variables*/
1841 This
->pShellBrowser
= psb
;
1842 This
->FolderSettings
= *lpfs
;
1844 /*get our parent window*/
1845 IShellBrowser_AddRef(This
->pShellBrowser
);
1846 IShellBrowser_GetWindow(This
->pShellBrowser
, &(This
->hWndParent
));
1848 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
1849 This
->pCommDlgBrowser
=NULL
;
1850 if ( SUCCEEDED (IShellBrowser_QueryInterface( This
->pShellBrowser
,
1851 (REFIID
)&IID_ICommDlgBrowser
, (LPVOID
*) &This
->pCommDlgBrowser
)))
1853 TRACE("-- CommDlgBrowser\n");
1856 /*if our window class has not been registered, then do so*/
1857 if(!GetClassInfoA(shell32_hInstance
, SV_CLASS_NAME
, &wc
))
1859 ZeroMemory(&wc
, sizeof(wc
));
1860 wc
.style
= CS_HREDRAW
| CS_VREDRAW
;
1861 wc
.lpfnWndProc
= ShellView_WndProc
;
1864 wc
.hInstance
= shell32_hInstance
;
1866 wc
.hCursor
= LoadCursorA (0, (LPSTR
)IDC_ARROW
);
1867 wc
.hbrBackground
= (HBRUSH
) (COLOR_WINDOW
+ 1);
1868 wc
.lpszMenuName
= NULL
;
1869 wc
.lpszClassName
= SV_CLASS_NAME
;
1871 if(!RegisterClassA(&wc
))
1875 *phWnd
= CreateWindowExA(0,
1878 WS_CHILD
| WS_VISIBLE
| WS_TABSTOP
,
1881 prcView
->right
- prcView
->left
,
1882 prcView
->bottom
- prcView
->top
,
1890 if(!*phWnd
) return E_FAIL
;
1895 static HRESULT WINAPI
IShellView_fnDestroyViewWindow(IShellView
* iface
)
1897 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1899 TRACE("(%p)\n",This
);
1901 /*Make absolutely sure all our UI is cleaned up.*/
1902 IShellView_UIActivate((IShellView
*)This
, SVUIA_DEACTIVATE
);
1906 DestroyMenu(This
->hMenu
);
1909 DestroyWindow(This
->hWnd
);
1910 if(This
->pShellBrowser
) IShellBrowser_Release(This
->pShellBrowser
);
1911 if(This
->pCommDlgBrowser
) ICommDlgBrowser_Release(This
->pCommDlgBrowser
);
1917 static HRESULT WINAPI
IShellView_fnGetCurrentInfo(IShellView
* iface
, LPFOLDERSETTINGS lpfs
)
1919 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1921 TRACE("(%p)->(%p) vmode=%x flags=%x\n",This
, lpfs
,
1922 This
->FolderSettings
.ViewMode
, This
->FolderSettings
.fFlags
);
1924 if (!lpfs
) return E_INVALIDARG
;
1926 *lpfs
= This
->FolderSettings
;
1930 static HRESULT WINAPI
IShellView_fnAddPropertySheetPages(IShellView
* iface
, DWORD dwReserved
,LPFNADDPROPSHEETPAGE lpfn
, LPARAM lparam
)
1932 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1934 FIXME("(%p) stub\n",This
);
1939 static HRESULT WINAPI
IShellView_fnSaveViewState(IShellView
* iface
)
1941 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1943 FIXME("(%p) stub\n",This
);
1948 static HRESULT WINAPI
IShellView_fnSelectItem(
1953 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
1956 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",This
, pidl
, uFlags
);
1958 i
= LV_FindItemByPidl(This
, pidl
);
1964 if(uFlags
& SVSI_ENSUREVISIBLE
)
1965 ListView_EnsureVisible(This
->hWndList
, i
, 0);
1967 ZeroMemory(&lvItem
, sizeof(LVITEMA
));
1968 lvItem
.mask
= LVIF_STATE
;
1971 while(ListView_GetItemA(This
->hWndList
, &lvItem
))
1973 if (lvItem
.iItem
== i
)
1975 if (uFlags
& SVSI_SELECT
)
1976 lvItem
.state
|= LVIS_SELECTED
;
1978 lvItem
.state
&= ~LVIS_SELECTED
;
1980 if(uFlags
& SVSI_FOCUSED
)
1981 lvItem
.state
&= ~LVIS_FOCUSED
;
1985 if (uFlags
& SVSI_DESELECTOTHERS
)
1986 lvItem
.state
&= ~LVIS_SELECTED
;
1988 ListView_SetItemA(This
->hWndList
, &lvItem
);
1993 if(uFlags
& SVSI_EDIT
)
1994 ListView_EditLabelA(This
->hWndList
, i
);
2000 static HRESULT WINAPI
IShellView_fnGetItemObject(IShellView
* iface
, UINT uItem
, REFIID riid
, LPVOID
*ppvOut
)
2002 IShellViewImpl
*This
= (IShellViewImpl
*)iface
;
2004 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",This
, uItem
, debugstr_guid(riid
), ppvOut
);
2010 case SVGIO_BACKGROUND
:
2011 *ppvOut
= ISvBgCm_Constructor(This
->pSFParent
, FALSE
);
2014 case SVGIO_SELECTION
:
2015 ShellView_GetSelections(This
);
2016 IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWnd
, This
->cidl
, (LPCITEMIDLIST
*)This
->apidl
, riid
, 0, ppvOut
);
2019 TRACE("-- (%p)->(interface=%p)\n",This
, *ppvOut
);
2021 if(!*ppvOut
) return E_OUTOFMEMORY
;
2026 static const IShellViewVtbl svvt
=
2028 IShellView_fnQueryInterface
,
2029 IShellView_fnAddRef
,
2030 IShellView_fnRelease
,
2031 IShellView_fnGetWindow
,
2032 IShellView_fnContextSensitiveHelp
,
2033 IShellView_fnTranslateAccelerator
,
2034 IShellView_fnEnableModeless
,
2035 IShellView_fnUIActivate
,
2036 IShellView_fnRefresh
,
2037 IShellView_fnCreateViewWindow
,
2038 IShellView_fnDestroyViewWindow
,
2039 IShellView_fnGetCurrentInfo
,
2040 IShellView_fnAddPropertySheetPages
,
2041 IShellView_fnSaveViewState
,
2042 IShellView_fnSelectItem
,
2043 IShellView_fnGetItemObject
2047 /**********************************************************
2048 * ISVOleCmdTarget_QueryInterface (IUnknown)
2050 static HRESULT WINAPI
ISVOleCmdTarget_QueryInterface(
2051 IOleCommandTarget
* iface
,
2055 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2057 return IShellFolder_QueryInterface((IShellFolder
*)This
, iid
, ppvObj
);
2060 /**********************************************************
2061 * ISVOleCmdTarget_AddRef (IUnknown)
2063 static ULONG WINAPI
ISVOleCmdTarget_AddRef(
2064 IOleCommandTarget
* iface
)
2066 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2068 return IShellFolder_AddRef((IShellFolder
*)This
);
2071 /**********************************************************
2072 * ISVOleCmdTarget_Release (IUnknown)
2074 static ULONG WINAPI
ISVOleCmdTarget_Release(
2075 IOleCommandTarget
* iface
)
2077 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2079 return IShellFolder_Release((IShellFolder
*)This
);
2082 /**********************************************************
2083 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2085 static HRESULT WINAPI
ISVOleCmdTarget_QueryStatus(
2086 IOleCommandTarget
*iface
,
2087 const GUID
* pguidCmdGroup
,
2090 OLECMDTEXT
* pCmdText
)
2093 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2095 FIXME("(%p)->(%p(%s) 0x%08lx %p %p\n",
2096 This
, pguidCmdGroup
, debugstr_guid(pguidCmdGroup
), cCmds
, prgCmds
, pCmdText
);
2100 for (i
= 0; i
< cCmds
; i
++)
2102 FIXME("\tprgCmds[%d].cmdID = %ld\n", i
, prgCmds
[i
].cmdID
);
2103 prgCmds
[i
].cmdf
= 0;
2105 return OLECMDERR_E_UNKNOWNGROUP
;
2108 /**********************************************************
2109 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2111 * nCmdID is the OLECMDID_* enumeration
2113 static HRESULT WINAPI
ISVOleCmdTarget_Exec(
2114 IOleCommandTarget
*iface
,
2115 const GUID
* pguidCmdGroup
,
2121 IShellViewImpl
*This
= impl_from_IOleCommandTarget(iface
);
2123 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08lx Opt:0x%08lx %p %p)\n",
2124 This
, debugstr_guid(pguidCmdGroup
), nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
2126 if (IsEqualIID(pguidCmdGroup
, &CGID_Explorer
) &&
2128 (nCmdexecopt
== 4) && pvaOut
)
2130 if (IsEqualIID(pguidCmdGroup
, &CGID_ShellDocView
) &&
2135 return OLECMDERR_E_UNKNOWNGROUP
;
2138 static const IOleCommandTargetVtbl ctvt
=
2140 ISVOleCmdTarget_QueryInterface
,
2141 ISVOleCmdTarget_AddRef
,
2142 ISVOleCmdTarget_Release
,
2143 ISVOleCmdTarget_QueryStatus
,
2144 ISVOleCmdTarget_Exec
2147 /**********************************************************
2148 * ISVDropTarget implementation
2151 static HRESULT WINAPI
ISVDropTarget_QueryInterface(
2156 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2158 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2160 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2163 static ULONG WINAPI
ISVDropTarget_AddRef( IDropTarget
*iface
)
2165 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2167 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
2169 return IShellFolder_AddRef((IShellFolder
*)This
);
2172 static ULONG WINAPI
ISVDropTarget_Release( IDropTarget
*iface
)
2174 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2176 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
2178 return IShellFolder_Release((IShellFolder
*)This
);
2181 /******************************************************************************
2182 * scroll_timer_proc [Internal]
2184 * Timer callback function for drag&drop scrolling
2188 #define IDT_DOWN 0x2u
2189 #define IDT_LEFT 0x4u
2190 #define IDT_RIGHT 0x8u
2192 VOID CALLBACK
scroll_timer_proc(HWND hwnd
, UINT uMsg
, UINT_PTR idTimer
, DWORD dwTimer
) {
2195 SendMessageW(hwnd
, WM_VSCROLL
, SB_LINEUP
, 0);
2198 SendMessageW(hwnd
, WM_VSCROLL
, SB_LINEDOWN
, 0);
2201 SendMessageW(hwnd
, WM_HSCROLL
, SB_LINEUP
, 0);
2204 SendMessageW(hwnd
, WM_HSCROLL
, SB_LINEDOWN
, 0);
2209 /******************************************************************************
2210 * start_stop_timer [Internal]
2212 static inline void start_stop_timer(IShellViewImpl
*This
, UINT_PTR idTimer
, BOOL fStart
) {
2213 if (fStart
&& !(This
->iActiveTimersMask
& idTimer
)) {
2214 SetTimer(This
->hWndList
, idTimer
, 200, scroll_timer_proc
);
2215 This
->iActiveTimersMask
|= idTimer
;
2217 if (!fStart
&& This
->iActiveTimersMask
& idTimer
) {
2218 KillTimer(This
->hWndList
, idTimer
);
2219 This
->iActiveTimersMask
&= ~idTimer
;
2223 /******************************************************************************
2224 * drag_notify_subitem [Internal]
2226 * Figure out the shellfolder object, which is currently under the mouse cursor
2227 * and notify it via the IDropTarget interface.
2230 #define SCROLLAREAWIDTH 20
2232 static HRESULT
drag_notify_subitem(IShellViewImpl
*This
, DWORD grfKeyState
, POINTL pt
,
2235 LVHITTESTINFO htinfo
;
2241 /* Map from global to client coordinates and query the index of the listview-item, which is
2242 * currently under the mouse cursor. */
2245 htinfo
.flags
= LVHT_ONITEM
;
2246 ScreenToClient(This
->hWndList
, &htinfo
.pt
);
2247 lResult
= SendMessageW(This
->hWndList
, LVM_HITTEST
, 0, (LPARAM
)&htinfo
);
2249 /* Start or stop the drag scrolling timers */
2250 GetClientRect(This
->hWndList
, &clientRect
);
2251 start_stop_timer(This
, IDT_LEFT
, htinfo
.pt
.x
< SCROLLAREAWIDTH
);
2252 start_stop_timer(This
, IDT_RIGHT
, htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
);
2253 start_stop_timer(This
, IDT_UP
, htinfo
.pt
.y
< SCROLLAREAWIDTH
);
2254 start_stop_timer(This
, IDT_DOWN
, htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
);
2256 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2257 if (This
->pCurDropTarget
&& lResult
== This
->iDragOverItem
)
2258 return IDropTarget_DragOver(This
->pCurDropTarget
, grfKeyState
, pt
, pdwEffect
);
2260 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2261 if (This
->pCurDropTarget
) {
2262 IDropTarget_DragLeave(This
->pCurDropTarget
);
2263 IDropTarget_Release(This
->pCurDropTarget
);
2264 This
->pCurDropTarget
= NULL
;
2267 This
->iDragOverItem
= lResult
;
2268 if (lResult
== -1) {
2269 /* We are not above one of the listview's subitems. Bind to the parent folder's
2270 * DropTarget interface. */
2271 hr
= IShellFolder_QueryInterface(This
->pSFParent
, &IID_IDropTarget
,
2272 (LPVOID
*)&This
->pCurDropTarget
);
2274 /* Query the relative PIDL of the shellfolder object represented by the currently
2275 * dragged over listview-item ... */
2276 ZeroMemory(&lvItem
, sizeof(lvItem
));
2277 lvItem
.mask
= LVIF_PARAM
;
2278 lvItem
.iItem
= lResult
;
2279 ListView_GetItemA(This
->hWndList
, &lvItem
);
2281 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2282 hr
= IShellFolder_GetUIObjectOf(This
->pSFParent
, This
->hWndList
, 1,
2283 (LPCITEMIDLIST
*)&lvItem
.lParam
, &IID_IDropTarget
, NULL
, (LPVOID
*)&This
->pCurDropTarget
);
2286 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2290 /* Notify the item just entered via DragEnter. */
2291 return IDropTarget_DragEnter(This
->pCurDropTarget
, This
->pCurDataObject
, grfKeyState
, pt
, pdwEffect
);
2294 static HRESULT WINAPI
ISVDropTarget_DragEnter(IDropTarget
*iface
, IDataObject
*pDataObject
,
2295 DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2297 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2299 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2300 This
->pCurDataObject
= pDataObject
;
2301 IDataObject_AddRef(pDataObject
);
2303 return drag_notify_subitem(This
, grfKeyState
, pt
, pdwEffect
);
2306 static HRESULT WINAPI
ISVDropTarget_DragOver(IDropTarget
*iface
, DWORD grfKeyState
, POINTL pt
,
2309 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2310 return drag_notify_subitem(This
, grfKeyState
, pt
, pdwEffect
);
2313 static HRESULT WINAPI
ISVDropTarget_DragLeave(IDropTarget
*iface
) {
2314 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2316 IDropTarget_DragLeave(This
->pCurDropTarget
);
2318 IDropTarget_Release(This
->pCurDropTarget
);
2319 IDataObject_Release(This
->pCurDataObject
);
2320 This
->pCurDataObject
= NULL
;
2321 This
->pCurDropTarget
= NULL
;
2322 This
->iDragOverItem
= 0;
2324 start_stop_timer(This
, IDT_LEFT
, FALSE
);
2325 start_stop_timer(This
, IDT_RIGHT
, FALSE
);
2326 start_stop_timer(This
, IDT_UP
, FALSE
);
2327 start_stop_timer(This
, IDT_DOWN
, FALSE
);
2332 static HRESULT WINAPI
ISVDropTarget_Drop(IDropTarget
*iface
, IDataObject
* pDataObject
,
2333 DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2335 IShellViewImpl
*This
= impl_from_IDropTarget(iface
);
2337 IDropTarget_Drop(This
->pCurDropTarget
, pDataObject
, grfKeyState
, pt
, pdwEffect
);
2339 IDropTarget_Release(This
->pCurDropTarget
);
2340 IDataObject_Release(This
->pCurDataObject
);
2341 This
->pCurDataObject
= NULL
;
2342 This
->pCurDropTarget
= NULL
;
2343 This
->iDragOverItem
= 0;
2345 start_stop_timer(This
, IDT_LEFT
, FALSE
);
2346 start_stop_timer(This
, IDT_RIGHT
, FALSE
);
2347 start_stop_timer(This
, IDT_UP
, FALSE
);
2348 start_stop_timer(This
, IDT_DOWN
, FALSE
);
2353 static const IDropTargetVtbl dtvt
=
2355 ISVDropTarget_QueryInterface
,
2356 ISVDropTarget_AddRef
,
2357 ISVDropTarget_Release
,
2358 ISVDropTarget_DragEnter
,
2359 ISVDropTarget_DragOver
,
2360 ISVDropTarget_DragLeave
,
2364 /**********************************************************
2365 * ISVDropSource implementation
2368 static HRESULT WINAPI
ISVDropSource_QueryInterface(
2373 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2375 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2377 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2380 static ULONG WINAPI
ISVDropSource_AddRef( IDropSource
*iface
)
2382 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2384 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
2386 return IShellFolder_AddRef((IShellFolder
*)This
);
2389 static ULONG WINAPI
ISVDropSource_Release( IDropSource
*iface
)
2391 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2393 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
2395 return IShellFolder_Release((IShellFolder
*)This
);
2397 static HRESULT WINAPI
ISVDropSource_QueryContinueDrag(
2399 BOOL fEscapePressed
,
2402 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2403 TRACE("(%p)\n",This
);
2406 return DRAGDROP_S_CANCEL
;
2407 else if (!(grfKeyState
& MK_LBUTTON
) && !(grfKeyState
& MK_RBUTTON
))
2408 return DRAGDROP_S_DROP
;
2413 static HRESULT WINAPI
ISVDropSource_GiveFeedback(
2417 IShellViewImpl
*This
= impl_from_IDropSource(iface
);
2418 TRACE("(%p)\n",This
);
2420 return DRAGDROP_S_USEDEFAULTCURSORS
;
2423 static const IDropSourceVtbl dsvt
=
2425 ISVDropSource_QueryInterface
,
2426 ISVDropSource_AddRef
,
2427 ISVDropSource_Release
,
2428 ISVDropSource_QueryContinueDrag
,
2429 ISVDropSource_GiveFeedback
2431 /**********************************************************
2432 * ISVViewObject implementation
2435 static HRESULT WINAPI
ISVViewObject_QueryInterface(
2440 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2442 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This
,debugstr_guid(riid
),ppvObj
);
2444 return IShellFolder_QueryInterface((IShellFolder
*)This
, riid
, ppvObj
);
2447 static ULONG WINAPI
ISVViewObject_AddRef( IViewObject
*iface
)
2449 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2451 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
2453 return IShellFolder_AddRef((IShellFolder
*)This
);
2456 static ULONG WINAPI
ISVViewObject_Release( IViewObject
*iface
)
2458 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2460 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
2462 return IShellFolder_Release((IShellFolder
*)This
);
2465 static HRESULT WINAPI
ISVViewObject_Draw(
2470 DVTARGETDEVICE
* ptd
,
2473 LPCRECTL lprcBounds
,
2474 LPCRECTL lprcWBounds
,
2475 BOOL (CALLBACK
*pfnContinue
)(ULONG_PTR dwContinue
),
2476 ULONG_PTR dwContinue
)
2479 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2481 FIXME("Stub: This=%p\n",This
);
2485 static HRESULT WINAPI
ISVViewObject_GetColorSet(
2490 DVTARGETDEVICE
* ptd
,
2491 HDC hicTargetDevice
,
2492 LOGPALETTE
** ppColorSet
)
2495 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2497 FIXME("Stub: This=%p\n",This
);
2501 static HRESULT WINAPI
ISVViewObject_Freeze(
2509 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2511 FIXME("Stub: This=%p\n",This
);
2515 static HRESULT WINAPI
ISVViewObject_Unfreeze(
2520 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2522 FIXME("Stub: This=%p\n",This
);
2526 static HRESULT WINAPI
ISVViewObject_SetAdvise(
2530 IAdviseSink
* pAdvSink
)
2533 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2535 FIXME("partial stub: %p %08lx %08lx %p\n",
2536 This
, aspects
, advf
, pAdvSink
);
2538 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2539 This
->pAdvSink
= pAdvSink
;
2540 This
->dwAspects
= aspects
;
2541 This
->dwAdvf
= advf
;
2546 static HRESULT WINAPI
ISVViewObject_GetAdvise(
2550 IAdviseSink
** ppAdvSink
)
2553 IShellViewImpl
*This
= impl_from_IViewObject(iface
);
2555 TRACE("This=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n",
2556 This
, pAspects
, pAdvf
, ppAdvSink
);
2560 IAdviseSink_AddRef( This
->pAdvSink
);
2561 *ppAdvSink
= This
->pAdvSink
;
2564 *pAspects
= This
->dwAspects
;
2566 *pAdvf
= This
->dwAdvf
;
2572 static const IViewObjectVtbl vovt
=
2574 ISVViewObject_QueryInterface
,
2575 ISVViewObject_AddRef
,
2576 ISVViewObject_Release
,
2578 ISVViewObject_GetColorSet
,
2579 ISVViewObject_Freeze
,
2580 ISVViewObject_Unfreeze
,
2581 ISVViewObject_SetAdvise
,
2582 ISVViewObject_GetAdvise