4 * Copyright 1998,1999 <juergen.schmied@debitel.net>
6 * This is the view visualizing the data provided by the shellfolder.
7 * No direct access to data from pidls should be done from here.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * FIXME: The order by part of the background context menu should be
24 * built according to the columns shown.
26 * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
28 * FIXME: ShellView_FillList: consider sort orders
33 1. Load/Save the view state from/into the stream provided by the ShellBrowser.
34 2. Let the shell folder sort items.
35 3. Code to merge menus in the shellbrowser is incorrect.
36 4. Move the background context menu creation into shell view. It should store the
37 shell view HWND to send commands.
38 5. Send init, measure, and draw messages to context menu during tracking.
39 6. Shell view should do SetCommandTarget on internet toolbar.
40 7. When editing starts on item, set edit text to for editing value.
41 8. When shell view is called back for item info, let listview save the value.
42 9. Shell view should update status bar.
43 10. Fix shell view to handle view mode popup exec.
44 11. The background context menu should have a pidl just like foreground menus. This
45 causes crashes when dynamic handlers try to use the NULL pidl.
46 12. The SHELLDLL_DefView should not be filled with blue unconditionally. This causes
47 annoying flashing of blue even on XP, and is not correct.
48 13. Reorder of columns doesn't work - might be bug in comctl32
53 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
57 static const WCHAR SV_CLASS_NAME
[] = {'S','H','E','L','L','D','L','L','_','D','e','f','V','i','e','w',0};
63 }LISTVIEW_SORT_INFO
, *LPLISTVIEW_SORT_INFO
;
65 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
68 public CWindowImpl
<CDefView
, CWindow
, CControlWinTraits
>,
69 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
72 public IOleCommandTarget
,
76 public IServiceProvider
79 CComPtr
<IShellFolder
> pSFParent
;
80 CComPtr
<IShellFolder2
> pSF2Parent
;
81 CComPtr
<IShellBrowser
> pShellBrowser
;
82 CComPtr
<ICommDlgBrowser
> pCommDlgBrowser
;
83 HWND hWndList
; /* ListView control */
85 FOLDERSETTINGS FolderSettings
;
90 LISTVIEW_SORT_INFO ListViewSortInfo
;
91 ULONG hNotify
; /* change notification handle */
95 CComPtr
<IAdviseSink
> pAdvSink
;
97 CComPtr
<IDropTarget
> pCurDropTarget
; /* The sub-item, which is currently dragged over */
98 CComPtr
<IDataObject
> pCurDataObject
; /* The dragged data-object */
99 LONG iDragOverItem
; /* Dragged over item's index, iff pCurDropTarget != NULL */
100 UINT cScrollDelay
; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
101 POINT ptLastMousePos
; /* Mouse position at last DragOver call */
103 CComPtr
<IContextMenu2
> pCM
;
107 HRESULT WINAPI
Initialize(IShellFolder
*shellFolder
);
108 HRESULT
IncludeObject(LPCITEMIDLIST pidl
);
109 HRESULT
OnDefaultCommand();
110 HRESULT
OnStateChange(UINT uFlags
);
112 void SetStyle(DWORD dwAdd
, DWORD dwRemove
);
115 static INT CALLBACK
CompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
);
116 static INT CALLBACK
ListViewCompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
);
117 int LV_FindItemByPidl(LPCITEMIDLIST pidl
);
118 BOOLEAN
LV_AddItem(LPCITEMIDLIST pidl
);
119 BOOLEAN
LV_DeleteItem(LPCITEMIDLIST pidl
);
120 BOOLEAN
LV_RenameItem(LPCITEMIDLIST pidlOld
, LPCITEMIDLIST pidlNew
);
121 static INT CALLBACK
fill_list(LPVOID ptr
, LPVOID arg
);
123 HMENU
BuildFileMenu();
124 void MergeFileMenu(HMENU hSubMenu
);
125 void MergeViewMenu(HMENU hSubMenu
);
126 UINT
GetSelections();
127 HRESULT
OpenSelectedItems();
129 void DoActivate(UINT uState
);
130 HRESULT
drag_notify_subitem(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
);
132 // *** IOleWindow methods ***
133 virtual HRESULT STDMETHODCALLTYPE
GetWindow(HWND
*lphwnd
);
134 virtual HRESULT STDMETHODCALLTYPE
ContextSensitiveHelp(BOOL fEnterMode
);
136 // *** IShellView methods ***
137 virtual HRESULT STDMETHODCALLTYPE
TranslateAccelerator(MSG
*pmsg
);
138 virtual HRESULT STDMETHODCALLTYPE
EnableModeless(BOOL fEnable
);
139 virtual HRESULT STDMETHODCALLTYPE
UIActivate(UINT uState
);
140 virtual HRESULT STDMETHODCALLTYPE
Refresh();
141 virtual HRESULT STDMETHODCALLTYPE
CreateViewWindow(IShellView
*psvPrevious
, LPCFOLDERSETTINGS pfs
, IShellBrowser
*psb
, RECT
*prcView
, HWND
*phWnd
);
142 virtual HRESULT STDMETHODCALLTYPE
DestroyViewWindow();
143 virtual HRESULT STDMETHODCALLTYPE
GetCurrentInfo(LPFOLDERSETTINGS pfs
);
144 virtual HRESULT STDMETHODCALLTYPE
AddPropertySheetPages(DWORD dwReserved
, LPFNSVADDPROPSHEETPAGE pfn
, LPARAM lparam
);
145 virtual HRESULT STDMETHODCALLTYPE
SaveViewState();
146 virtual HRESULT STDMETHODCALLTYPE
SelectItem(LPCITEMIDLIST pidlItem
, SVSIF uFlags
);
147 virtual HRESULT STDMETHODCALLTYPE
GetItemObject(UINT uItem
, REFIID riid
, void **ppv
);
149 // *** IFolderView methods ***
150 virtual HRESULT STDMETHODCALLTYPE
GetCurrentViewMode(UINT
*pViewMode
);
151 virtual HRESULT STDMETHODCALLTYPE
SetCurrentViewMode(UINT ViewMode
);
152 virtual HRESULT STDMETHODCALLTYPE
GetFolder(REFIID riid
, void **ppv
);
153 virtual HRESULT STDMETHODCALLTYPE
Item(int iItemIndex
, LPITEMIDLIST
*ppidl
);
154 virtual HRESULT STDMETHODCALLTYPE
ItemCount(UINT uFlags
, int *pcItems
);
155 virtual HRESULT STDMETHODCALLTYPE
Items(UINT uFlags
, REFIID riid
, void **ppv
);
156 virtual HRESULT STDMETHODCALLTYPE
GetSelectionMarkedItem(int *piItem
);
157 virtual HRESULT STDMETHODCALLTYPE
GetFocusedItem(int *piItem
);
158 virtual HRESULT STDMETHODCALLTYPE
GetItemPosition(LPCITEMIDLIST pidl
, POINT
*ppt
);
159 virtual HRESULT STDMETHODCALLTYPE
GetSpacing(POINT
*ppt
);
160 virtual HRESULT STDMETHODCALLTYPE
GetDefaultSpacing(POINT
*ppt
);
161 virtual HRESULT STDMETHODCALLTYPE
GetAutoArrange();
162 virtual HRESULT STDMETHODCALLTYPE
SelectItem(int iItem
, DWORD dwFlags
);
163 virtual HRESULT STDMETHODCALLTYPE
SelectAndPositionItems(UINT cidl
, LPCITEMIDLIST
*apidl
, POINT
*apt
, DWORD dwFlags
);
165 // *** IOleCommandTarget methods ***
166 virtual HRESULT STDMETHODCALLTYPE
QueryStatus(const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD prgCmds
[ ], OLECMDTEXT
*pCmdText
);
167 virtual HRESULT STDMETHODCALLTYPE
Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
);
169 // *** IDropTarget methods ***
170 virtual HRESULT STDMETHODCALLTYPE
DragEnter(IDataObject
*pDataObj
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
);
171 virtual HRESULT STDMETHODCALLTYPE
DragOver(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
);
172 virtual HRESULT STDMETHODCALLTYPE
DragLeave();
173 virtual HRESULT STDMETHODCALLTYPE
Drop(IDataObject
*pDataObj
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
);
175 // *** IDropSource methods ***
176 virtual HRESULT STDMETHODCALLTYPE
QueryContinueDrag(BOOL fEscapePressed
, DWORD grfKeyState
);
177 virtual HRESULT STDMETHODCALLTYPE
GiveFeedback(DWORD dwEffect
);
179 // *** IViewObject methods ***
180 virtual HRESULT STDMETHODCALLTYPE
Draw(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DVTARGETDEVICE
*ptd
,
181 HDC hdcTargetDev
, HDC hdcDraw
, LPCRECTL lprcBounds
, LPCRECTL lprcWBounds
,
182 BOOL ( STDMETHODCALLTYPE
*pfnContinue
)(ULONG_PTR dwContinue
), ULONG_PTR dwContinue
);
183 virtual HRESULT STDMETHODCALLTYPE
GetColorSet(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
,
184 DVTARGETDEVICE
*ptd
, HDC hicTargetDev
, LOGPALETTE
**ppColorSet
);
185 virtual HRESULT STDMETHODCALLTYPE
Freeze(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DWORD
*pdwFreeze
);
186 virtual HRESULT STDMETHODCALLTYPE
Unfreeze(DWORD dwFreeze
);
187 virtual HRESULT STDMETHODCALLTYPE
SetAdvise(DWORD aspects
, DWORD advf
, IAdviseSink
*pAdvSink
);
188 virtual HRESULT STDMETHODCALLTYPE
GetAdvise(DWORD
*pAspects
, DWORD
*pAdvf
, IAdviseSink
**ppAdvSink
);
190 // *** IServiceProvider methods ***
191 virtual HRESULT STDMETHODCALLTYPE
QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
);
194 LRESULT
OnShowWindow(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
195 LRESULT
OnGetDlgCode(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
196 LRESULT
OnDestroy(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
197 LRESULT
OnEraseBackground(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
198 LRESULT
OnSysColorChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
199 LRESULT
OnGetShellBrowser(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
200 LRESULT
OnCreate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
201 LRESULT
OnContextMenu(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
202 LRESULT
OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
203 LRESULT
OnActivate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
204 LRESULT
OnSetFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
205 LRESULT
OnKillFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
206 LRESULT
OnCommand(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
207 LRESULT
OnNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
208 LRESULT
OnChangeNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
209 LRESULT
OnCustomItem(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
211 static ATL::CWndClassInfo
& GetWndClassInfo()
213 static ATL::CWndClassInfo wc
=
215 { sizeof(WNDCLASSEX
), CS_HREDRAW
| CS_VREDRAW
, StartWindowProc
,
217 LoadCursor(NULL
, IDC_ARROW
), (HBRUSH
)(COLOR_BACKGROUND
+ 1), NULL
, SV_CLASS_NAME
, NULL
},
218 NULL
, NULL
, IDC_ARROW
, TRUE
, 0, _T("")
223 virtual WNDPROC
GetWindowProc()
228 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
233 // must hold a reference during message handling
234 pThis
= reinterpret_cast<CDefView
*>(hWnd
);
236 result
= CWindowImpl
<CDefView
, CWindow
, CControlWinTraits
>::WindowProc(hWnd
, uMsg
, wParam
, lParam
);
241 BEGIN_MSG_MAP(CDefView
)
242 MESSAGE_HANDLER(WM_SIZE
, OnSize
)
243 MESSAGE_HANDLER(WM_SETFOCUS
, OnSetFocus
)
244 MESSAGE_HANDLER(WM_KILLFOCUS
, OnKillFocus
)
245 MESSAGE_HANDLER(WM_CREATE
, OnCreate
)
246 MESSAGE_HANDLER(WM_ACTIVATE
, OnActivate
)
247 MESSAGE_HANDLER(WM_NOTIFY
, OnNotify
)
248 MESSAGE_HANDLER(WM_COMMAND
, OnCommand
)
249 MESSAGE_HANDLER(SHV_CHANGE_NOTIFY
, OnChangeNotify
)
250 MESSAGE_HANDLER(WM_CONTEXTMENU
, OnContextMenu
)
251 MESSAGE_HANDLER(WM_DRAWITEM
, OnCustomItem
)
252 MESSAGE_HANDLER(WM_MEASUREITEM
, OnCustomItem
)
253 MESSAGE_HANDLER(WM_SHOWWINDOW
, OnShowWindow
)
254 MESSAGE_HANDLER(WM_GETDLGCODE
, OnGetDlgCode
)
255 MESSAGE_HANDLER(WM_DESTROY
, OnDestroy
)
256 MESSAGE_HANDLER(WM_ERASEBKGND
, OnEraseBackground
)
257 MESSAGE_HANDLER(WM_SYSCOLORCHANGE
, OnSysColorChange
)
258 MESSAGE_HANDLER(CWM_GETISHELLBROWSER
, OnGetShellBrowser
)
261 BEGIN_COM_MAP(CDefView
)
262 COM_INTERFACE_ENTRY_IID(IID_IOleWindow
, IOleWindow
)
263 COM_INTERFACE_ENTRY_IID(IID_IShellView
, IShellView
)
264 COM_INTERFACE_ENTRY_IID(IID_IFolderView
, IFolderView
)
265 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget
, IOleCommandTarget
)
266 COM_INTERFACE_ENTRY_IID(IID_IDropTarget
, IDropTarget
)
267 COM_INTERFACE_ENTRY_IID(IID_IDropSource
, IDropSource
)
268 COM_INTERFACE_ENTRY_IID(IID_IViewObject
, IViewObject
)
269 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider
, IServiceProvider
)
273 /* ListView Header ID's */
274 #define LISTVIEW_COLUMN_NAME 0
275 #define LISTVIEW_COLUMN_SIZE 1
276 #define LISTVIEW_COLUMN_TYPE 2
277 #define LISTVIEW_COLUMN_TIME 3
278 #define LISTVIEW_COLUMN_ATTRIB 4
281 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
282 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
283 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
285 #define ID_LISTVIEW 1
288 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
289 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
290 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
293 Items merged into the toolbar and the filemenu
302 } MYTOOLINFO
, *LPMYTOOLINFO
;
304 static const MYTOOLINFO Tools
[] =
306 { FCIDM_SHVIEW_BIGICON
, 0, 0, IDS_VIEW_LARGE
, TBSTATE_ENABLED
, BTNS_BUTTON
},
307 { FCIDM_SHVIEW_SMALLICON
, 0, 0, IDS_VIEW_SMALL
, TBSTATE_ENABLED
, BTNS_BUTTON
},
308 { FCIDM_SHVIEW_LISTVIEW
, 0, 0, IDS_VIEW_LIST
, TBSTATE_ENABLED
, BTNS_BUTTON
},
309 { FCIDM_SHVIEW_REPORTVIEW
, 0, 0, IDS_VIEW_DETAILS
, TBSTATE_ENABLED
, BTNS_BUTTON
},
313 typedef void (CALLBACK
*PFNSHGETSETTINGSPROC
)(LPSHELLFLAGSTATE lpsfs
, DWORD dwMask
);
319 FolderSettings
.fFlags
= 0;
320 FolderSettings
.ViewMode
= 0;
325 ListViewSortInfo
.bIsAscending
= FALSE
;
326 ListViewSortInfo
.nHeaderID
= 0;
327 ListViewSortInfo
.nLastHeaderID
= 0;
334 ptLastMousePos
.x
= 0;
335 ptLastMousePos
.y
= 0;
338 CDefView::~CDefView()
340 TRACE(" destroying IShellView(%p)\n", this);
345 HRESULT WINAPI
CDefView::Initialize(IShellFolder
*shellFolder
)
347 pSFParent
= shellFolder
;
348 shellFolder
->QueryInterface(IID_IShellFolder2
, (LPVOID
*)&pSF2Parent
);
353 /**********************************************************
355 * ##### helperfunctions for communication with ICommDlgBrowser #####
357 HRESULT
CDefView::IncludeObject(LPCITEMIDLIST pidl
)
361 if (pCommDlgBrowser
.p
!= NULL
)
363 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl
);
364 ret
= pCommDlgBrowser
->IncludeObject((IShellView
*)this, pidl
);
365 TRACE("--0x%08x\n", ret
);
371 HRESULT
CDefView::OnDefaultCommand()
373 HRESULT ret
= S_FALSE
;
375 if (pCommDlgBrowser
.p
!= NULL
)
377 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
378 ret
= pCommDlgBrowser
->OnDefaultCommand((IShellView
*)this);
379 TRACE("-- returns %08x\n", ret
);
385 HRESULT
CDefView::OnStateChange(UINT uFlags
)
387 HRESULT ret
= S_FALSE
;
389 if (pCommDlgBrowser
.p
!= NULL
)
391 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags
);
392 ret
= pCommDlgBrowser
->OnStateChange((IShellView
*)this, uFlags
);
398 /**********************************************************
399 * set the toolbar of the filedialog buttons
401 * - activates the buttons from the shellbrowser according to
404 void CDefView::CheckToolbar()
410 if (pCommDlgBrowser
!= NULL
)
412 pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_CHECKBUTTON
,
413 FCIDM_TB_SMALLICON
, (FolderSettings
.ViewMode
==FVM_LIST
)? TRUE
: FALSE
, &result
);
414 pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_CHECKBUTTON
,
415 FCIDM_TB_REPORTVIEW
, (FolderSettings
.ViewMode
==FVM_DETAILS
)? TRUE
: FALSE
, &result
);
416 pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_ENABLEBUTTON
,
417 FCIDM_TB_SMALLICON
, TRUE
, &result
);
418 pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_ENABLEBUTTON
,
419 FCIDM_TB_REPORTVIEW
, TRUE
, &result
);
423 /**********************************************************
425 * ##### helperfunctions for initializing the view #####
427 /**********************************************************
428 * change the style of the listview control
430 void CDefView::SetStyle(DWORD dwAdd
, DWORD dwRemove
)
434 TRACE("(%p)\n", this);
436 tmpstyle
= ::GetWindowLongPtrW(hWndList
, GWL_STYLE
);
437 ::SetWindowLongPtrW(hWndList
, GWL_STYLE
, dwAdd
| (tmpstyle
& ~dwRemove
));
440 /**********************************************************
441 * ShellView_CreateList()
443 * - creates the list view window
445 BOOL
CDefView::CreateList()
446 { DWORD dwStyle
, dwExStyle
;
450 dwStyle
= WS_TABSTOP
| WS_VISIBLE
| WS_CHILDWINDOW
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
451 LVS_SHAREIMAGELISTS
| LVS_EDITLABELS
| LVS_AUTOARRANGE
;
452 dwExStyle
= WS_EX_CLIENTEDGE
;
454 if (FolderSettings
.fFlags
& FWF_DESKTOP
)
455 dwStyle
|= LVS_ALIGNLEFT
;
457 dwStyle
|= LVS_ALIGNTOP
;
459 switch (FolderSettings
.ViewMode
)
466 dwStyle
|= LVS_REPORT
;
470 dwStyle
|= LVS_SMALLICON
;
482 if (FolderSettings
.fFlags
& FWF_AUTOARRANGE
)
483 dwStyle
|= LVS_AUTOARRANGE
;
485 if (FolderSettings
.fFlags
& FWF_DESKTOP
)
486 FolderSettings
.fFlags
|= FWF_NOCLIENTEDGE
| FWF_NOSCROLL
;
488 if (FolderSettings
.fFlags
& FWF_SINGLESEL
)
489 dwStyle
|= LVS_SINGLESEL
;
491 if (FolderSettings
.fFlags
& FWF_NOCLIENTEDGE
)
492 dwExStyle
&= ~WS_EX_CLIENTEDGE
;
494 hWndList
=CreateWindowExW( dwExStyle
,
507 ListViewSortInfo
.bIsAscending
= TRUE
;
508 ListViewSortInfo
.nHeaderID
= -1;
509 ListViewSortInfo
.nLastHeaderID
= -1;
511 if (FolderSettings
.fFlags
& FWF_DESKTOP
)
514 * FIXME: look at the registry value
515 * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
516 * and activate drop shadows if necessary
520 SendMessageW(hWndList
, LVM_SETTEXTBKCOLOR
, 0, CLR_NONE
);
521 SendMessageW(hWndList
, LVM_SETBKCOLOR
, 0, CLR_NONE
);
525 SendMessageW(hWndList
, LVM_SETTEXTBKCOLOR
, 0, GetSysColor(COLOR_DESKTOP
));
526 SendMessageW(hWndList
, LVM_SETBKCOLOR
, 0, GetSysColor(COLOR_DESKTOP
));
529 SendMessageW(hWndList
, LVM_SETTEXTCOLOR
, 0, RGB(255,255,255));
532 /* UpdateShellSettings(); */
536 /**********************************************************
537 * ShellView_InitList()
539 * - adds all needed columns to the shellview
541 BOOL
CDefView::InitList()
549 SendMessageW(hWndList
, LVM_DELETEALLITEMS
, 0, 0);
551 lvColumn
.mask
= LVCF_FMT
| LVCF_WIDTH
| LVCF_TEXT
;
552 lvColumn
.pszText
= szTemp
;
556 for (int i
=0; 1; i
++)
558 if (FAILED(pSF2Parent
->GetDetailsOf(NULL
, i
, &sd
)))
561 lvColumn
.fmt
= sd
.fmt
;
562 lvColumn
.cx
= sd
.cxChar
*8; /* chars->pixel */
563 StrRetToStrNW( szTemp
, 50, &sd
.str
, NULL
);
564 SendMessageW(hWndList
, LVM_INSERTCOLUMNW
, i
, (LPARAM
) &lvColumn
);
572 SendMessageW(hWndList
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)ShellSmallIconList
);
573 SendMessageW(hWndList
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)ShellBigIconList
);
578 /**********************************************************
579 * ShellView_CompareItems()
582 * internal, CALLBACK for DSA_Sort
584 INT CALLBACK
CDefView::CompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
)
587 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1
, lParam2
, (LPVOID
) lpData
);
592 ret
= (SHORT
)SCODE_CODE(((IShellFolder
*)lpData
)->CompareIDs(0, (LPITEMIDLIST
)lParam1
, (LPITEMIDLIST
)lParam2
));
593 TRACE("ret=%i\n",ret
);
598 /*************************************************************************
599 * ShellView_ListViewCompareItems
601 * Compare Function for the Listview (FileOpen Dialog)
604 * lParam1 [I] the first ItemIdList to compare with
605 * lParam2 [I] the second ItemIdList to compare with
606 * lpData [I] The column ID for the header Ctrl to process
609 * A negative value if the first item should precede the second,
610 * a positive value if the first item should follow the second,
611 * or zero if the two items are equivalent
614 * FIXME: function does what ShellView_CompareItems is supposed to do.
615 * unify it and figure out how to use the undocumented first parameter
616 * of IShellFolder_CompareIDs to do the job this function does and
617 * move this code to IShellFolder.
618 * make LISTVIEW_SORT_INFO obsolete
619 * the way this function works is only usable if we had only
620 * filesystemfolders (25/10/99 jsch)
622 INT CALLBACK
CDefView::ListViewCompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
)
626 char strName1
[MAX_PATH
], strName2
[MAX_PATH
];
627 BOOL bIsFolder1
, bIsFolder2
,bIsBothFolder
;
628 LPITEMIDLIST pItemIdList1
= (LPITEMIDLIST
) lParam1
;
629 LPITEMIDLIST pItemIdList2
= (LPITEMIDLIST
) lParam2
;
630 LISTVIEW_SORT_INFO
*pSortInfo
= (LPLISTVIEW_SORT_INFO
) lpData
;
633 bIsFolder1
= _ILIsFolder(pItemIdList1
);
634 bIsFolder2
= _ILIsFolder(pItemIdList2
);
635 bIsBothFolder
= bIsFolder1
&& bIsFolder2
;
637 /* When sorting between a File and a Folder, the Folder gets sorted first */
638 if ( (bIsFolder1
|| bIsFolder2
) && !bIsBothFolder
)
640 nDiff
= bIsFolder1
? -1 : 1;
644 /* Sort by Time: Folders or Files can be sorted */
646 if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_TIME
)
648 _ILGetFileDateTime(pItemIdList1
, &fd1
);
649 _ILGetFileDateTime(pItemIdList2
, &fd2
);
650 nDiff
= CompareFileTime(&fd2
, &fd1
);
652 /* Sort by Attribute: Folder or Files can be sorted */
653 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_ATTRIB
)
655 _ILGetFileAttributes(pItemIdList1
, strName1
, MAX_PATH
);
656 _ILGetFileAttributes(pItemIdList2
, strName2
, MAX_PATH
);
657 nDiff
= lstrcmpiA(strName1
, strName2
);
659 /* Sort by FileName: Folder or Files can be sorted */
660 else if (pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_NAME
|| bIsBothFolder
)
663 _ILSimpleGetText(pItemIdList1
, strName1
, MAX_PATH
);
664 _ILSimpleGetText(pItemIdList2
, strName2
, MAX_PATH
);
665 nDiff
= lstrcmpiA(strName1
, strName2
);
667 /* Sort by File Size, Only valid for Files */
668 else if (pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_SIZE
)
670 nDiff
= (INT
)(_ILGetFileSize(pItemIdList1
, NULL
, 0) - _ILGetFileSize(pItemIdList2
, NULL
, 0));
672 /* Sort by File Type, Only valid for Files */
673 else if (pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_TYPE
)
676 _ILGetFileType(pItemIdList1
, strName1
, MAX_PATH
);
677 _ILGetFileType(pItemIdList2
, strName2
, MAX_PATH
);
678 nDiff
= lstrcmpiA(strName1
, strName2
);
681 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
685 _ILSimpleGetText(pItemIdList1
, strName1
, MAX_PATH
);
686 _ILSimpleGetText(pItemIdList2
, strName2
, MAX_PATH
);
687 nDiff
= lstrcmpiA(strName1
, strName2
);
690 if (!pSortInfo
->bIsAscending
)
698 /**********************************************************
699 * LV_FindItemByPidl()
701 int CDefView::LV_FindItemByPidl(LPCITEMIDLIST pidl
)
705 lvItem
.mask
= LVIF_PARAM
;
707 for (lvItem
.iItem
= 0;
708 SendMessageW(hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
711 LPITEMIDLIST currentpidl
= (LPITEMIDLIST
) lvItem
.lParam
;
712 HRESULT hr
= pSFParent
->CompareIDs(0, pidl
, currentpidl
);
714 if (SUCCEEDED(hr
) && !HRESULT_CODE(hr
))
722 /**********************************************************
725 BOOLEAN
CDefView::LV_AddItem(LPCITEMIDLIST pidl
)
729 TRACE("(%p)(pidl=%p)\n", this, pidl
);
731 lvItem
.mask
= LVIF_TEXT
| LVIF_IMAGE
| LVIF_PARAM
; /*set the mask*/
732 lvItem
.iItem
= ListView_GetItemCount(hWndList
); /*add the item to the end of the list*/
734 lvItem
.lParam
= (LPARAM
) ILClone(ILFindLastID(pidl
)); /*set the item's data*/
735 lvItem
.pszText
= LPSTR_TEXTCALLBACKW
; /*get text on a callback basis*/
736 lvItem
.iImage
= I_IMAGECALLBACK
; /*get the image on a callback basis*/
738 if (SendMessageW(hWndList
, LVM_INSERTITEMW
, 0, (LPARAM
)&lvItem
) == -1)
744 /**********************************************************
747 BOOLEAN
CDefView::LV_DeleteItem(LPCITEMIDLIST pidl
)
751 TRACE("(%p)(pidl=%p)\n", this, pidl
);
753 nIndex
= LV_FindItemByPidl(ILFindLastID(pidl
));
755 return (-1 == ListView_DeleteItem(hWndList
, nIndex
)) ? FALSE
: TRUE
;
758 /**********************************************************
761 BOOLEAN
CDefView::LV_RenameItem(LPCITEMIDLIST pidlOld
, LPCITEMIDLIST pidlNew
)
766 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", this, pidlOld
, pidlNew
);
768 nItem
= LV_FindItemByPidl(ILFindLastID(pidlOld
));
772 lvItem
.mask
= LVIF_PARAM
; /* only the pidl */
773 lvItem
.iItem
= nItem
;
774 SendMessageW(hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
776 SHFree((LPITEMIDLIST
)lvItem
.lParam
);
777 lvItem
.mask
= LVIF_PARAM
;
778 lvItem
.iItem
= nItem
;
779 lvItem
.lParam
= (LPARAM
) ILClone(ILFindLastID(pidlNew
)); /* set the item's data */
780 SendMessageW(hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
781 SendMessageW(hWndList
, LVM_UPDATE
, nItem
, 0);
782 return TRUE
; /* FIXME: better handling */
788 /**********************************************************
789 * ShellView_FillList()
791 * - gets the objectlist from the shellfolder
793 * - fills the list into the view
795 INT CALLBACK
CDefView::fill_list( LPVOID ptr
, LPVOID arg
)
797 LPITEMIDLIST pidl
= (LPITEMIDLIST
)ptr
;
798 CDefView
*pThis
= (CDefView
*)arg
;
799 /* in a commdlg This works as a filemask*/
800 if (pThis
->IncludeObject(pidl
) == S_OK
)
801 pThis
->LV_AddItem(pidl
);
807 HRESULT
CDefView::FillList()
809 LPENUMIDLIST pEnumIDList
;
817 /* get the itemlist from the shfolder*/
818 hRes
= pSFParent
->EnumObjects(m_hWnd
, SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
, &pEnumIDList
);
826 /* create a pointer array */
827 hdpa
= DPA_Create(16);
830 return(E_OUTOFMEMORY
);
833 /* copy the items into the array*/
834 while((S_OK
== pEnumIDList
->Next(1, &pidl
, &dwFetched
)) && dwFetched
)
836 if (DPA_InsertPtr(hdpa
, 0x7fff, pidl
) == -1)
843 DPA_Sort(hdpa
, CompareItems
, (LPARAM
)pSFParent
.p
);
845 /*turn the listview's redrawing off*/
846 SendMessageA(hWndList
, WM_SETREDRAW
, FALSE
, 0);
848 DPA_DestroyCallback( hdpa
, fill_list
, (void *)this);
850 /*turn the listview's redrawing back on and force it to draw*/
851 SendMessageA(hWndList
, WM_SETREDRAW
, TRUE
, 0);
853 pEnumIDList
->Release(); /* destroy the list*/
858 LRESULT
CDefView::OnShowWindow(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
860 ::UpdateWindow(hWndList
);
865 LRESULT
CDefView::OnGetDlgCode(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
867 return SendMessageW(hWndList
, uMsg
, 0, 0);
870 LRESULT
CDefView::OnDestroy(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
872 RevokeDragDrop(m_hWnd
);
873 SHChangeNotifyDeregister(hNotify
);
878 LRESULT
CDefView::OnEraseBackground(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
880 if (FolderSettings
.fFlags
& (FWF_DESKTOP
| FWF_TRANSPARENT
))
881 return SendMessageW(GetParent(), WM_ERASEBKGND
, wParam
, lParam
); /* redirect to parent */
887 LRESULT
CDefView::OnSysColorChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
889 /* Forward WM_SYSCOLORCHANGE to common controls */
890 return SendMessageW(hWndList
, uMsg
, 0, 0);
893 LRESULT
CDefView::OnGetShellBrowser(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
895 return (LRESULT
)pShellBrowser
.p
;
898 /**********************************************************
899 * ShellView_OnCreate()
901 LRESULT
CDefView::OnCreate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
903 CComPtr
<IDropTarget
> pdt
;
904 SHChangeNotifyEntry ntreg
;
905 CComPtr
<IPersistFolder2
> ppf2
;
917 if (SUCCEEDED(this->QueryInterface(IID_IDropTarget
, (LPVOID
*)&pdt
)))
918 RegisterDragDrop(m_hWnd
, pdt
);
920 /* register for receiving notifications */
921 pSFParent
->QueryInterface(IID_IPersistFolder2
, (LPVOID
*)&ppf2
);
924 ppf2
->GetCurFolder((LPITEMIDLIST
*)&ntreg
.pidl
);
925 ntreg
.fRecursive
= TRUE
;
926 hNotify
= SHChangeNotifyRegister(m_hWnd
, SHCNF_IDLIST
, SHCNE_ALLEVENTS
, SHV_CHANGE_NOTIFY
, 1, &ntreg
);
927 SHFree((LPITEMIDLIST
)ntreg
.pidl
);
930 hAccel
= LoadAcceleratorsA(shell32_hInstance
, "shv_accel");
935 /**********************************************************
936 * #### Handling of the menus ####
939 /**********************************************************
940 * ShellView_BuildFileMenu()
942 HMENU
CDefView::BuildFileMenu()
943 { WCHAR szText
[MAX_PATH
];
948 TRACE("(%p)\n",this);
950 hSubMenu
= CreatePopupMenu();
953 /*get the number of items in our global array*/
954 for(nTools
= 0; Tools
[nTools
].idCommand
!= -1; nTools
++){}
956 /*add the menu items*/
957 for(i
= 0; i
< nTools
; i
++)
959 LoadStringW(shell32_hInstance
, Tools
[i
].idMenuString
, szText
, MAX_PATH
);
961 ZeroMemory(&mii
, sizeof(mii
));
962 mii
.cbSize
= sizeof(mii
);
963 mii
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
965 if(BTNS_SEP
!= Tools
[i
].bStyle
) /* no separator*/
967 mii
.fType
= MFT_STRING
;
968 mii
.fState
= MFS_ENABLED
;
969 mii
.dwTypeData
= szText
;
970 mii
.wID
= Tools
[i
].idCommand
;
974 mii
.fType
= MFT_SEPARATOR
;
976 /* tack This item onto the end of the menu */
977 InsertMenuItemW(hSubMenu
, (UINT
)-1, TRUE
, &mii
);
981 TRACE("-- return (menu=%p)\n",hSubMenu
);
985 /**********************************************************
986 * ShellView_MergeFileMenu()
988 void CDefView::MergeFileMenu(HMENU hSubMenu
)
990 TRACE("(%p)->(submenu=%p) stub\n",this,hSubMenu
);
993 { /*insert This item at the beginning of the menu */
994 _InsertMenuItemW(hSubMenu
, 0, TRUE
, 0, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
995 _InsertMenuItemW(hSubMenu
, 0, TRUE
, IDM_MYFILEITEM
, MFT_STRING
, L
"dummy45", MFS_ENABLED
);
1001 /**********************************************************
1002 * ShellView_MergeViewMenu()
1004 void CDefView::MergeViewMenu(HMENU hSubMenu
)
1006 TRACE("(%p)->(submenu=%p)\n",this,hSubMenu
);
1010 /*add a separator at the correct position in the menu*/
1012 static WCHAR view
[] = L
"View";
1014 _InsertMenuItemW(hSubMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
, FALSE
, 0, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
1016 ZeroMemory(&mii
, sizeof(mii
));
1017 mii
.cbSize
= sizeof(mii
);
1018 mii
.fMask
= MIIM_SUBMENU
| MIIM_TYPE
| MIIM_DATA
;
1019 mii
.fType
= MFT_STRING
;
1020 mii
.dwTypeData
= view
;
1021 mii
.hSubMenu
= LoadMenuW(shell32_hInstance
, L
"MENU_001");
1022 InsertMenuItemW(hSubMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
, FALSE
, &mii
);
1026 /**********************************************************
1027 * ShellView_GetSelections()
1029 * - fills the this->apidl list with the selected objects
1032 * number of selected items
1034 UINT
CDefView::GetSelections()
1041 cidl
= ListView_GetSelectedCount(hWndList
);
1042 apidl
= (LPITEMIDLIST
*)SHAlloc(cidl
* sizeof(LPITEMIDLIST
));
1044 TRACE("selected=%i\n", cidl
);
1048 TRACE("-- Items selected =%u\n", cidl
);
1050 lvItem
.mask
= LVIF_STATE
| LVIF_PARAM
;
1051 lvItem
.stateMask
= LVIS_SELECTED
;
1053 lvItem
.iSubItem
= 0;
1056 while(SendMessageW(hWndList
, LVM_GETITEMW
, 0, (LPARAM
)&lvItem
) && (i
< cidl
))
1058 if(lvItem
.state
& LVIS_SELECTED
)
1060 apidl
[i
] = (LPITEMIDLIST
)lvItem
.lParam
;
1064 TRACE("-- selected Item found\n");
1073 /**********************************************************
1074 * ShellView_OpenSelectedItems()
1076 HRESULT
CDefView::OpenSelectedItems()
1078 static UINT CF_IDLIST
= 0;
1080 CComPtr
<IDataObject
> selection
;
1081 CComPtr
<IContextMenu
> cm
;
1086 LPCITEMIDLIST parent_pidl
;
1087 WCHAR parent_path
[MAX_PATH
];
1088 LPCWSTR parent_dir
= NULL
;
1091 CMINVOKECOMMANDINFOEX ici
;
1094 if (0 == GetSelections())
1099 hr
= pSFParent
->GetUIObjectOf(m_hWnd
, cidl
,
1100 (LPCITEMIDLIST
*)apidl
, IID_IContextMenu
,
1105 hmenu
= CreatePopupMenu();
1108 hr
= IUnknown_SetSite(cm
, (IShellView
*)this);
1109 if (SUCCEEDED(cm
->QueryContextMenu(hmenu
, 0, 0x20, 0x7fff, CMF_DEFAULTONLY
)))
1111 INT def
= -1, n
= GetMenuItemCount(hmenu
);
1113 for ( i
= 0; i
< n
; i
++ )
1115 memset( &info
, 0, sizeof info
);
1116 info
.cbSize
= sizeof info
;
1117 info
.fMask
= MIIM_FTYPE
| MIIM_STATE
| MIIM_ID
;
1118 if (GetMenuItemInfoW( hmenu
, i
, TRUE
, &info
))
1120 if (info
.fState
& MFS_DEFAULT
)
1129 memset( &ici
, 0, sizeof ici
);
1130 ici
.cbSize
= sizeof ici
;
1131 ici
.lpVerb
= MAKEINTRESOURCEA( def
);
1134 if (cm
->InvokeCommand((LPCMINVOKECOMMANDINFO
) &ici
) == S_OK
)
1136 DestroyMenu( hmenu
);
1137 hr
= IUnknown_SetSite(cm
, NULL
);
1143 DestroyMenu( hmenu
);
1144 hr
= IUnknown_SetSite(cm
, NULL
);
1151 hr
= pSFParent
->GetUIObjectOf(m_hWnd
, cidl
,
1152 (LPCITEMIDLIST
*)apidl
, IID_IDataObject
,
1153 0, (LPVOID
*)&selection
);
1162 CF_IDLIST
= RegisterClipboardFormatW(CFSTR_SHELLIDLIST
);
1165 fetc
.cfFormat
= CF_IDLIST
;
1167 fetc
.dwAspect
= DVASPECT_CONTENT
;
1169 fetc
.tymed
= TYMED_HGLOBAL
;
1171 hr
= selection
->QueryGetData(&fetc
);
1175 hr
= selection
->GetData(&fetc
, &stgm
);
1179 pIDList
= (LPIDA
)GlobalLock(stgm
.hGlobal
);
1181 parent_pidl
= (LPCITEMIDLIST
) ((LPBYTE
)pIDList
+pIDList
->aoffset
[0]);
1182 hr
= pSFParent
->GetAttributesOf(1, &parent_pidl
, &attribs
);
1183 if (SUCCEEDED(hr
) && (attribs
& SFGAO_FILESYSTEM
) &&
1184 SHGetPathFromIDListW(parent_pidl
, parent_path
))
1186 parent_dir
= parent_path
;
1189 for (i
= pIDList
->cidl
; i
> 0; --i
)
1193 pidl
= (LPCITEMIDLIST
)((LPBYTE
)pIDList
+pIDList
->aoffset
[i
]);
1195 attribs
= SFGAO_FOLDER
;
1196 hr
= pSFParent
->GetAttributesOf(1, &pidl
, &attribs
);
1198 if (SUCCEEDED(hr
) && ! (attribs
& SFGAO_FOLDER
))
1200 SHELLEXECUTEINFOW shexinfo
;
1202 shexinfo
.cbSize
= sizeof(SHELLEXECUTEINFOW
);
1203 shexinfo
.fMask
= SEE_MASK_INVOKEIDLIST
; /* SEE_MASK_IDLIST is also possible. */
1204 shexinfo
.hwnd
= NULL
;
1205 shexinfo
.lpVerb
= NULL
;
1206 shexinfo
.lpFile
= NULL
;
1207 shexinfo
.lpParameters
= NULL
;
1208 shexinfo
.lpDirectory
= parent_dir
;
1209 shexinfo
.nShow
= SW_NORMAL
;
1210 shexinfo
.lpIDList
= ILCombine(parent_pidl
, pidl
);
1212 ShellExecuteExW(&shexinfo
); /* Discard error/success info */
1214 ILFree((LPITEMIDLIST
)shexinfo
.lpIDList
);
1218 GlobalUnlock(stgm
.hGlobal
);
1219 ReleaseStgMedium(&stgm
);
1224 /**********************************************************
1225 * ShellView_DoContextMenu()
1227 LRESULT
CDefView::OnContextMenu(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1237 CMINVOKECOMMANDINFO cmi
;
1240 // for some reason I haven't figured out, we sometimes recurse into this method
1248 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",this, x
, y
, bDefault
);
1253 /* look, what's selected and create a context menu object of it*/
1254 if (GetSelections())
1256 pSFParent
->GetUIObjectOf(hWndParent
, cidl
, (LPCITEMIDLIST
*)apidl
, IID_IContextMenu
, NULL
, (LPVOID
*)&pCM
);
1260 TRACE("-- pContextMenu\n");
1261 hMenu
= CreatePopupMenu();
1265 hResult
= IUnknown_SetSite(pCM
, (IShellView
*)this);
1267 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
1268 if (SUCCEEDED(pShellBrowser
->GetControlWindow(FCW_TREE
, &hwndTree
)) && hwndTree
)
1270 TRACE("-- explore mode\n");
1274 /* build the flags depending on what we can do with the selected item */
1275 wFlags
= CMF_NORMAL
| (cidl
!= 1 ? 0 : CMF_CANRENAME
) | (fExplore
? CMF_EXPLORE
: 0);
1277 /* let the ContextMenu merge its items in */
1278 if (SUCCEEDED(pCM
->QueryContextMenu(hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, wFlags
)))
1280 if (FolderSettings
.fFlags
& FWF_DESKTOP
)
1281 SetMenuDefaultItem(hMenu
, FCIDM_SHVIEW_OPEN
, MF_BYCOMMAND
);
1285 TRACE("-- get menu default command\n");
1286 uCommand
= GetMenuDefaultItem(hMenu
, FALSE
, GMDI_GOINTOPOPUPS
);
1290 TRACE("-- track popup\n");
1291 uCommand
= TrackPopupMenu( hMenu
,TPM_LEFTALIGN
| TPM_RETURNCMD
,x
,y
,0,m_hWnd
,NULL
);
1296 TRACE("-- uCommand=%u\n", uCommand
);
1298 if (uCommand
==FCIDM_SHVIEW_OPEN
&& pCommDlgBrowser
.p
!= NULL
)
1300 TRACE("-- dlg: OnDefaultCommand\n");
1301 if (OnDefaultCommand() != S_OK
)
1303 OpenSelectedItems();
1308 TRACE("-- explore -- invoke command\n");
1309 ZeroMemory(&cmi
, sizeof(cmi
));
1310 cmi
.cbSize
= sizeof(cmi
);
1311 cmi
.hwnd
= hWndParent
; /* this window has to answer CWM_GETISHELLBROWSER */
1312 cmi
.lpVerb
= (LPCSTR
)MAKEINTRESOURCEA(uCommand
);
1313 pCM
->InvokeCommand(&cmi
);
1317 hResult
= IUnknown_SetSite(pCM
, NULL
);
1324 else /* background context menu */
1326 hMenu
= CreatePopupMenu();
1328 CDefFolderMenu_Create2(NULL
, NULL
, cidl
, (LPCITEMIDLIST
*)apidl
, pSFParent
, NULL
, 0, NULL
, (IContextMenu
**)&pCM
);
1329 pCM
->QueryContextMenu(hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, 0);
1331 uCommand
= TrackPopupMenu( hMenu
, TPM_LEFTALIGN
| TPM_RETURNCMD
,x
,y
,0,m_hWnd
,NULL
);
1334 TRACE("-- (%p)->(uCommand=0x%08x )\n",this, uCommand
);
1336 ZeroMemory(&cmi
, sizeof(cmi
));
1337 cmi
.cbSize
= sizeof(cmi
);
1338 cmi
.lpVerb
= (LPCSTR
)MAKEINTRESOURCEA(uCommand
);
1339 cmi
.hwnd
= hWndParent
;
1340 pCM
->InvokeCommand(&cmi
);
1348 /**********************************************************
1349 * ##### message handling #####
1352 /**********************************************************
1353 * ShellView_OnSize()
1355 LRESULT
CDefView::OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1360 wWidth
= LOWORD(lParam
);
1361 wHeight
= HIWORD(lParam
);
1363 TRACE("%p width=%u height=%u\n", this, wWidth
, wHeight
);
1365 /*resize the ListView to fit our window*/
1368 ::MoveWindow(hWndList
, 0, 0, wWidth
, wHeight
, TRUE
);
1374 /**********************************************************
1375 * ShellView_OnDeactivate()
1380 void CDefView::OnDeactivate()
1384 if (uState
!= SVUIA_DEACTIVATE
)
1388 pShellBrowser
->SetMenuSB(0, 0, 0);
1389 pShellBrowser
->RemoveMenusSB(hMenu
);
1394 uState
= SVUIA_DEACTIVATE
;
1398 void CDefView::DoActivate(UINT uState
)
1400 OLEMENUGROUPWIDTHS omw
= { {0, 0, 0, 0, 0, 0} };
1402 CHAR szText
[MAX_PATH
];
1404 TRACE("%p uState=%x\n", this, uState
);
1406 /*don't do anything if the state isn't really changing */
1407 if (uState
== uState
)
1414 /*only do This if we are active */
1415 if(uState
!= SVUIA_DEACTIVATE
)
1417 /*merge the menus */
1418 hMenu
= CreateMenu();
1422 pShellBrowser
->InsertMenusSB(hMenu
, &omw
);
1423 TRACE("-- after fnInsertMenusSB\n");
1425 /*build the top level menu get the menu item's text*/
1426 strcpy(szText
,"dummy 31");
1428 ZeroMemory(&mii
, sizeof(mii
));
1429 mii
.cbSize
= sizeof(mii
);
1430 mii
.fMask
= MIIM_SUBMENU
| MIIM_TYPE
| MIIM_STATE
;
1431 mii
.fType
= MFT_STRING
;
1432 mii
.fState
= MFS_ENABLED
;
1433 mii
.dwTypeData
= szText
;
1434 mii
.hSubMenu
= BuildFileMenu();
1436 /*insert our menu into the menu bar*/
1439 InsertMenuItemA(hMenu
, FCIDM_MENU_HELP
, FALSE
, &mii
);
1442 /*get the view menu so we can merge with it*/
1443 ZeroMemory(&mii
, sizeof(mii
));
1444 mii
.cbSize
= sizeof(mii
);
1445 mii
.fMask
= MIIM_SUBMENU
;
1447 if (GetMenuItemInfoA(hMenu
, FCIDM_MENU_VIEW
, FALSE
, &mii
))
1449 MergeViewMenu(mii
.hSubMenu
);
1452 /*add the items that should only be added if we have the focus*/
1453 if (SVUIA_ACTIVATE_FOCUS
== uState
)
1455 /*get the file menu so we can merge with it */
1456 ZeroMemory(&mii
, sizeof(mii
));
1457 mii
.cbSize
= sizeof(mii
);
1458 mii
.fMask
= MIIM_SUBMENU
;
1460 if (GetMenuItemInfoA(hMenu
, FCIDM_MENU_FILE
, FALSE
, &mii
))
1462 MergeFileMenu(mii
.hSubMenu
);
1466 TRACE("-- before fnSetMenuSB\n");
1467 pShellBrowser
->SetMenuSB(hMenu
, 0, m_hWnd
);
1474 /**********************************************************
1475 * ShellView_OnActivate()
1477 LRESULT
CDefView::OnActivate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1479 DoActivate(SVUIA_ACTIVATE_FOCUS
);
1483 /**********************************************************
1484 * ShellView_OnSetFocus()
1487 LRESULT
CDefView::OnSetFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1489 TRACE("%p\n", this);
1491 /* Tell the browser one of our windows has received the focus. This
1492 should always be done before merging menus (OnActivate merges the
1493 menus) if one of our windows has the focus.*/
1495 pShellBrowser
->OnViewWindowActive((IShellView
*)this);
1496 DoActivate(SVUIA_ACTIVATE_FOCUS
);
1498 /* Set the focus to the listview */
1499 ::SetFocus(hWndList
);
1501 /* Notify the ICommDlgBrowser interface */
1502 OnStateChange(CDBOSC_SETFOCUS
);
1507 /**********************************************************
1508 * ShellView_OnKillFocus()
1510 LRESULT
CDefView::OnKillFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1512 TRACE("(%p) stub\n", this);
1514 DoActivate(SVUIA_ACTIVATE_NOFOCUS
);
1515 /* Notify the ICommDlgBrowser */
1516 OnStateChange(CDBOSC_KILLFOCUS
);
1521 /**********************************************************
1522 * ShellView_OnCommand()
1525 * the CmdID's are the ones from the context menu
1527 LRESULT
CDefView::OnCommand(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1533 dwCmdID
= GET_WM_COMMAND_ID(wParam
, lParam
);
1534 dwCmd
= GET_WM_COMMAND_CMD(wParam
, lParam
);
1535 hwndCmd
= GET_WM_COMMAND_HWND(wParam
, lParam
);
1537 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",this, dwCmdID
, dwCmd
, hwndCmd
);
1541 case FCIDM_SHVIEW_SMALLICON
:
1542 FolderSettings
.ViewMode
= FVM_SMALLICON
;
1543 SetStyle (LVS_SMALLICON
, LVS_TYPEMASK
);
1547 case FCIDM_SHVIEW_BIGICON
:
1548 FolderSettings
.ViewMode
= FVM_ICON
;
1549 SetStyle (LVS_ICON
, LVS_TYPEMASK
);
1553 case FCIDM_SHVIEW_LISTVIEW
:
1554 FolderSettings
.ViewMode
= FVM_LIST
;
1555 SetStyle (LVS_LIST
, LVS_TYPEMASK
);
1559 case FCIDM_SHVIEW_REPORTVIEW
:
1560 FolderSettings
.ViewMode
= FVM_DETAILS
;
1561 SetStyle (LVS_REPORT
, LVS_TYPEMASK
);
1565 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1570 ListViewSortInfo
.nHeaderID
= (LPARAM
) (dwCmdID
- 0x30);
1571 ListViewSortInfo
.bIsAscending
= TRUE
;
1572 ListViewSortInfo
.nLastHeaderID
= ListViewSortInfo
.nHeaderID
;
1573 SendMessageA(hWndList
, LVM_SORTITEMS
, (WPARAM
) &ListViewSortInfo
, (LPARAM
)ListViewCompareItems
);
1577 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID
);
1583 /**********************************************************
1584 * ShellView_OnNotify()
1587 LRESULT
CDefView::OnNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1591 LPNMLISTVIEW lpnmlv
;
1592 NMLVDISPINFOW
*lpdi
;
1597 lpnmh
= (LPNMHDR
)lParam
;
1598 lpnmlv
= (LPNMLISTVIEW
)lpnmh
;
1599 lpdi
= (NMLVDISPINFOW
*)lpnmh
;
1601 TRACE("%p CtlID=%u lpnmh->code=%x\n",this,CtlID
,lpnmh
->code
);
1603 switch (lpnmh
->code
)
1606 TRACE("-- NM_SETFOCUS %p\n", this);
1607 OnSetFocus(0, 0, 0, unused
);
1611 TRACE("-- NM_KILLFOCUS %p\n", this);
1613 /* Notify the ICommDlgBrowser interface */
1614 OnStateChange(CDBOSC_KILLFOCUS
);
1618 TRACE("-- NM_CUSTOMDRAW %p\n", this);
1619 return CDRF_DODEFAULT
;
1621 case NM_RELEASEDCAPTURE
:
1622 TRACE("-- NM_RELEASEDCAPTURE %p\n", this);
1626 TRACE("-- NM_CLICK %p\n", this);
1630 TRACE("-- NM_RCLICK %p\n", this);
1634 TRACE("-- NM_DBLCLK %p\n", this);
1635 if (OnDefaultCommand() != S_OK
) OpenSelectedItems();
1639 TRACE("-- NM_RETURN %p\n", this);
1640 if (OnDefaultCommand() != S_OK
) OpenSelectedItems();
1644 TRACE("-- HDN_ENDTRACKW %p\n", this);
1645 /*nColumn1 = ListView_GetColumnWidth(hWndList, 0);
1646 nColumn2 = ListView_GetColumnWidth(hWndList, 1);*/
1649 case LVN_DELETEITEM
:
1650 TRACE("-- LVN_DELETEITEM %p\n", this);
1651 SHFree((LPITEMIDLIST
)lpnmlv
->lParam
); /*delete the pidl because we made a copy of it*/
1654 case LVN_DELETEALLITEMS
:
1655 TRACE("-- LVN_DELETEALLITEMS %p\n", this);
1658 case LVN_INSERTITEM
:
1659 TRACE("-- LVN_INSERTITEM (STUB)%p\n", this);
1662 case LVN_ITEMACTIVATE
:
1663 TRACE("-- LVN_ITEMACTIVATE %p\n", this);
1664 OnStateChange(CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1667 case LVN_COLUMNCLICK
:
1668 ListViewSortInfo
.nHeaderID
= lpnmlv
->iSubItem
;
1669 if (ListViewSortInfo
.nLastHeaderID
== ListViewSortInfo
.nHeaderID
)
1671 ListViewSortInfo
.bIsAscending
= !ListViewSortInfo
.bIsAscending
;
1675 ListViewSortInfo
.bIsAscending
= TRUE
;
1677 ListViewSortInfo
.nLastHeaderID
= ListViewSortInfo
.nHeaderID
;
1679 SendMessageW(lpnmlv
->hdr
.hwndFrom
, LVM_SORTITEMS
, (WPARAM
) &ListViewSortInfo
, (LPARAM
)ListViewCompareItems
);
1682 case LVN_GETDISPINFOA
:
1683 case LVN_GETDISPINFOW
:
1684 TRACE("-- LVN_GETDISPINFO %p\n", this);
1685 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1687 if (lpdi
->item
.mask
& LVIF_TEXT
) /* text requested */
1692 pSF2Parent
->GetDetailsOf(pidl
, lpdi
->item
.iSubItem
, &sd
);
1693 if (lpnmh
->code
== LVN_GETDISPINFOA
)
1695 /* shouldn't happen */
1696 NMLVDISPINFOA
*lpdiA
= (NMLVDISPINFOA
*)lpnmh
;
1697 StrRetToStrNA( lpdiA
->item
.pszText
, lpdiA
->item
.cchTextMax
, &sd
.str
, NULL
);
1698 TRACE("-- text=%s\n",lpdiA
->item
.pszText
);
1700 else /* LVN_GETDISPINFOW */
1702 StrRetToStrNW( lpdi
->item
.pszText
, lpdi
->item
.cchTextMax
, &sd
.str
, NULL
);
1703 TRACE("-- text=%s\n",debugstr_w(lpdi
->item
.pszText
));
1711 if(lpdi
->item
.mask
& LVIF_IMAGE
) /* image requested */
1713 lpdi
->item
.iImage
= SHMapPIDLToSystemImageListIndex(pSFParent
, pidl
, 0);
1715 lpdi
->item
.mask
|= LVIF_DI_SETITEM
;
1718 case LVN_ITEMCHANGED
:
1719 TRACE("-- LVN_ITEMCHANGED %p\n", this);
1720 OnStateChange(CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1724 case LVN_BEGINRDRAG
:
1725 TRACE("-- LVN_BEGINDRAG\n");
1727 if (GetSelections())
1730 DWORD dwAttributes
= SFGAO_CANLINK
;
1731 DWORD dwEffect
= DROPEFFECT_COPY
| DROPEFFECT_MOVE
;
1733 if (SUCCEEDED(pSFParent
->GetUIObjectOf(m_hWnd
, cidl
, (LPCITEMIDLIST
*)apidl
, IID_IDataObject
,0,(LPVOID
*)&pda
)))
1735 IDropSource
* pds
= (IDropSource
*)this; /* own DropSource interface */
1737 if (SUCCEEDED(pSFParent
->GetAttributesOf(cidl
, (LPCITEMIDLIST
*)apidl
, &dwAttributes
)))
1739 if (dwAttributes
& SFGAO_CANLINK
)
1741 dwEffect
|= DROPEFFECT_LINK
;
1748 DoDragDrop(pda
, pds
, dwEffect
, &dwEffect2
);
1755 case LVN_BEGINLABELEDITW
:
1757 DWORD dwAttr
= SFGAO_CANRENAME
;
1758 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1760 TRACE("-- LVN_BEGINLABELEDITW %p\n", this);
1762 pSFParent
->GetAttributesOf(1, (LPCITEMIDLIST
*)&pidl
, &dwAttr
);
1763 if (SFGAO_CANRENAME
& dwAttr
)
1770 case LVN_ENDLABELEDITW
:
1772 TRACE("-- LVN_ENDLABELEDITW %p\n", this);
1773 if (lpdi
->item
.pszText
)
1778 lvItem
.iItem
= lpdi
->item
.iItem
;
1779 lvItem
.iSubItem
= 0;
1780 lvItem
.mask
= LVIF_PARAM
;
1781 SendMessageW(hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
1783 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1784 hr
= pSFParent
->SetNameOf(0, pidl
, lpdi
->item
.pszText
, SHGDN_INFOLDER
, &pidl
);
1786 if (SUCCEEDED(hr
) && pidl
)
1788 lvItem
.mask
= LVIF_PARAM
;
1789 lvItem
.lParam
= (LPARAM
)pidl
;
1790 SendMessageW(hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
1803 msg.message = WM_KEYDOWN;
1804 msg.wParam = plvKeyDown->wVKey;
1809 LPNMLVKEYDOWN plvKeyDown
= (LPNMLVKEYDOWN
) lpnmh
;
1810 SHORT ctrl
= GetKeyState(VK_CONTROL
) & 0x8000;
1812 /* initiate a rename of the selected file or directory */
1813 if (plvKeyDown
->wVKey
== VK_F2
)
1815 /* see how many files are selected */
1816 int i
= ListView_GetSelectedCount(hWndList
);
1818 /* get selected item */
1821 /* get selected item */
1822 i
= ListView_GetNextItem(hWndList
, -1, LVNI_SELECTED
);
1824 SendMessageW(hWndList
, LVM_ENSUREVISIBLE
, i
, 0);
1825 SendMessageW(hWndList
, LVM_EDITLABELW
, i
, 0);
1829 TranslateAccelerator(m_hWnd
, hAccel
, &msg
)
1831 else if(plvKeyDown
->wVKey
== VK_DELETE
)
1836 LPITEMIDLIST
* pItems
;
1839 pSFParent
->QueryInterface(IID_ISFHelper
,
1845 if (!(i
= ListView_GetSelectedCount(hWndList
)))
1848 /* allocate memory for the pidl array */
1849 pItems
= (LPITEMIDLIST
*)HeapAlloc(GetProcessHeap(), 0,
1850 sizeof(LPITEMIDLIST
) * i
);
1852 /* retrieve all selected items */
1855 while (ListView_GetSelectedCount(hWndList
) > i
)
1857 /* get selected item */
1858 item_index
= ListView_GetNextItem(hWndList
,
1859 item_index
, LVNI_SELECTED
);
1860 item
.iItem
= item_index
;
1861 item
.mask
= LVIF_PARAM
;
1862 SendMessageA(hWndList
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1865 pItems
[i
] = (LPITEMIDLIST
)item
.lParam
;
1870 /* perform the item deletion */
1871 psfhlp
->DeleteItems(i
, (LPCITEMIDLIST
*)pItems
);
1873 /* free pidl array memory */
1874 HeapFree(GetProcessHeap(), 0, pItems
);
1876 /* Initiate a refresh */
1877 else if (plvKeyDown
->wVKey
== VK_F5
)
1881 else if (plvKeyDown
->wVKey
== VK_BACK
)
1883 LPSHELLBROWSER lpSb
;
1884 if ((lpSb
= (LPSHELLBROWSER
)SendMessageW(hWndParent
, CWM_GETISHELLBROWSER
, 0, 0)))
1886 lpSb
->BrowseObject(NULL
, SBSP_PARENT
);
1889 else if (plvKeyDown
->wVKey
== 'C' && ctrl
)
1891 if (GetSelections())
1893 CComPtr
<IDataObject
> pda
;
1895 if (SUCCEEDED(pSFParent
->GetUIObjectOf(m_hWnd
, cidl
, (LPCITEMIDLIST
*)apidl
, IID_IDataObject
, 0, (LPVOID
*)&pda
)))
1897 HRESULT hr
= OleSetClipboard(pda
);
1900 WARN("OleSetClipboard failed");
1906 else if(plvKeyDown
->wVKey
== 'V' && ctrl
)
1908 CComPtr
<IDataObject
> pda
;
1910 FORMATETC formatetc
;
1911 LPITEMIDLIST
* apidl
;
1913 CComPtr
<IShellFolder
> psfFrom
;
1914 CComPtr
<IShellFolder
> psfDesktop
;
1915 CComPtr
<IShellFolder
> psfTarget
;
1917 CComPtr
<ISFHelper
> psfhlpdst
;
1918 CComPtr
<ISFHelper
> psfhlpsrc
;
1921 hr
= OleGetClipboard(&pda
);
1924 ERR("Failed to get clipboard with %lx\n", hr
);
1928 InitFormatEtc(formatetc
, RegisterClipboardFormatW(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
1929 hr
= pda
->GetData(&formatetc
, &medium
);
1933 ERR("Failed to get clipboard data with %lx\n", hr
);
1937 /* lock the handle */
1938 lpcida
= (LPIDA
)GlobalLock(medium
.hGlobal
);
1941 ERR("failed to lock pidl\n");
1942 ReleaseStgMedium(&medium
);
1946 /* convert the data into pidl */
1947 apidl
= _ILCopyCidaToaPidl(&pidl
, lpcida
);
1951 ERR("failed to copy pidl\n");
1955 if (FAILED(SHGetDesktopFolder(&psfDesktop
)))
1957 ERR("failed to get desktop folder\n");
1959 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1960 ReleaseStgMedium(&medium
);
1964 if (_ILIsDesktop(pidl
))
1966 /* use desktop shellfolder */
1967 psfFrom
= psfDesktop
;
1969 else if (FAILED(psfDesktop
->BindToObject(pidl
, NULL
, IID_IShellFolder
, (LPVOID
*)&psfFrom
)))
1971 ERR("no IShellFolder\n");
1974 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1975 ReleaseStgMedium(&medium
);
1980 psfTarget
= pSFParent
;
1983 /* get source and destination shellfolder */
1984 if (FAILED(psfTarget
->QueryInterface(IID_ISFHelper
, (LPVOID
*)&psfhlpdst
)))
1986 ERR("no IID_ISFHelper for destination\n");
1989 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1990 ReleaseStgMedium(&medium
);
1995 if (FAILED(psfFrom
->QueryInterface(IID_ISFHelper
, (LPVOID
*)&psfhlpsrc
)))
1997 ERR("no IID_ISFHelper for source\n");
2000 _ILFreeaPidl(apidl
, lpcida
->cidl
);
2001 ReleaseStgMedium(&medium
);
2006 * do we want to perform a copy or move ???
2008 hr
= psfhlpdst
->CopyItems(psfFrom
, lpcida
->cidl
, (LPCITEMIDLIST
*)apidl
);
2011 _ILFreeaPidl(apidl
, lpcida
->cidl
);
2012 ReleaseStgMedium(&medium
);
2014 TRACE("paste end hr %x\n", hr
);
2018 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown
->wVKey
);
2023 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh
->code
);
2030 /**********************************************************
2031 * ShellView_OnChange()
2033 LRESULT
CDefView::OnChangeNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2035 LPITEMIDLIST
*Pidls
;
2037 Pidls
= (LPITEMIDLIST
*)wParam
;
2039 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls
[0], Pidls
[1], lParam
);
2045 LV_AddItem(Pidls
[0]);
2050 LV_DeleteItem(Pidls
[0]);
2053 case SHCNE_RENAMEFOLDER
:
2054 case SHCNE_RENAMEITEM
:
2055 LV_RenameItem(Pidls
[0], Pidls
[1]);
2058 case SHCNE_UPDATEITEM
:
2065 /**********************************************************
2066 * ShellView_DoMeasureItem
2068 LRESULT
CDefView::OnCustomItem(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2073 ERR("no menu!!!\n");
2077 if (pCM
.p
->HandleMenuMsg(uMsg
, (WPARAM
)m_hWnd
, lParam
) == S_OK
)
2083 /**********************************************************
2086 * The INTERFACE of the IShellView object
2089 **********************************************************
2092 /**********************************************************
2093 * ShellView_GetWindow
2095 HRESULT WINAPI
CDefView::GetWindow(HWND
*phWnd
)
2097 TRACE("(%p)\n",this);
2104 HRESULT WINAPI
CDefView::ContextSensitiveHelp(BOOL fEnterMode
)
2106 FIXME("(%p) stub\n",this);
2111 /**********************************************************
2112 * IShellView_TranslateAccelerator
2115 * use the accel functions
2117 HRESULT WINAPI
CDefView::TranslateAccelerator(LPMSG lpmsg
)
2120 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",this,lpmsg
, lpmsg
->hwnd
, lpmsg
->message
, lpmsg
->lParam
, lpmsg
->wParam
);
2123 if (lpmsg
->message
>= WM_KEYFIRST
&& lpmsg
->message
>= WM_KEYLAST
)
2125 TRACE("-- key=0x04%lx\n",lpmsg
->wParam
) ;
2128 return S_FALSE
; /* not handled */
2131 HRESULT WINAPI
CDefView::EnableModeless(BOOL fEnable
)
2133 FIXME("(%p) stub\n",this);
2138 HRESULT WINAPI
CDefView::UIActivate(UINT uState
)
2141 CHAR szName[MAX_PATH];
2144 int nPartArray
[1] = {-1};
2146 TRACE("(%p)->(state=%x) stub\n",this, uState
);
2148 /*don't do anything if the state isn't really changing*/
2149 if (uState
== uState
)
2154 /*OnActivate handles the menu merging and internal state*/
2157 /*only do This if we are active*/
2158 if (uState
!= SVUIA_DEACTIVATE
)
2162 GetFolderPath is not a method of IShellFolder
2163 IShellFolder_GetFolderPath( pSFParent, szName, sizeof(szName) );
2165 /* set the number of parts */
2166 pShellBrowser
->SendControlMsg(FCW_STATUS
, SB_SETPARTS
, 1, (LPARAM
)nPartArray
, &lResult
);
2168 /* set the text for the parts */
2170 pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult);
2177 HRESULT WINAPI
CDefView::Refresh()
2179 TRACE("(%p)\n",this);
2181 SendMessageW(hWndList
, LVM_DELETEALLITEMS
, 0, 0);
2187 HRESULT WINAPI
CDefView::CreateViewWindow(IShellView
*lpPrevView
, LPCFOLDERSETTINGS lpfs
, IShellBrowser
*psb
, RECT
*prcView
, HWND
*phWnd
)
2191 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",this, lpPrevView
,lpfs
, psb
, prcView
, phWnd
);
2194 TRACE("-- vmode=%x flags=%x\n", lpfs
->ViewMode
, lpfs
->fFlags
);
2195 if (prcView
!= NULL
)
2196 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView
->left
, prcView
->top
, prcView
->right
, prcView
->bottom
);
2198 /* Validate the Shell Browser */
2200 return E_UNEXPECTED
;
2202 /*set up the member variables*/
2203 pShellBrowser
= psb
;
2204 FolderSettings
= *lpfs
;
2206 /*get our parent window*/
2207 pShellBrowser
->GetWindow(&hWndParent
);
2209 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
2210 pCommDlgBrowser
= NULL
;
2211 if (SUCCEEDED(pShellBrowser
->QueryInterface(IID_ICommDlgBrowser
, (LPVOID
*)&pCommDlgBrowser
)))
2213 TRACE("-- CommDlgBrowser\n");
2216 Create(hWndParent
, prcView
, NULL
, WS_CHILD
| WS_TABSTOP
, 0, 0U);
2227 SetWindowPos(HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_SHOWWINDOW
);
2233 HRESULT WINAPI
CDefView::DestroyViewWindow()
2235 TRACE("(%p)\n",this);
2237 /*Make absolutely sure all our UI is cleaned up.*/
2238 UIActivate(SVUIA_DEACTIVATE
);
2246 pShellBrowser
.Release();
2247 pCommDlgBrowser
.Release();
2252 HRESULT WINAPI
CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs
)
2254 TRACE("(%p)->(%p) vmode=%x flags=%x\n",this, lpfs
,
2255 FolderSettings
.ViewMode
, FolderSettings
.fFlags
);
2258 return E_INVALIDARG
;
2260 *lpfs
= FolderSettings
;
2264 HRESULT WINAPI
CDefView::AddPropertySheetPages(DWORD dwReserved
,LPFNADDPROPSHEETPAGE lpfn
, LPARAM lparam
)
2266 FIXME("(%p) stub\n",this);
2271 HRESULT WINAPI
CDefView::SaveViewState()
2273 FIXME("(%p) stub\n",this);
2278 HRESULT WINAPI
CDefView::SelectItem(LPCITEMIDLIST pidl
, UINT uFlags
)
2282 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",this, pidl
, uFlags
);
2284 i
= LV_FindItemByPidl(pidl
);
2290 if(uFlags
& SVSI_ENSUREVISIBLE
)
2291 SendMessageW(hWndList
, LVM_ENSUREVISIBLE
, i
, 0);
2293 lvItem
.mask
= LVIF_STATE
;
2294 lvItem
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
2296 lvItem
.iSubItem
= 0;
2298 while (SendMessageW(hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
))
2300 if (lvItem
.iItem
== i
)
2302 if (uFlags
& SVSI_SELECT
)
2303 lvItem
.state
|= LVIS_SELECTED
;
2305 lvItem
.state
&= ~LVIS_SELECTED
;
2307 if (uFlags
& SVSI_FOCUSED
)
2308 lvItem
.state
&= ~LVIS_FOCUSED
;
2312 if (uFlags
& SVSI_DESELECTOTHERS
)
2313 lvItem
.state
&= ~LVIS_SELECTED
;
2316 SendMessageW(hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
2321 if(uFlags
& SVSI_EDIT
)
2322 SendMessageW(hWndList
, LVM_EDITLABELW
, i
, 0);
2328 HRESULT WINAPI
CDefView::GetItemObject(UINT uItem
, REFIID riid
, LPVOID
*ppvOut
)
2330 HRESULT hr
= E_FAIL
;
2332 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",this, uItem
, debugstr_guid(&riid
), ppvOut
);
2338 case SVGIO_BACKGROUND
:
2339 if (IsEqualIID(riid
, IID_IContextMenu
))
2341 //*ppvOut = ISvBgCm_Constructor(pSFParent, FALSE);
2342 CDefFolderMenu_Create2(NULL
, NULL
, cidl
, (LPCITEMIDLIST
*)apidl
, pSFParent
, NULL
, 0, NULL
, (IContextMenu
**)ppvOut
);
2348 case SVGIO_SELECTION
:
2350 hr
= pSFParent
->GetUIObjectOf(m_hWnd
, cidl
, (LPCITEMIDLIST
*)apidl
, riid
, 0, ppvOut
);
2354 TRACE("-- (%p)->(interface=%p)\n",this, *ppvOut
);
2359 HRESULT STDMETHODCALLTYPE
CDefView::GetCurrentViewMode(UINT
*pViewMode
)
2364 HRESULT STDMETHODCALLTYPE
CDefView::SetCurrentViewMode(UINT ViewMode
)
2369 HRESULT STDMETHODCALLTYPE
CDefView::GetFolder(REFIID riid
, void **ppv
)
2371 if (pSFParent
== NULL
)
2374 return pSFParent
->QueryInterface(riid
, ppv
);
2377 HRESULT STDMETHODCALLTYPE
CDefView::Item(int iItemIndex
, LPITEMIDLIST
*ppidl
)
2382 HRESULT STDMETHODCALLTYPE
CDefView::ItemCount(UINT uFlags
, int *pcItems
)
2387 HRESULT STDMETHODCALLTYPE
CDefView::Items(UINT uFlags
, REFIID riid
, void **ppv
)
2392 HRESULT STDMETHODCALLTYPE
CDefView::GetSelectionMarkedItem(int *piItem
)
2397 HRESULT STDMETHODCALLTYPE
CDefView::GetFocusedItem(int *piItem
)
2402 HRESULT STDMETHODCALLTYPE
CDefView::GetItemPosition(LPCITEMIDLIST pidl
, POINT
*ppt
)
2407 HRESULT STDMETHODCALLTYPE
CDefView::GetSpacing(POINT
*ppt
)
2412 HRESULT STDMETHODCALLTYPE
CDefView::GetDefaultSpacing(POINT
*ppt
)
2417 HRESULT STDMETHODCALLTYPE
CDefView::GetAutoArrange()
2422 HRESULT STDMETHODCALLTYPE
CDefView::SelectItem(int iItem
, DWORD dwFlags
)
2427 HRESULT STDMETHODCALLTYPE
CDefView::SelectAndPositionItems(UINT cidl
, LPCITEMIDLIST
*apidl
, POINT
*apt
, DWORD dwFlags
)
2432 /**********************************************************
2433 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2435 HRESULT WINAPI
CDefView::QueryStatus(const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD
*prgCmds
, OLECMDTEXT
*pCmdText
)
2437 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2438 this, pguidCmdGroup
, debugstr_guid(pguidCmdGroup
), cCmds
, prgCmds
, pCmdText
);
2443 for (UINT i
=0; i
< cCmds
; i
++)
2445 FIXME("\tprgCmds[%d].cmdID = %d\n", i
, prgCmds
[i
].cmdID
);
2446 prgCmds
[i
].cmdf
= 0;
2449 return OLECMDERR_E_UNKNOWNGROUP
;
2452 /**********************************************************
2453 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2455 * nCmdID is the OLECMDID_* enumeration
2457 HRESULT WINAPI
CDefView::Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
2459 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2460 this, debugstr_guid(pguidCmdGroup
), nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
2462 if (IsEqualIID(*pguidCmdGroup
, CGID_Explorer
) &&
2464 (nCmdexecopt
== 4) && pvaOut
)
2467 if (IsEqualIID(*pguidCmdGroup
, CGID_ShellDocView
) &&
2472 return OLECMDERR_E_UNKNOWNGROUP
;
2475 /**********************************************************
2476 * ISVDropTarget implementation
2479 /******************************************************************************
2480 * drag_notify_subitem [Internal]
2482 * Figure out the shellfolder object, which is currently under the mouse cursor
2483 * and notify it via the IDropTarget interface.
2486 #define SCROLLAREAWIDTH 20
2488 HRESULT
CDefView::drag_notify_subitem(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2490 LVHITTESTINFO htinfo
;
2496 /* Map from global to client coordinates and query the index of the listview-item, which is
2497 * currently under the mouse cursor. */
2500 htinfo
.flags
= LVHT_ONITEM
;
2501 ::ScreenToClient(hWndList
, &htinfo
.pt
);
2502 lResult
= SendMessageW(hWndList
, LVM_HITTEST
, 0, (LPARAM
)&htinfo
);
2504 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2505 ::GetClientRect(hWndList
, &clientRect
);
2506 if (htinfo
.pt
.x
== ptLastMousePos
.x
&& htinfo
.pt
.y
== ptLastMousePos
.y
&&
2507 (htinfo
.pt
.x
< SCROLLAREAWIDTH
|| htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
||
2508 htinfo
.pt
.y
< SCROLLAREAWIDTH
|| htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
))
2510 cScrollDelay
= (cScrollDelay
+ 1) % 5; /* DragOver is called every 50 ms */
2511 if (cScrollDelay
== 0)
2513 /* Mouse did hover another 250 ms over the scroll-area */
2514 if (htinfo
.pt
.x
< SCROLLAREAWIDTH
)
2515 SendMessageW(hWndList
, WM_HSCROLL
, SB_LINEUP
, 0);
2517 if (htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
)
2518 SendMessageW(hWndList
, WM_HSCROLL
, SB_LINEDOWN
, 0);
2520 if (htinfo
.pt
.y
< SCROLLAREAWIDTH
)
2521 SendMessageW(hWndList
, WM_VSCROLL
, SB_LINEUP
, 0);
2523 if (htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
)
2524 SendMessageW(hWndList
, WM_VSCROLL
, SB_LINEDOWN
, 0);
2529 cScrollDelay
= 0; /* Reset, if the cursor is not over the listview's scroll-area */
2532 ptLastMousePos
= htinfo
.pt
;
2534 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2535 if (pCurDropTarget
&& lResult
== iDragOverItem
)
2536 return pCurDropTarget
->DragOver(grfKeyState
, pt
, pdwEffect
);
2538 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2541 pCurDropTarget
->DragLeave();
2542 pCurDropTarget
.Release();
2545 iDragOverItem
= lResult
;
2548 /* We are not above one of the listview's subitems. Bind to the parent folder's
2549 * DropTarget interface. */
2550 hr
= pSFParent
->QueryInterface(IID_IDropTarget
,
2551 (LPVOID
*)&pCurDropTarget
);
2555 /* Query the relative PIDL of the shellfolder object represented by the currently
2556 * dragged over listview-item ... */
2557 lvItem
.mask
= LVIF_PARAM
;
2558 lvItem
.iItem
= lResult
;
2559 lvItem
.iSubItem
= 0;
2560 SendMessageW(hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
2562 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2563 hr
= pSFParent
->GetUIObjectOf(hWndList
, 1,
2564 (LPCITEMIDLIST
*)&lvItem
.lParam
, IID_IDropTarget
, NULL
, (LPVOID
*)&pCurDropTarget
);
2567 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2571 /* Notify the item just entered via DragEnter. */
2572 return pCurDropTarget
->DragEnter(pCurDataObject
, grfKeyState
, pt
, pdwEffect
);
2575 HRESULT WINAPI
CDefView::DragEnter(IDataObject
*pDataObject
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2577 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2578 pCurDataObject
= pDataObject
;
2579 pDataObject
->AddRef();
2581 return drag_notify_subitem(grfKeyState
, pt
, pdwEffect
);
2584 HRESULT WINAPI
CDefView::DragOver(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2586 return drag_notify_subitem(grfKeyState
, pt
, pdwEffect
);
2589 HRESULT WINAPI
CDefView::DragLeave()
2593 pCurDropTarget
->DragLeave();
2594 pCurDropTarget
.Release();
2597 if (pCurDataObject
!= NULL
)
2599 pCurDataObject
.Release();
2607 HRESULT WINAPI
CDefView::Drop(IDataObject
* pDataObject
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2611 pCurDropTarget
->Drop(pDataObject
, grfKeyState
, pt
, pdwEffect
);
2612 pCurDropTarget
.Release();
2615 pCurDataObject
.Release();
2621 /**********************************************************
2622 * ISVDropSource implementation
2625 HRESULT WINAPI
CDefView::QueryContinueDrag(BOOL fEscapePressed
, DWORD grfKeyState
)
2627 TRACE("(%p)\n",this);
2630 return DRAGDROP_S_CANCEL
;
2631 else if (!(grfKeyState
& MK_LBUTTON
) && !(grfKeyState
& MK_RBUTTON
))
2632 return DRAGDROP_S_DROP
;
2637 HRESULT WINAPI
CDefView::GiveFeedback(DWORD dwEffect
)
2639 TRACE("(%p)\n",this);
2641 return DRAGDROP_S_USEDEFAULTCURSORS
;
2644 /**********************************************************
2645 * ISVViewObject implementation
2648 HRESULT WINAPI
CDefView::Draw(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DVTARGETDEVICE
*ptd
, HDC hdcTargetDev
, HDC hdcDraw
, LPCRECTL lprcBounds
, LPCRECTL lprcWBounds
, BOOL (CALLBACK
*pfnContinue
)(ULONG_PTR dwContinue
), ULONG_PTR dwContinue
)
2650 FIXME("Stub: this=%p\n",this);
2655 HRESULT WINAPI
CDefView::GetColorSet(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DVTARGETDEVICE
*ptd
, HDC hicTargetDevice
, LOGPALETTE
**ppColorSet
)
2657 FIXME("Stub: this=%p\n",this);
2662 HRESULT WINAPI
CDefView::Freeze(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DWORD
*pdwFreeze
)
2664 FIXME("Stub: this=%p\n",this);
2669 HRESULT WINAPI
CDefView::Unfreeze(DWORD dwFreeze
)
2671 FIXME("Stub: this=%p\n",this);
2676 HRESULT WINAPI
CDefView::SetAdvise(DWORD aspects
, DWORD advf
, IAdviseSink
*pAdvSink
)
2678 FIXME("partial stub: %p %08x %08x %p\n", this, aspects
, advf
, pAdvSink
);
2680 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2681 pAdvSink
= pAdvSink
;
2682 dwAspects
= aspects
;
2688 HRESULT WINAPI
CDefView::GetAdvise(DWORD
*pAspects
, DWORD
*pAdvf
, IAdviseSink
**ppAdvSink
)
2690 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects
, pAdvf
, ppAdvSink
);
2694 *ppAdvSink
= pAdvSink
;
2695 pAdvSink
.p
->AddRef();
2699 *pAspects
= dwAspects
;
2707 HRESULT STDMETHODCALLTYPE
CDefView::QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
)
2709 if (IsEqualIID(guidService
, SID_IShellBrowser
))
2710 return pShellBrowser
->QueryInterface(riid
, ppvObject
);
2711 return E_NOINTERFACE
;
2714 /**********************************************************
2715 * IShellView_Constructor
2717 HRESULT WINAPI
IShellView_Constructor(IShellFolder
*pFolder
, IShellView
**newView
)
2719 CComObject
<CDefView
> *theView
;
2720 CComPtr
<IShellView
> result
;
2723 if (newView
== NULL
)
2727 ATLTRY (theView
= new CComObject
<CDefView
>);
2729 if (theView
== NULL
)
2730 return E_OUTOFMEMORY
;
2732 hResult
= theView
->QueryInterface (IID_IShellView
, (void **)&result
);
2733 if (FAILED (hResult
))
2739 hResult
= theView
->Initialize (pFolder
);
2740 if (FAILED (hResult
))
2742 *newView
= result
.Detach ();