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
);
352 /**********************************************************
354 * ##### helperfunctions for communication with ICommDlgBrowser #####
356 HRESULT
CDefView::IncludeObject(LPCITEMIDLIST pidl
)
360 if (pCommDlgBrowser
.p
!= NULL
)
362 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl
);
363 ret
= pCommDlgBrowser
->IncludeObject((IShellView
*)this, pidl
);
364 TRACE("--0x%08x\n", ret
);
369 HRESULT
CDefView::OnDefaultCommand()
371 HRESULT ret
= S_FALSE
;
373 if (pCommDlgBrowser
.p
!= NULL
)
375 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
376 ret
= pCommDlgBrowser
->OnDefaultCommand((IShellView
*)this);
377 TRACE("-- returns %08x\n", ret
);
382 HRESULT
CDefView::OnStateChange(UINT uFlags
)
384 HRESULT ret
= S_FALSE
;
386 if (pCommDlgBrowser
.p
!= NULL
)
388 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags
);
389 ret
= pCommDlgBrowser
->OnStateChange((IShellView
*)this, uFlags
);
394 /**********************************************************
395 * set the toolbar of the filedialog buttons
397 * - activates the buttons from the shellbrowser according to
400 void CDefView::CheckToolbar()
406 if (pCommDlgBrowser
!= NULL
)
408 pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_CHECKBUTTON
,
409 FCIDM_TB_SMALLICON
, (FolderSettings
.ViewMode
==FVM_LIST
)? TRUE
: FALSE
, &result
);
410 pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_CHECKBUTTON
,
411 FCIDM_TB_REPORTVIEW
, (FolderSettings
.ViewMode
==FVM_DETAILS
)? TRUE
: FALSE
, &result
);
412 pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_ENABLEBUTTON
,
413 FCIDM_TB_SMALLICON
, TRUE
, &result
);
414 pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_ENABLEBUTTON
,
415 FCIDM_TB_REPORTVIEW
, TRUE
, &result
);
419 /**********************************************************
421 * ##### helperfunctions for initializing the view #####
423 /**********************************************************
424 * change the style of the listview control
426 void CDefView::SetStyle(DWORD dwAdd
, DWORD dwRemove
)
430 TRACE("(%p)\n", this);
432 tmpstyle
= ::GetWindowLongPtrW(hWndList
, GWL_STYLE
);
433 ::SetWindowLongPtrW(hWndList
, GWL_STYLE
, dwAdd
| (tmpstyle
& ~dwRemove
));
436 /**********************************************************
437 * ShellView_CreateList()
439 * - creates the list view window
441 BOOL
CDefView::CreateList()
442 { DWORD dwStyle
, dwExStyle
;
446 dwStyle
= WS_TABSTOP
| WS_VISIBLE
| WS_CHILDWINDOW
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
447 LVS_SHAREIMAGELISTS
| LVS_EDITLABELS
| LVS_AUTOARRANGE
;
448 dwExStyle
= WS_EX_CLIENTEDGE
;
450 if (FolderSettings
.fFlags
& FWF_DESKTOP
)
451 dwStyle
|= LVS_ALIGNLEFT
;
453 dwStyle
|= LVS_ALIGNTOP
;
455 switch (FolderSettings
.ViewMode
)
457 case FVM_ICON
: dwStyle
|= LVS_ICON
; break;
458 case FVM_DETAILS
: dwStyle
|= LVS_REPORT
; break;
459 case FVM_SMALLICON
: dwStyle
|= LVS_SMALLICON
; break;
460 case FVM_LIST
: dwStyle
|= LVS_LIST
; break;
461 default: dwStyle
|= LVS_LIST
; break;
464 if (FolderSettings
.fFlags
& FWF_AUTOARRANGE
) dwStyle
|= LVS_AUTOARRANGE
;
465 if (FolderSettings
.fFlags
& FWF_DESKTOP
)
466 FolderSettings
.fFlags
|= FWF_NOCLIENTEDGE
| FWF_NOSCROLL
;
467 if (FolderSettings
.fFlags
& FWF_SINGLESEL
) dwStyle
|= LVS_SINGLESEL
;
468 if (FolderSettings
.fFlags
& FWF_NOCLIENTEDGE
)
469 dwExStyle
&= ~WS_EX_CLIENTEDGE
;
471 hWndList
=CreateWindowExW( dwExStyle
,
484 ListViewSortInfo
.bIsAscending
= TRUE
;
485 ListViewSortInfo
.nHeaderID
= -1;
486 ListViewSortInfo
.nLastHeaderID
= -1;
488 if (FolderSettings
.fFlags
& FWF_DESKTOP
) {
490 * FIXME: look at the registry value
491 * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
492 * and activate drop shadows if necessary
496 SendMessageW(hWndList
, LVM_SETTEXTBKCOLOR
, 0, CLR_NONE
);
497 SendMessageW(hWndList
, LVM_SETBKCOLOR
, 0, CLR_NONE
);
501 SendMessageW(hWndList
, LVM_SETTEXTBKCOLOR
, 0, GetSysColor(COLOR_DESKTOP
));
502 SendMessageW(hWndList
, LVM_SETBKCOLOR
, 0, GetSysColor(COLOR_DESKTOP
));
505 SendMessageW(hWndList
, LVM_SETTEXTCOLOR
, 0, RGB(255,255,255));
508 /* UpdateShellSettings(); */
512 /**********************************************************
513 * ShellView_InitList()
515 * - adds all needed columns to the shellview
517 BOOL
CDefView::InitList()
526 SendMessageW(hWndList
, LVM_DELETEALLITEMS
, 0, 0);
528 lvColumn
.mask
= LVCF_FMT
| LVCF_WIDTH
| LVCF_TEXT
;
529 lvColumn
.pszText
= szTemp
;
535 if (FAILED(pSF2Parent
->GetDetailsOf(NULL
, i
, &sd
)))
537 lvColumn
.fmt
= sd
.fmt
;
538 lvColumn
.cx
= sd
.cxChar
*8; /* chars->pixel */
539 StrRetToStrNW( szTemp
, 50, &sd
.str
, NULL
);
540 SendMessageW(hWndList
, LVM_INSERTCOLUMNW
, i
, (LPARAM
) &lvColumn
);
548 SendMessageW(hWndList
, LVM_SETIMAGELIST
, LVSIL_SMALL
, (LPARAM
)ShellSmallIconList
);
549 SendMessageW(hWndList
, LVM_SETIMAGELIST
, LVSIL_NORMAL
, (LPARAM
)ShellBigIconList
);
554 /**********************************************************
555 * ShellView_CompareItems()
558 * internal, CALLBACK for DSA_Sort
560 INT CALLBACK
CDefView::CompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
)
563 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1
, lParam2
, (LPVOID
) lpData
);
565 if(!lpData
) return 0;
567 ret
= (SHORT
)SCODE_CODE(((IShellFolder
*)lpData
)->CompareIDs(0, (LPITEMIDLIST
)lParam1
, (LPITEMIDLIST
)lParam2
));
568 TRACE("ret=%i\n",ret
);
572 /*************************************************************************
573 * ShellView_ListViewCompareItems
575 * Compare Function for the Listview (FileOpen Dialog)
578 * lParam1 [I] the first ItemIdList to compare with
579 * lParam2 [I] the second ItemIdList to compare with
580 * lpData [I] The column ID for the header Ctrl to process
583 * A negative value if the first item should precede the second,
584 * a positive value if the first item should follow the second,
585 * or zero if the two items are equivalent
588 * FIXME: function does what ShellView_CompareItems is supposed to do.
589 * unify it and figure out how to use the undocumented first parameter
590 * of IShellFolder_CompareIDs to do the job this function does and
591 * move this code to IShellFolder.
592 * make LISTVIEW_SORT_INFO obsolete
593 * the way this function works is only usable if we had only
594 * filesystemfolders (25/10/99 jsch)
596 INT CALLBACK
CDefView::ListViewCompareItems(LPVOID lParam1
, LPVOID lParam2
, LPARAM lpData
)
600 char strName1
[MAX_PATH
], strName2
[MAX_PATH
];
601 BOOL bIsFolder1
, bIsFolder2
,bIsBothFolder
;
602 LPITEMIDLIST pItemIdList1
= (LPITEMIDLIST
) lParam1
;
603 LPITEMIDLIST pItemIdList2
= (LPITEMIDLIST
) lParam2
;
604 LISTVIEW_SORT_INFO
*pSortInfo
= (LPLISTVIEW_SORT_INFO
) lpData
;
607 bIsFolder1
= _ILIsFolder(pItemIdList1
);
608 bIsFolder2
= _ILIsFolder(pItemIdList2
);
609 bIsBothFolder
= bIsFolder1
&& bIsFolder2
;
611 /* When sorting between a File and a Folder, the Folder gets sorted first */
612 if( (bIsFolder1
|| bIsFolder2
) && !bIsBothFolder
)
614 nDiff
= bIsFolder1
? -1 : 1;
618 /* Sort by Time: Folders or Files can be sorted */
620 if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_TIME
)
622 _ILGetFileDateTime(pItemIdList1
, &fd1
);
623 _ILGetFileDateTime(pItemIdList2
, &fd2
);
624 nDiff
= CompareFileTime(&fd2
, &fd1
);
626 /* Sort by Attribute: Folder or Files can be sorted */
627 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_ATTRIB
)
629 _ILGetFileAttributes(pItemIdList1
, strName1
, MAX_PATH
);
630 _ILGetFileAttributes(pItemIdList2
, strName2
, MAX_PATH
);
631 nDiff
= lstrcmpiA(strName1
, strName2
);
633 /* Sort by FileName: Folder or Files can be sorted */
634 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_NAME
|| bIsBothFolder
)
637 _ILSimpleGetText(pItemIdList1
, strName1
, MAX_PATH
);
638 _ILSimpleGetText(pItemIdList2
, strName2
, MAX_PATH
);
639 nDiff
= lstrcmpiA(strName1
, strName2
);
641 /* Sort by File Size, Only valid for Files */
642 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_SIZE
)
644 nDiff
= (INT
)(_ILGetFileSize(pItemIdList1
, NULL
, 0) - _ILGetFileSize(pItemIdList2
, NULL
, 0));
646 /* Sort by File Type, Only valid for Files */
647 else if(pSortInfo
->nHeaderID
== LISTVIEW_COLUMN_TYPE
)
650 _ILGetFileType(pItemIdList1
, strName1
, MAX_PATH
);
651 _ILGetFileType(pItemIdList2
, strName2
, MAX_PATH
);
652 nDiff
= lstrcmpiA(strName1
, strName2
);
655 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
659 _ILSimpleGetText(pItemIdList1
, strName1
, MAX_PATH
);
660 _ILSimpleGetText(pItemIdList2
, strName2
, MAX_PATH
);
661 nDiff
= lstrcmpiA(strName1
, strName2
);
664 if(!pSortInfo
->bIsAscending
)
673 /**********************************************************
674 * LV_FindItemByPidl()
676 int CDefView::LV_FindItemByPidl(LPCITEMIDLIST pidl
)
680 lvItem
.mask
= LVIF_PARAM
;
681 for(lvItem
.iItem
= 0;
682 SendMessageW(hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
685 LPITEMIDLIST currentpidl
= (LPITEMIDLIST
) lvItem
.lParam
;
686 HRESULT hr
= pSFParent
->CompareIDs(0, pidl
, currentpidl
);
687 if(SUCCEEDED(hr
) && !HRESULT_CODE(hr
))
695 /**********************************************************
698 BOOLEAN
CDefView::LV_AddItem(LPCITEMIDLIST pidl
)
702 TRACE("(%p)(pidl=%p)\n", this, pidl
);
704 lvItem
.mask
= LVIF_TEXT
| LVIF_IMAGE
| LVIF_PARAM
; /*set the mask*/
705 lvItem
.iItem
= ListView_GetItemCount(hWndList
); /*add the item to the end of the list*/
707 lvItem
.lParam
= (LPARAM
) ILClone(ILFindLastID(pidl
)); /*set the item's data*/
708 lvItem
.pszText
= LPSTR_TEXTCALLBACKW
; /*get text on a callback basis*/
709 lvItem
.iImage
= I_IMAGECALLBACK
; /*get the image on a callback basis*/
710 if (SendMessageW(hWndList
, LVM_INSERTITEMW
, 0, (LPARAM
)&lvItem
) == -1)
716 /**********************************************************
719 BOOLEAN
CDefView::LV_DeleteItem(LPCITEMIDLIST pidl
)
723 TRACE("(%p)(pidl=%p)\n", this, pidl
);
725 nIndex
= LV_FindItemByPidl(ILFindLastID(pidl
));
726 return (-1 == ListView_DeleteItem(hWndList
, nIndex
)) ? FALSE
: TRUE
;
729 /**********************************************************
732 BOOLEAN
CDefView::LV_RenameItem(LPCITEMIDLIST pidlOld
, LPCITEMIDLIST pidlNew
)
737 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", this, pidlOld
, pidlNew
);
739 nItem
= LV_FindItemByPidl(ILFindLastID(pidlOld
));
742 lvItem
.mask
= LVIF_PARAM
; /* only the pidl */
743 lvItem
.iItem
= nItem
;
744 SendMessageW(hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
746 SHFree((LPITEMIDLIST
)lvItem
.lParam
);
747 lvItem
.mask
= LVIF_PARAM
;
748 lvItem
.iItem
= nItem
;
749 lvItem
.lParam
= (LPARAM
) ILClone(ILFindLastID(pidlNew
)); /* set the item's data */
750 SendMessageW(hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
751 SendMessageW(hWndList
, LVM_UPDATE
, nItem
, 0);
752 return TRUE
; /* FIXME: better handling */
757 /**********************************************************
758 * ShellView_FillList()
760 * - gets the objectlist from the shellfolder
762 * - fills the list into the view
764 INT CALLBACK
CDefView::fill_list( LPVOID ptr
, LPVOID arg
)
766 LPITEMIDLIST pidl
= (LPITEMIDLIST
)ptr
;
767 CDefView
*pThis
= (CDefView
*)arg
;
768 /* in a commdlg This works as a filemask*/
769 if ( pThis
->IncludeObject(pidl
)==S_OK
) pThis
->LV_AddItem(pidl
);
774 HRESULT
CDefView::FillList()
776 LPENUMIDLIST pEnumIDList
;
784 DbgPrint("[shell32, CDefView::FillList] Called\n");
786 /* get the itemlist from the shfolder*/
787 hRes
= pSFParent
->EnumObjects(m_hWnd
, SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
, &pEnumIDList
);
795 /* create a pointer array */
796 hdpa
= DPA_Create(16);
799 return(E_OUTOFMEMORY
);
802 /* copy the items into the array*/
803 while((S_OK
== pEnumIDList
->Next(1, &pidl
, &dwFetched
)) && dwFetched
)
805 if (DPA_InsertPtr(hdpa
, 0x7fff, pidl
) == -1)
812 DPA_Sort(hdpa
, CompareItems
, (LPARAM
)pSFParent
.p
);
814 /*turn the listview's redrawing off*/
815 SendMessageA(hWndList
, WM_SETREDRAW
, FALSE
, 0);
817 DPA_DestroyCallback( hdpa
, fill_list
, (void *)this);
819 /*turn the listview's redrawing back on and force it to draw*/
820 SendMessageA(hWndList
, WM_SETREDRAW
, TRUE
, 0);
822 pEnumIDList
->Release(); /* destroy the list*/
827 LRESULT
CDefView::OnShowWindow(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
829 ::UpdateWindow(hWndList
);
834 LRESULT
CDefView::OnGetDlgCode(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
836 return SendMessageW(hWndList
, uMsg
, 0, 0);
839 LRESULT
CDefView::OnDestroy(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
841 RevokeDragDrop(m_hWnd
);
842 SHChangeNotifyDeregister(hNotify
);
847 LRESULT
CDefView::OnEraseBackground(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
849 if (FolderSettings
.fFlags
& (FWF_DESKTOP
| FWF_TRANSPARENT
))
850 return SendMessageW(GetParent(), WM_ERASEBKGND
, wParam
, lParam
); /* redirect to parent */
856 LRESULT
CDefView::OnSysColorChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
858 /* Forward WM_SYSCOLORCHANGE to common controls */
859 return SendMessageW(hWndList
, uMsg
, 0, 0);
862 LRESULT
CDefView::OnGetShellBrowser(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
864 return (LRESULT
)pShellBrowser
.p
;
867 /**********************************************************
868 * ShellView_OnCreate()
870 LRESULT
CDefView::OnCreate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
872 CComPtr
<IDropTarget
> pdt
;
873 SHChangeNotifyEntry ntreg
;
874 CComPtr
<IPersistFolder2
> ppf2
;
878 DbgPrint("[shell32, CDefView::OnCreate] Called\n");
888 if (SUCCEEDED(this->QueryInterface(IID_IDropTarget
, (LPVOID
*)&pdt
)))
889 RegisterDragDrop(m_hWnd
, pdt
);
891 /* register for receiving notifications */
892 pSFParent
->QueryInterface(IID_IPersistFolder2
, (LPVOID
*)&ppf2
);
895 ppf2
->GetCurFolder((LPITEMIDLIST
*)&ntreg
.pidl
);
896 ntreg
.fRecursive
= TRUE
;
897 hNotify
= SHChangeNotifyRegister(m_hWnd
, SHCNF_IDLIST
, SHCNE_ALLEVENTS
, SHV_CHANGE_NOTIFY
, 1, &ntreg
);
898 SHFree((LPITEMIDLIST
)ntreg
.pidl
);
901 hAccel
= LoadAcceleratorsA(shell32_hInstance
, "shv_accel");
906 /**********************************************************
907 * #### Handling of the menus ####
910 /**********************************************************
911 * ShellView_BuildFileMenu()
913 HMENU
CDefView::BuildFileMenu()
914 { WCHAR szText
[MAX_PATH
];
919 TRACE("(%p)\n",this);
921 hSubMenu
= CreatePopupMenu();
923 { /*get the number of items in our global array*/
924 for(nTools
= 0; Tools
[nTools
].idCommand
!= -1; nTools
++){}
926 /*add the menu items*/
927 for(i
= 0; i
< nTools
; i
++)
929 LoadStringW(shell32_hInstance
, Tools
[i
].idMenuString
, szText
, MAX_PATH
);
931 ZeroMemory(&mii
, sizeof(mii
));
932 mii
.cbSize
= sizeof(mii
);
933 mii
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
935 if(BTNS_SEP
!= Tools
[i
].bStyle
) /* no separator*/
937 mii
.fType
= MFT_STRING
;
938 mii
.fState
= MFS_ENABLED
;
939 mii
.dwTypeData
= szText
;
940 mii
.wID
= Tools
[i
].idCommand
;
944 mii
.fType
= MFT_SEPARATOR
;
946 /* tack This item onto the end of the menu */
947 InsertMenuItemW(hSubMenu
, (UINT
)-1, TRUE
, &mii
);
950 TRACE("-- return (menu=%p)\n",hSubMenu
);
954 /**********************************************************
955 * ShellView_MergeFileMenu()
957 void CDefView::MergeFileMenu(HMENU hSubMenu
)
958 { TRACE("(%p)->(submenu=%p) stub\n",this,hSubMenu
);
961 { /*insert This item at the beginning of the menu */
962 _InsertMenuItemW(hSubMenu
, 0, TRUE
, 0, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
963 _InsertMenuItemW(hSubMenu
, 0, TRUE
, IDM_MYFILEITEM
, MFT_STRING
, L
"dummy45", MFS_ENABLED
);
969 /**********************************************************
970 * ShellView_MergeViewMenu()
972 void CDefView::MergeViewMenu(HMENU hSubMenu
)
974 TRACE("(%p)->(submenu=%p)\n",this,hSubMenu
);
977 { /*add a separator at the correct position in the menu*/
979 static WCHAR view
[] = L
"View";
981 _InsertMenuItemW(hSubMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
, FALSE
, 0, MFT_SEPARATOR
, NULL
, MFS_ENABLED
);
983 ZeroMemory(&mii
, sizeof(mii
));
984 mii
.cbSize
= sizeof(mii
);
985 mii
.fMask
= MIIM_SUBMENU
| MIIM_TYPE
| MIIM_DATA
;
986 mii
.fType
= MFT_STRING
;
987 mii
.dwTypeData
= view
;
988 mii
.hSubMenu
= LoadMenuW(shell32_hInstance
, L
"MENU_001");
989 InsertMenuItemW(hSubMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
, FALSE
, &mii
);
993 /**********************************************************
994 * ShellView_GetSelections()
996 * - fills the this->apidl list with the selected objects
999 * number of selected items
1001 UINT
CDefView::GetSelections()
1008 cidl
= ListView_GetSelectedCount(hWndList
);
1009 apidl
= (LPITEMIDLIST
*)SHAlloc(cidl
* sizeof(LPITEMIDLIST
));
1011 TRACE("selected=%i\n", cidl
);
1015 TRACE("-- Items selected =%u\n", cidl
);
1017 lvItem
.mask
= LVIF_STATE
| LVIF_PARAM
;
1018 lvItem
.stateMask
= LVIS_SELECTED
;
1020 lvItem
.iSubItem
= 0;
1023 while(SendMessageW(hWndList
, LVM_GETITEMW
, 0, (LPARAM
)&lvItem
) && (i
< cidl
))
1025 if(lvItem
.state
& LVIS_SELECTED
)
1027 apidl
[i
] = (LPITEMIDLIST
)lvItem
.lParam
;
1031 TRACE("-- selected Item found\n");
1040 /**********************************************************
1041 * ShellView_OpenSelectedItems()
1043 HRESULT
CDefView::OpenSelectedItems()
1045 static UINT CF_IDLIST
= 0;
1047 CComPtr
<IDataObject
> selection
;
1048 CComPtr
<IContextMenu
> cm
;
1053 LPCITEMIDLIST parent_pidl
;
1054 WCHAR parent_path
[MAX_PATH
];
1055 LPCWSTR parent_dir
= NULL
;
1058 CMINVOKECOMMANDINFOEX ici
;
1061 if (0 == GetSelections())
1066 hr
= pSFParent
->GetUIObjectOf(m_hWnd
, cidl
,
1067 (LPCITEMIDLIST
*)apidl
, IID_IContextMenu
,
1072 hmenu
= CreatePopupMenu();
1075 hr
= IUnknown_SetSite(cm
, (IShellView
*)this);
1076 if (SUCCEEDED(cm
->QueryContextMenu(hmenu
, 0, 0x20, 0x7fff, CMF_DEFAULTONLY
)))
1078 INT def
= -1, n
= GetMenuItemCount(hmenu
);
1080 for ( i
= 0; i
< n
; i
++ )
1082 memset( &info
, 0, sizeof info
);
1083 info
.cbSize
= sizeof info
;
1084 info
.fMask
= MIIM_FTYPE
| MIIM_STATE
| MIIM_ID
;
1085 if (GetMenuItemInfoW( hmenu
, i
, TRUE
, &info
))
1087 if (info
.fState
& MFS_DEFAULT
)
1096 memset( &ici
, 0, sizeof ici
);
1097 ici
.cbSize
= sizeof ici
;
1098 ici
.lpVerb
= MAKEINTRESOURCEA( def
);
1101 if (cm
->InvokeCommand((LPCMINVOKECOMMANDINFO
) &ici
) == S_OK
)
1103 DestroyMenu( hmenu
);
1104 hr
= IUnknown_SetSite(cm
, NULL
);
1110 DestroyMenu( hmenu
);
1111 hr
= IUnknown_SetSite(cm
, NULL
);
1118 hr
= pSFParent
->GetUIObjectOf(m_hWnd
, cidl
,
1119 (LPCITEMIDLIST
*)apidl
, IID_IDataObject
,
1120 0, (LPVOID
*)&selection
);
1129 CF_IDLIST
= RegisterClipboardFormatW(CFSTR_SHELLIDLIST
);
1131 fetc
.cfFormat
= CF_IDLIST
;
1133 fetc
.dwAspect
= DVASPECT_CONTENT
;
1135 fetc
.tymed
= TYMED_HGLOBAL
;
1137 hr
= selection
->QueryGetData(&fetc
);
1141 hr
= selection
->GetData(&fetc
, &stgm
);
1145 pIDList
= (LPIDA
)GlobalLock(stgm
.hGlobal
);
1147 parent_pidl
= (LPCITEMIDLIST
) ((LPBYTE
)pIDList
+pIDList
->aoffset
[0]);
1148 hr
= pSFParent
->GetAttributesOf(1, &parent_pidl
, &attribs
);
1149 if (SUCCEEDED(hr
) && (attribs
& SFGAO_FILESYSTEM
) &&
1150 SHGetPathFromIDListW(parent_pidl
, parent_path
))
1152 parent_dir
= parent_path
;
1155 for (i
= pIDList
->cidl
; i
> 0; --i
)
1159 pidl
= (LPCITEMIDLIST
)((LPBYTE
)pIDList
+pIDList
->aoffset
[i
]);
1161 attribs
= SFGAO_FOLDER
;
1162 hr
= pSFParent
->GetAttributesOf(1, &pidl
, &attribs
);
1164 if (SUCCEEDED(hr
) && ! (attribs
& SFGAO_FOLDER
))
1166 SHELLEXECUTEINFOW shexinfo
;
1168 shexinfo
.cbSize
= sizeof(SHELLEXECUTEINFOW
);
1169 shexinfo
.fMask
= SEE_MASK_INVOKEIDLIST
; /* SEE_MASK_IDLIST is also possible. */
1170 shexinfo
.hwnd
= NULL
;
1171 shexinfo
.lpVerb
= NULL
;
1172 shexinfo
.lpFile
= NULL
;
1173 shexinfo
.lpParameters
= NULL
;
1174 shexinfo
.lpDirectory
= parent_dir
;
1175 shexinfo
.nShow
= SW_NORMAL
;
1176 shexinfo
.lpIDList
= ILCombine(parent_pidl
, pidl
);
1178 ShellExecuteExW(&shexinfo
); /* Discard error/success info */
1180 ILFree((LPITEMIDLIST
)shexinfo
.lpIDList
);
1184 GlobalUnlock(stgm
.hGlobal
);
1185 ReleaseStgMedium(&stgm
);
1190 /**********************************************************
1191 * ShellView_DoContextMenu()
1193 LRESULT
CDefView::OnContextMenu(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1203 CMINVOKECOMMANDINFO cmi
;
1206 // for some reason I haven't figured out, we sometimes recurse into this method
1214 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",this, x
, y
, bDefault
);
1219 /* look, what's selected and create a context menu object of it*/
1220 if (GetSelections())
1222 pSFParent
->GetUIObjectOf(hWndParent
, cidl
, (LPCITEMIDLIST
*)apidl
, IID_IContextMenu
, NULL
, (LPVOID
*)&pCM
);
1226 TRACE("-- pContextMenu\n");
1227 hMenu
= CreatePopupMenu();
1231 hResult
= IUnknown_SetSite(pCM
, (IShellView
*)this);
1232 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
1233 if(SUCCEEDED(pShellBrowser
->GetControlWindow(FCW_TREE
, &hwndTree
)) && hwndTree
)
1235 TRACE("-- explore mode\n");
1239 /* build the flags depending on what we can do with the selected item */
1240 wFlags
= CMF_NORMAL
| (cidl
!= 1 ? 0 : CMF_CANRENAME
) | (fExplore
? CMF_EXPLORE
: 0);
1242 /* let the ContextMenu merge its items in */
1243 if (SUCCEEDED(pCM
->QueryContextMenu(hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, wFlags
)))
1245 if (FolderSettings
.fFlags
& FWF_DESKTOP
)
1246 SetMenuDefaultItem(hMenu
, FCIDM_SHVIEW_OPEN
, MF_BYCOMMAND
);
1250 TRACE("-- get menu default command\n");
1251 uCommand
= GetMenuDefaultItem(hMenu
, FALSE
, GMDI_GOINTOPOPUPS
);
1255 TRACE("-- track popup\n");
1256 uCommand
= TrackPopupMenu( hMenu
,TPM_LEFTALIGN
| TPM_RETURNCMD
,x
,y
,0,m_hWnd
,NULL
);
1261 TRACE("-- uCommand=%u\n", uCommand
);
1262 if (uCommand
==FCIDM_SHVIEW_OPEN
&& pCommDlgBrowser
.p
!= NULL
)
1264 TRACE("-- dlg: OnDefaultCommand\n");
1265 if (OnDefaultCommand() != S_OK
)
1267 OpenSelectedItems();
1272 TRACE("-- explore -- invoke command\n");
1273 ZeroMemory(&cmi
, sizeof(cmi
));
1274 cmi
.cbSize
= sizeof(cmi
);
1275 cmi
.hwnd
= hWndParent
; /* this window has to answer CWM_GETISHELLBROWSER */
1276 cmi
.lpVerb
= (LPCSTR
)MAKEINTRESOURCEA(uCommand
);
1277 pCM
->InvokeCommand(&cmi
);
1280 hResult
= IUnknown_SetSite(pCM
, NULL
);
1287 else /* background context menu */
1289 hMenu
= CreatePopupMenu();
1291 CDefFolderMenu_Create2(NULL
, NULL
, cidl
, (LPCITEMIDLIST
*)apidl
, pSFParent
, NULL
, 0, NULL
, (IContextMenu
**)&pCM
);
1292 pCM
->QueryContextMenu(hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, 0);
1294 uCommand
= TrackPopupMenu( hMenu
, TPM_LEFTALIGN
| TPM_RETURNCMD
,x
,y
,0,m_hWnd
,NULL
);
1297 TRACE("-- (%p)->(uCommand=0x%08x )\n",this, uCommand
);
1299 ZeroMemory(&cmi
, sizeof(cmi
));
1300 cmi
.cbSize
= sizeof(cmi
);
1301 cmi
.lpVerb
= (LPCSTR
)MAKEINTRESOURCEA(uCommand
);
1302 cmi
.hwnd
= hWndParent
;
1303 pCM
->InvokeCommand(&cmi
);
1310 /**********************************************************
1311 * ##### message handling #####
1314 /**********************************************************
1315 * ShellView_OnSize()
1317 LRESULT
CDefView::OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1322 wWidth
= LOWORD(lParam
);
1323 wHeight
= HIWORD(lParam
);
1325 TRACE("%p width=%u height=%u\n", this, wWidth
, wHeight
);
1327 /*resize the ListView to fit our window*/
1330 ::MoveWindow(hWndList
, 0, 0, wWidth
, wHeight
, TRUE
);
1336 /**********************************************************
1337 * ShellView_OnDeactivate()
1342 void CDefView::OnDeactivate()
1346 if(uState
!= SVUIA_DEACTIVATE
)
1350 pShellBrowser
->SetMenuSB(0, 0, 0);
1351 pShellBrowser
->RemoveMenusSB(hMenu
);
1356 uState
= SVUIA_DEACTIVATE
;
1360 void CDefView::DoActivate(UINT uState
)
1362 OLEMENUGROUPWIDTHS omw
= { {0, 0, 0, 0, 0, 0} };
1364 CHAR szText
[MAX_PATH
];
1366 TRACE("%p uState=%x\n", this, uState
);
1368 /*don't do anything if the state isn't really changing */
1369 if(uState
== uState
)
1376 /*only do This if we are active */
1377 if(uState
!= SVUIA_DEACTIVATE
)
1379 /*merge the menus */
1380 hMenu
= CreateMenu();
1384 pShellBrowser
->InsertMenusSB(hMenu
, &omw
);
1385 TRACE("-- after fnInsertMenusSB\n");
1387 /*build the top level menu get the menu item's text*/
1388 strcpy(szText
,"dummy 31");
1390 ZeroMemory(&mii
, sizeof(mii
));
1391 mii
.cbSize
= sizeof(mii
);
1392 mii
.fMask
= MIIM_SUBMENU
| MIIM_TYPE
| MIIM_STATE
;
1393 mii
.fType
= MFT_STRING
;
1394 mii
.fState
= MFS_ENABLED
;
1395 mii
.dwTypeData
= szText
;
1396 mii
.hSubMenu
= BuildFileMenu();
1398 /*insert our menu into the menu bar*/
1401 InsertMenuItemA(hMenu
, FCIDM_MENU_HELP
, FALSE
, &mii
);
1404 /*get the view menu so we can merge with it*/
1405 ZeroMemory(&mii
, sizeof(mii
));
1406 mii
.cbSize
= sizeof(mii
);
1407 mii
.fMask
= MIIM_SUBMENU
;
1409 if(GetMenuItemInfoA(hMenu
, FCIDM_MENU_VIEW
, FALSE
, &mii
))
1411 MergeViewMenu(mii
.hSubMenu
);
1414 /*add the items that should only be added if we have the focus*/
1415 if(SVUIA_ACTIVATE_FOCUS
== uState
)
1417 /*get the file menu so we can merge with it */
1418 ZeroMemory(&mii
, sizeof(mii
));
1419 mii
.cbSize
= sizeof(mii
);
1420 mii
.fMask
= MIIM_SUBMENU
;
1422 if(GetMenuItemInfoA(hMenu
, FCIDM_MENU_FILE
, FALSE
, &mii
))
1424 MergeFileMenu(mii
.hSubMenu
);
1427 TRACE("-- before fnSetMenuSB\n");
1428 pShellBrowser
->SetMenuSB(hMenu
, 0, m_hWnd
);
1435 /**********************************************************
1436 * ShellView_OnActivate()
1438 LRESULT
CDefView::OnActivate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1440 DoActivate(SVUIA_ACTIVATE_FOCUS
);
1444 /**********************************************************
1445 * ShellView_OnSetFocus()
1448 LRESULT
CDefView::OnSetFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1450 TRACE("%p\n", this);
1452 /* Tell the browser one of our windows has received the focus. This
1453 should always be done before merging menus (OnActivate merges the
1454 menus) if one of our windows has the focus.*/
1456 pShellBrowser
->OnViewWindowActive((IShellView
*)this);
1457 DoActivate(SVUIA_ACTIVATE_FOCUS
);
1459 /* Set the focus to the listview */
1460 ::SetFocus(hWndList
);
1462 /* Notify the ICommDlgBrowser interface */
1463 OnStateChange(CDBOSC_SETFOCUS
);
1468 /**********************************************************
1469 * ShellView_OnKillFocus()
1471 LRESULT
CDefView::OnKillFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1473 TRACE("(%p) stub\n", this);
1475 DoActivate(SVUIA_ACTIVATE_NOFOCUS
);
1476 /* Notify the ICommDlgBrowser */
1477 OnStateChange(CDBOSC_KILLFOCUS
);
1482 /**********************************************************
1483 * ShellView_OnCommand()
1486 * the CmdID's are the ones from the context menu
1488 LRESULT
CDefView::OnCommand(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1494 dwCmdID
= GET_WM_COMMAND_ID(wParam
, lParam
);
1495 dwCmd
= GET_WM_COMMAND_CMD(wParam
, lParam
);
1496 hwndCmd
= GET_WM_COMMAND_HWND(wParam
, lParam
);
1498 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",this, dwCmdID
, dwCmd
, hwndCmd
);
1502 case FCIDM_SHVIEW_SMALLICON
:
1503 FolderSettings
.ViewMode
= FVM_SMALLICON
;
1504 SetStyle (LVS_SMALLICON
, LVS_TYPEMASK
);
1508 case FCIDM_SHVIEW_BIGICON
:
1509 FolderSettings
.ViewMode
= FVM_ICON
;
1510 SetStyle (LVS_ICON
, LVS_TYPEMASK
);
1514 case FCIDM_SHVIEW_LISTVIEW
:
1515 FolderSettings
.ViewMode
= FVM_LIST
;
1516 SetStyle (LVS_LIST
, LVS_TYPEMASK
);
1520 case FCIDM_SHVIEW_REPORTVIEW
:
1521 FolderSettings
.ViewMode
= FVM_DETAILS
;
1522 SetStyle (LVS_REPORT
, LVS_TYPEMASK
);
1526 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1531 ListViewSortInfo
.nHeaderID
= (LPARAM
) (dwCmdID
- 0x30);
1532 ListViewSortInfo
.bIsAscending
= TRUE
;
1533 ListViewSortInfo
.nLastHeaderID
= ListViewSortInfo
.nHeaderID
;
1534 SendMessageA(hWndList
, LVM_SORTITEMS
, (WPARAM
) &ListViewSortInfo
, (LPARAM
)ListViewCompareItems
);
1538 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID
);
1543 /**********************************************************
1544 * ShellView_OnNotify()
1547 LRESULT
CDefView::OnNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1551 LPNMLISTVIEW lpnmlv
;
1552 NMLVDISPINFOW
*lpdi
;
1557 lpnmh
= (LPNMHDR
)lParam
;
1558 lpnmlv
= (LPNMLISTVIEW
)lpnmh
;
1559 lpdi
= (NMLVDISPINFOW
*)lpnmh
;
1561 TRACE("%p CtlID=%u lpnmh->code=%x\n",this,CtlID
,lpnmh
->code
);
1566 TRACE("-- NM_SETFOCUS %p\n", this);
1567 OnSetFocus(0, 0, 0, unused
);
1571 TRACE("-- NM_KILLFOCUS %p\n", this);
1573 /* Notify the ICommDlgBrowser interface */
1574 OnStateChange(CDBOSC_KILLFOCUS
);
1578 TRACE("-- NM_CUSTOMDRAW %p\n", this);
1579 return CDRF_DODEFAULT
;
1581 case NM_RELEASEDCAPTURE
:
1582 TRACE("-- NM_RELEASEDCAPTURE %p\n", this);
1586 TRACE("-- NM_CLICK %p\n", this);
1590 TRACE("-- NM_RCLICK %p\n", this);
1594 TRACE("-- NM_DBLCLK %p\n", this);
1595 if (OnDefaultCommand() != S_OK
) OpenSelectedItems();
1599 TRACE("-- NM_RETURN %p\n", this);
1600 if (OnDefaultCommand() != S_OK
) OpenSelectedItems();
1604 TRACE("-- HDN_ENDTRACKW %p\n", this);
1605 /*nColumn1 = ListView_GetColumnWidth(hWndList, 0);
1606 nColumn2 = ListView_GetColumnWidth(hWndList, 1);*/
1609 case LVN_DELETEITEM
:
1610 TRACE("-- LVN_DELETEITEM %p\n", this);
1611 SHFree((LPITEMIDLIST
)lpnmlv
->lParam
); /*delete the pidl because we made a copy of it*/
1614 case LVN_DELETEALLITEMS
:
1615 TRACE("-- LVN_DELETEALLITEMS %p\n", this);
1618 case LVN_INSERTITEM
:
1619 TRACE("-- LVN_INSERTITEM (STUB)%p\n", this);
1622 case LVN_ITEMACTIVATE
:
1623 TRACE("-- LVN_ITEMACTIVATE %p\n", this);
1624 OnStateChange(CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1627 case LVN_COLUMNCLICK
:
1628 ListViewSortInfo
.nHeaderID
= lpnmlv
->iSubItem
;
1629 if(ListViewSortInfo
.nLastHeaderID
== ListViewSortInfo
.nHeaderID
)
1631 ListViewSortInfo
.bIsAscending
= !ListViewSortInfo
.bIsAscending
;
1635 ListViewSortInfo
.bIsAscending
= TRUE
;
1637 ListViewSortInfo
.nLastHeaderID
= ListViewSortInfo
.nHeaderID
;
1639 SendMessageW(lpnmlv
->hdr
.hwndFrom
, LVM_SORTITEMS
, (WPARAM
) &ListViewSortInfo
, (LPARAM
)ListViewCompareItems
);
1642 case LVN_GETDISPINFOA
:
1643 case LVN_GETDISPINFOW
:
1644 TRACE("-- LVN_GETDISPINFO %p\n", this);
1645 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1647 if(lpdi
->item
.mask
& LVIF_TEXT
) /* text requested */
1652 pSF2Parent
->GetDetailsOf(pidl
, lpdi
->item
.iSubItem
, &sd
);
1653 if (lpnmh
->code
== LVN_GETDISPINFOA
)
1655 /* shouldn't happen */
1656 NMLVDISPINFOA
*lpdiA
= (NMLVDISPINFOA
*)lpnmh
;
1657 StrRetToStrNA( lpdiA
->item
.pszText
, lpdiA
->item
.cchTextMax
, &sd
.str
, NULL
);
1658 TRACE("-- text=%s\n",lpdiA
->item
.pszText
);
1660 else /* LVN_GETDISPINFOW */
1662 StrRetToStrNW( lpdi
->item
.pszText
, lpdi
->item
.cchTextMax
, &sd
.str
, NULL
);
1663 TRACE("-- text=%s\n",debugstr_w(lpdi
->item
.pszText
));
1671 if(lpdi
->item
.mask
& LVIF_IMAGE
) /* image requested */
1673 lpdi
->item
.iImage
= SHMapPIDLToSystemImageListIndex(pSFParent
, pidl
, 0);
1675 lpdi
->item
.mask
|= LVIF_DI_SETITEM
;
1678 case LVN_ITEMCHANGED
:
1679 TRACE("-- LVN_ITEMCHANGED %p\n", this);
1680 OnStateChange(CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1684 case LVN_BEGINRDRAG
:
1685 TRACE("-- LVN_BEGINDRAG\n");
1687 if (GetSelections())
1690 DWORD dwAttributes
= SFGAO_CANLINK
;
1691 DWORD dwEffect
= DROPEFFECT_COPY
| DROPEFFECT_MOVE
;
1693 if (SUCCEEDED(pSFParent
->GetUIObjectOf(m_hWnd
, cidl
, (LPCITEMIDLIST
*)apidl
, IID_IDataObject
,0,(LPVOID
*)&pda
)))
1695 IDropSource
* pds
= (IDropSource
*)this; /* own DropSource interface */
1697 if (SUCCEEDED(pSFParent
->GetAttributesOf(cidl
, (LPCITEMIDLIST
*)apidl
, &dwAttributes
)))
1699 if (dwAttributes
& SFGAO_CANLINK
)
1701 dwEffect
|= DROPEFFECT_LINK
;
1708 DoDragDrop(pda
, pds
, dwEffect
, &dwEffect2
);
1715 case LVN_BEGINLABELEDITW
:
1717 DWORD dwAttr
= SFGAO_CANRENAME
;
1718 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1720 TRACE("-- LVN_BEGINLABELEDITW %p\n", this);
1722 pSFParent
->GetAttributesOf(1, (LPCITEMIDLIST
*)&pidl
, &dwAttr
);
1723 if (SFGAO_CANRENAME
& dwAttr
)
1730 case LVN_ENDLABELEDITW
:
1732 TRACE("-- LVN_ENDLABELEDITW %p\n", this);
1733 if (lpdi
->item
.pszText
)
1738 lvItem
.iItem
= lpdi
->item
.iItem
;
1739 lvItem
.iSubItem
= 0;
1740 lvItem
.mask
= LVIF_PARAM
;
1741 SendMessageW(hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
1743 pidl
= (LPITEMIDLIST
)lpdi
->item
.lParam
;
1744 hr
= pSFParent
->SetNameOf(0, pidl
, lpdi
->item
.pszText
, SHGDN_INFOLDER
, &pidl
);
1746 if(SUCCEEDED(hr
) && pidl
)
1748 lvItem
.mask
= LVIF_PARAM
;
1749 lvItem
.lParam
= (LPARAM
)pidl
;
1750 SendMessageW(hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
1761 msg.message = WM_KEYDOWN;
1762 msg.wParam = plvKeyDown->wVKey;
1767 LPNMLVKEYDOWN plvKeyDown
= (LPNMLVKEYDOWN
) lpnmh
;
1768 SHORT ctrl
= GetKeyState(VK_CONTROL
) & 0x8000;
1770 /* initiate a rename of the selected file or directory */
1771 if(plvKeyDown
->wVKey
== VK_F2
)
1773 /* see how many files are selected */
1774 int i
= ListView_GetSelectedCount(hWndList
);
1776 /* get selected item */
1779 /* get selected item */
1780 i
= ListView_GetNextItem(hWndList
, -1,
1783 SendMessageW(hWndList
, LVM_ENSUREVISIBLE
, i
, 0);
1784 SendMessageW(hWndList
, LVM_EDITLABELW
, i
, 0);
1788 TranslateAccelerator(m_hWnd
, hAccel
, &msg
)
1790 else if(plvKeyDown
->wVKey
== VK_DELETE
)
1795 LPITEMIDLIST
* pItems
;
1798 pSFParent
->QueryInterface(IID_ISFHelper
,
1804 if(!(i
= ListView_GetSelectedCount(hWndList
)))
1807 /* allocate memory for the pidl array */
1808 pItems
= (LPITEMIDLIST
*)HeapAlloc(GetProcessHeap(), 0,
1809 sizeof(LPITEMIDLIST
) * i
);
1811 /* retrieve all selected items */
1814 while(ListView_GetSelectedCount(hWndList
) > i
)
1816 /* get selected item */
1817 item_index
= ListView_GetNextItem(hWndList
,
1818 item_index
, LVNI_SELECTED
);
1819 item
.iItem
= item_index
;
1820 item
.mask
= LVIF_PARAM
;
1821 SendMessageA(hWndList
, LVM_GETITEMA
, 0, (LPARAM
) &item
);
1824 pItems
[i
] = (LPITEMIDLIST
)item
.lParam
;
1829 /* perform the item deletion */
1830 psfhlp
->DeleteItems(i
, (LPCITEMIDLIST
*)pItems
);
1832 /* free pidl array memory */
1833 HeapFree(GetProcessHeap(), 0, pItems
);
1836 /* Initiate a refresh */
1837 else if(plvKeyDown
->wVKey
== VK_F5
)
1841 else if(plvKeyDown
->wVKey
== VK_BACK
)
1843 LPSHELLBROWSER lpSb
;
1844 if((lpSb
= (LPSHELLBROWSER
)SendMessageW(hWndParent
, CWM_GETISHELLBROWSER
, 0, 0)))
1846 lpSb
->BrowseObject(NULL
, SBSP_PARENT
);
1849 else if(plvKeyDown
->wVKey
== 'C' && ctrl
)
1851 if (GetSelections())
1853 CComPtr
<IDataObject
> pda
;
1855 if (SUCCEEDED(pSFParent
->GetUIObjectOf(m_hWnd
, cidl
, (LPCITEMIDLIST
*)apidl
, IID_IDataObject
, 0, (LPVOID
*)&pda
)))
1857 HRESULT hr
= OleSetClipboard(pda
);
1860 WARN("OleSetClipboard failed");
1866 else if(plvKeyDown
->wVKey
== 'V' && ctrl
)
1868 CComPtr
<IDataObject
> pda
;
1870 FORMATETC formatetc
;
1871 LPITEMIDLIST
* apidl
;
1873 CComPtr
<IShellFolder
> psfFrom
;
1874 CComPtr
<IShellFolder
> psfDesktop
;
1875 CComPtr
<IShellFolder
> psfTarget
;
1877 CComPtr
<ISFHelper
> psfhlpdst
;
1878 CComPtr
<ISFHelper
> psfhlpsrc
;
1881 hr
= OleGetClipboard(&pda
);
1884 ERR("Failed to get clipboard with %lx\n", hr
);
1888 InitFormatEtc(formatetc
, RegisterClipboardFormatW(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
1889 hr
= pda
->GetData(&formatetc
, &medium
);
1893 ERR("Failed to get clipboard data with %lx\n", hr
);
1897 /* lock the handle */
1898 lpcida
= (LPIDA
)GlobalLock(medium
.hGlobal
);
1901 ERR("failed to lock pidl\n");
1902 ReleaseStgMedium(&medium
);
1906 /* convert the data into pidl */
1907 apidl
= _ILCopyCidaToaPidl(&pidl
, lpcida
);
1911 ERR("failed to copy pidl\n");
1915 if (FAILED(SHGetDesktopFolder(&psfDesktop
)))
1917 ERR("failed to get desktop folder\n");
1919 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1920 ReleaseStgMedium(&medium
);
1924 if (_ILIsDesktop(pidl
))
1926 /* use desktop shellfolder */
1927 psfFrom
= psfDesktop
;
1929 else if (FAILED(psfDesktop
->BindToObject(pidl
, NULL
, IID_IShellFolder
, (LPVOID
*)&psfFrom
)))
1931 ERR("no IShellFolder\n");
1934 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1935 ReleaseStgMedium(&medium
);
1940 psfTarget
= pSFParent
;
1943 /* get source and destination shellfolder */
1944 if (FAILED(psfTarget
->QueryInterface(IID_ISFHelper
, (LPVOID
*)&psfhlpdst
)))
1946 ERR("no IID_ISFHelper for destination\n");
1949 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1950 ReleaseStgMedium(&medium
);
1955 if (FAILED(psfFrom
->QueryInterface(IID_ISFHelper
, (LPVOID
*)&psfhlpsrc
)))
1957 ERR("no IID_ISFHelper for source\n");
1960 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1961 ReleaseStgMedium(&medium
);
1966 * do we want to perform a copy or move ???
1968 hr
= psfhlpdst
->CopyItems(psfFrom
, lpcida
->cidl
, (LPCITEMIDLIST
*)apidl
);
1971 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1972 ReleaseStgMedium(&medium
);
1974 TRACE("paste end hr %x\n", hr
);
1978 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown
->wVKey
);
1983 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh
->code
);
1989 /**********************************************************
1990 * ShellView_OnChange()
1992 LRESULT
CDefView::OnChangeNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1994 LPITEMIDLIST
*Pidls
;
1996 Pidls
= (LPITEMIDLIST
*)wParam
;
1998 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls
[0], Pidls
[1], lParam
);
2004 LV_AddItem(Pidls
[0]);
2008 LV_DeleteItem(Pidls
[0]);
2010 case SHCNE_RENAMEFOLDER
:
2011 case SHCNE_RENAMEITEM
:
2012 LV_RenameItem(Pidls
[0], Pidls
[1]);
2014 case SHCNE_UPDATEITEM
:
2020 /**********************************************************
2021 * ShellView_DoMeasureItem
2023 LRESULT
CDefView::OnCustomItem(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2028 ERR("no menu!!!\n");
2032 if (pCM
.p
->HandleMenuMsg(uMsg
, (WPARAM
)m_hWnd
, lParam
) == S_OK
)
2038 /**********************************************************
2041 * The INTERFACE of the IShellView object
2044 **********************************************************
2047 /**********************************************************
2048 * ShellView_GetWindow
2050 HRESULT WINAPI
CDefView::GetWindow(HWND
*phWnd
)
2052 TRACE("(%p)\n",this);
2059 HRESULT WINAPI
CDefView::ContextSensitiveHelp(BOOL fEnterMode
)
2061 FIXME("(%p) stub\n",this);
2066 /**********************************************************
2067 * IShellView_TranslateAccelerator
2070 * use the accel functions
2072 HRESULT WINAPI
CDefView::TranslateAccelerator(LPMSG lpmsg
)
2075 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",this,lpmsg
, lpmsg
->hwnd
, lpmsg
->message
, lpmsg
->lParam
, lpmsg
->wParam
);
2078 if (lpmsg
->message
>= WM_KEYFIRST
&& lpmsg
->message
>= WM_KEYLAST
)
2080 TRACE("-- key=0x04%lx\n",lpmsg
->wParam
) ;
2082 return S_FALSE
; /* not handled */
2085 HRESULT WINAPI
CDefView::EnableModeless(BOOL fEnable
)
2087 FIXME("(%p) stub\n",this);
2092 HRESULT WINAPI
CDefView::UIActivate(UINT uState
)
2095 CHAR szName[MAX_PATH];
2098 int nPartArray
[1] = {-1};
2100 TRACE("(%p)->(state=%x) stub\n",this, uState
);
2102 /*don't do anything if the state isn't really changing*/
2103 if(uState
== uState
)
2108 /*OnActivate handles the menu merging and internal state*/
2111 /*only do This if we are active*/
2112 if(uState
!= SVUIA_DEACTIVATE
)
2116 GetFolderPath is not a method of IShellFolder
2117 IShellFolder_GetFolderPath( pSFParent, szName, sizeof(szName) );
2119 /* set the number of parts */
2120 pShellBrowser
->SendControlMsg(FCW_STATUS
, SB_SETPARTS
, 1, (LPARAM
)nPartArray
, &lResult
);
2122 /* set the text for the parts */
2124 pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult);
2131 HRESULT WINAPI
CDefView::Refresh()
2133 TRACE("(%p)\n",this);
2135 SendMessageW(hWndList
, LVM_DELETEALLITEMS
, 0, 0);
2141 HRESULT WINAPI
CDefView::CreateViewWindow(IShellView
*lpPrevView
, LPCFOLDERSETTINGS lpfs
, IShellBrowser
*psb
, RECT
*prcView
, HWND
*phWnd
)
2145 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",this, lpPrevView
,lpfs
, psb
, prcView
, phWnd
);
2147 DbgPrint("[shell32, CDefView::CreateViewWindow] Called lpfs = 0x%x, psb = 0x%x\n", lpfs
, psb
);
2150 TRACE("-- vmode=%x flags=%x\n", lpfs
->ViewMode
, lpfs
->fFlags
);
2151 if (prcView
!= NULL
)
2152 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView
->left
, prcView
->top
, prcView
->right
, prcView
->bottom
);
2154 /* Validate the Shell Browser */
2156 return E_UNEXPECTED
;
2158 /*set up the member variables*/
2159 pShellBrowser
= psb
;
2160 FolderSettings
= *lpfs
;
2162 /*get our parent window*/
2163 pShellBrowser
->GetWindow(&hWndParent
);
2165 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
2166 pCommDlgBrowser
= NULL
;
2167 if (SUCCEEDED(pShellBrowser
->QueryInterface(IID_ICommDlgBrowser
, (LPVOID
*)&pCommDlgBrowser
)))
2169 TRACE("-- CommDlgBrowser\n");
2172 DbgPrint("[shell32, CDefView::CreateViewWindow] About to call the create function\n");
2174 Create(hWndParent
, prcView
, NULL
, WS_CHILD
| WS_TABSTOP
, 0, 0U);
2185 SetWindowPos(HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_SHOWWINDOW
);
2191 HRESULT WINAPI
CDefView::DestroyViewWindow()
2193 TRACE("(%p)\n",this);
2195 /*Make absolutely sure all our UI is cleaned up.*/
2196 UIActivate(SVUIA_DEACTIVATE
);
2204 pShellBrowser
.Release();
2205 pCommDlgBrowser
.Release();
2210 HRESULT WINAPI
CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs
)
2212 TRACE("(%p)->(%p) vmode=%x flags=%x\n",this, lpfs
,
2213 FolderSettings
.ViewMode
, FolderSettings
.fFlags
);
2215 if (!lpfs
) return E_INVALIDARG
;
2217 *lpfs
= FolderSettings
;
2221 HRESULT WINAPI
CDefView::AddPropertySheetPages(DWORD dwReserved
,LPFNADDPROPSHEETPAGE lpfn
, LPARAM lparam
)
2223 FIXME("(%p) stub\n",this);
2228 HRESULT WINAPI
CDefView::SaveViewState()
2230 FIXME("(%p) stub\n",this);
2235 HRESULT WINAPI
CDefView::SelectItem(LPCITEMIDLIST pidl
, UINT uFlags
)
2239 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",this, pidl
, uFlags
);
2241 i
= LV_FindItemByPidl(pidl
);
2247 if(uFlags
& SVSI_ENSUREVISIBLE
)
2248 SendMessageW(hWndList
, LVM_ENSUREVISIBLE
, i
, 0);
2250 lvItem
.mask
= LVIF_STATE
;
2251 lvItem
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
2253 lvItem
.iSubItem
= 0;
2255 while(SendMessageW(hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
))
2257 if (lvItem
.iItem
== i
)
2259 if (uFlags
& SVSI_SELECT
)
2260 lvItem
.state
|= LVIS_SELECTED
;
2262 lvItem
.state
&= ~LVIS_SELECTED
;
2264 if(uFlags
& SVSI_FOCUSED
)
2265 lvItem
.state
&= ~LVIS_FOCUSED
;
2269 if (uFlags
& SVSI_DESELECTOTHERS
)
2270 lvItem
.state
&= ~LVIS_SELECTED
;
2272 SendMessageW(hWndList
, LVM_SETITEMW
, 0, (LPARAM
) &lvItem
);
2277 if(uFlags
& SVSI_EDIT
)
2278 SendMessageW(hWndList
, LVM_EDITLABELW
, i
, 0);
2284 HRESULT WINAPI
CDefView::GetItemObject(UINT uItem
, REFIID riid
, LPVOID
*ppvOut
)
2286 HRESULT hr
= E_FAIL
;
2288 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",this, uItem
, debugstr_guid(&riid
), ppvOut
);
2294 case SVGIO_BACKGROUND
:
2295 if (IsEqualIID(riid
, IID_IContextMenu
))
2297 //*ppvOut = ISvBgCm_Constructor(pSFParent, FALSE);
2298 CDefFolderMenu_Create2(NULL
, NULL
, cidl
, (LPCITEMIDLIST
*)apidl
, pSFParent
, NULL
, 0, NULL
, (IContextMenu
**)ppvOut
);
2304 case SVGIO_SELECTION
:
2306 hr
= pSFParent
->GetUIObjectOf(m_hWnd
, cidl
, (LPCITEMIDLIST
*)apidl
, riid
, 0, ppvOut
);
2309 TRACE("-- (%p)->(interface=%p)\n",this, *ppvOut
);
2314 HRESULT STDMETHODCALLTYPE
CDefView::GetCurrentViewMode(UINT
*pViewMode
)
2319 HRESULT STDMETHODCALLTYPE
CDefView::SetCurrentViewMode(UINT ViewMode
)
2324 HRESULT STDMETHODCALLTYPE
CDefView::GetFolder(REFIID riid
, void **ppv
)
2326 if (pSFParent
== NULL
)
2328 return pSFParent
->QueryInterface(riid
, ppv
);
2331 HRESULT STDMETHODCALLTYPE
CDefView::Item(int iItemIndex
, LPITEMIDLIST
*ppidl
)
2336 HRESULT STDMETHODCALLTYPE
CDefView::ItemCount(UINT uFlags
, int *pcItems
)
2341 HRESULT STDMETHODCALLTYPE
CDefView::Items(UINT uFlags
, REFIID riid
, void **ppv
)
2346 HRESULT STDMETHODCALLTYPE
CDefView::GetSelectionMarkedItem(int *piItem
)
2351 HRESULT STDMETHODCALLTYPE
CDefView::GetFocusedItem(int *piItem
)
2356 HRESULT STDMETHODCALLTYPE
CDefView::GetItemPosition(LPCITEMIDLIST pidl
, POINT
*ppt
)
2361 HRESULT STDMETHODCALLTYPE
CDefView::GetSpacing(POINT
*ppt
)
2366 HRESULT STDMETHODCALLTYPE
CDefView::GetDefaultSpacing(POINT
*ppt
)
2371 HRESULT STDMETHODCALLTYPE
CDefView::GetAutoArrange()
2376 HRESULT STDMETHODCALLTYPE
CDefView::SelectItem(int iItem
, DWORD dwFlags
)
2381 HRESULT STDMETHODCALLTYPE
CDefView::SelectAndPositionItems(UINT cidl
, LPCITEMIDLIST
*apidl
, POINT
*apt
, DWORD dwFlags
)
2386 /**********************************************************
2387 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2389 HRESULT WINAPI
CDefView::QueryStatus(const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD
*prgCmds
, OLECMDTEXT
*pCmdText
)
2393 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2394 this, pguidCmdGroup
, debugstr_guid(pguidCmdGroup
), cCmds
, prgCmds
, pCmdText
);
2398 for (i
= 0; i
< cCmds
; i
++)
2400 FIXME("\tprgCmds[%d].cmdID = %d\n", i
, prgCmds
[i
].cmdID
);
2401 prgCmds
[i
].cmdf
= 0;
2403 return OLECMDERR_E_UNKNOWNGROUP
;
2406 /**********************************************************
2407 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2409 * nCmdID is the OLECMDID_* enumeration
2411 HRESULT WINAPI
CDefView::Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
2413 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2414 this, debugstr_guid(pguidCmdGroup
), nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
2416 if (IsEqualIID(*pguidCmdGroup
, CGID_Explorer
) &&
2418 (nCmdexecopt
== 4) && pvaOut
)
2420 if (IsEqualIID(*pguidCmdGroup
, CGID_ShellDocView
) &&
2425 return OLECMDERR_E_UNKNOWNGROUP
;
2428 /**********************************************************
2429 * ISVDropTarget implementation
2432 /******************************************************************************
2433 * drag_notify_subitem [Internal]
2435 * Figure out the shellfolder object, which is currently under the mouse cursor
2436 * and notify it via the IDropTarget interface.
2439 #define SCROLLAREAWIDTH 20
2441 HRESULT
CDefView::drag_notify_subitem(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2443 LVHITTESTINFO htinfo
;
2449 /* Map from global to client coordinates and query the index of the listview-item, which is
2450 * currently under the mouse cursor. */
2453 htinfo
.flags
= LVHT_ONITEM
;
2454 ::ScreenToClient(hWndList
, &htinfo
.pt
);
2455 lResult
= SendMessageW(hWndList
, LVM_HITTEST
, 0, (LPARAM
)&htinfo
);
2457 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2458 ::GetClientRect(hWndList
, &clientRect
);
2459 if (htinfo
.pt
.x
== ptLastMousePos
.x
&& htinfo
.pt
.y
== ptLastMousePos
.y
&&
2460 (htinfo
.pt
.x
< SCROLLAREAWIDTH
|| htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
||
2461 htinfo
.pt
.y
< SCROLLAREAWIDTH
|| htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
))
2463 cScrollDelay
= (cScrollDelay
+ 1) % 5; /* DragOver is called every 50 ms */
2464 if (cScrollDelay
== 0) { /* Mouse did hover another 250 ms over the scroll-area */
2465 if (htinfo
.pt
.x
< SCROLLAREAWIDTH
)
2466 SendMessageW(hWndList
, WM_HSCROLL
, SB_LINEUP
, 0);
2467 if (htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
)
2468 SendMessageW(hWndList
, WM_HSCROLL
, SB_LINEDOWN
, 0);
2469 if (htinfo
.pt
.y
< SCROLLAREAWIDTH
)
2470 SendMessageW(hWndList
, WM_VSCROLL
, SB_LINEUP
, 0);
2471 if (htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
)
2472 SendMessageW(hWndList
, WM_VSCROLL
, SB_LINEDOWN
, 0);
2475 cScrollDelay
= 0; /* Reset, if the cursor is not over the listview's scroll-area */
2477 ptLastMousePos
= htinfo
.pt
;
2479 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2480 if (pCurDropTarget
&& lResult
== iDragOverItem
)
2481 return pCurDropTarget
->DragOver(grfKeyState
, pt
, pdwEffect
);
2483 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2484 if (pCurDropTarget
) {
2485 pCurDropTarget
->DragLeave();
2486 pCurDropTarget
.Release();
2489 iDragOverItem
= lResult
;
2490 if (lResult
== -1) {
2491 /* We are not above one of the listview's subitems. Bind to the parent folder's
2492 * DropTarget interface. */
2493 hr
= pSFParent
->QueryInterface(IID_IDropTarget
,
2494 (LPVOID
*)&pCurDropTarget
);
2496 /* Query the relative PIDL of the shellfolder object represented by the currently
2497 * dragged over listview-item ... */
2498 lvItem
.mask
= LVIF_PARAM
;
2499 lvItem
.iItem
= lResult
;
2500 lvItem
.iSubItem
= 0;
2501 SendMessageW(hWndList
, LVM_GETITEMW
, 0, (LPARAM
) &lvItem
);
2503 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2504 hr
= pSFParent
->GetUIObjectOf(hWndList
, 1,
2505 (LPCITEMIDLIST
*)&lvItem
.lParam
, IID_IDropTarget
, NULL
, (LPVOID
*)&pCurDropTarget
);
2508 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2512 /* Notify the item just entered via DragEnter. */
2513 return pCurDropTarget
->DragEnter(pCurDataObject
, grfKeyState
, pt
, pdwEffect
);
2516 HRESULT WINAPI
CDefView::DragEnter(IDataObject
*pDataObject
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2518 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2519 pCurDataObject
= pDataObject
;
2520 pDataObject
->AddRef();
2522 return drag_notify_subitem(grfKeyState
, pt
, pdwEffect
);
2525 HRESULT WINAPI
CDefView::DragOver(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2527 return drag_notify_subitem(grfKeyState
, pt
, pdwEffect
);
2530 HRESULT WINAPI
CDefView::DragLeave()
2534 pCurDropTarget
->DragLeave();
2535 pCurDropTarget
.Release();
2538 if (pCurDataObject
!= NULL
)
2540 pCurDataObject
.Release();
2548 HRESULT WINAPI
CDefView::Drop(IDataObject
* pDataObject
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
2552 pCurDropTarget
->Drop(pDataObject
, grfKeyState
, pt
, pdwEffect
);
2553 pCurDropTarget
.Release();
2556 pCurDataObject
.Release();
2562 /**********************************************************
2563 * ISVDropSource implementation
2566 HRESULT WINAPI
CDefView::QueryContinueDrag(BOOL fEscapePressed
, DWORD grfKeyState
)
2568 TRACE("(%p)\n",this);
2571 return DRAGDROP_S_CANCEL
;
2572 else if (!(grfKeyState
& MK_LBUTTON
) && !(grfKeyState
& MK_RBUTTON
))
2573 return DRAGDROP_S_DROP
;
2578 HRESULT WINAPI
CDefView::GiveFeedback(DWORD dwEffect
)
2580 TRACE("(%p)\n",this);
2582 return DRAGDROP_S_USEDEFAULTCURSORS
;
2585 /**********************************************************
2586 * ISVViewObject implementation
2589 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
)
2591 FIXME("Stub: this=%p\n",this);
2596 HRESULT WINAPI
CDefView::GetColorSet(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DVTARGETDEVICE
*ptd
, HDC hicTargetDevice
, LOGPALETTE
**ppColorSet
)
2598 FIXME("Stub: this=%p\n",this);
2603 HRESULT WINAPI
CDefView::Freeze(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DWORD
*pdwFreeze
)
2605 FIXME("Stub: this=%p\n",this);
2610 HRESULT WINAPI
CDefView::Unfreeze(DWORD dwFreeze
)
2612 FIXME("Stub: this=%p\n",this);
2617 HRESULT WINAPI
CDefView::SetAdvise(DWORD aspects
, DWORD advf
, IAdviseSink
*pAdvSink
)
2619 FIXME("partial stub: %p %08x %08x %p\n", this, aspects
, advf
, pAdvSink
);
2621 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2622 pAdvSink
= pAdvSink
;
2623 dwAspects
= aspects
;
2629 HRESULT WINAPI
CDefView::GetAdvise(DWORD
*pAspects
, DWORD
*pAdvf
, IAdviseSink
**ppAdvSink
)
2631 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects
, pAdvf
, ppAdvSink
);
2635 *ppAdvSink
= pAdvSink
;
2636 pAdvSink
.p
->AddRef();
2639 *pAspects
= dwAspects
;
2646 HRESULT STDMETHODCALLTYPE
CDefView::QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
)
2648 if (IsEqualIID(guidService
, SID_IShellBrowser
))
2649 return pShellBrowser
->QueryInterface(riid
, ppvObject
);
2650 return E_NOINTERFACE
;
2653 /**********************************************************
2654 * IShellView_Constructor
2656 HRESULT WINAPI
IShellView_Constructor(IShellFolder
*pFolder
, IShellView
**newView
)
2658 CComObject
<CDefView
> *theView
;
2659 CComPtr
<IShellView
> result
;
2662 if (newView
== NULL
)
2665 ATLTRY (theView
= new CComObject
<CDefView
>);
2666 if (theView
== NULL
)
2667 return E_OUTOFMEMORY
;
2668 hResult
= theView
->QueryInterface (IID_IShellView
, (void **)&result
);
2669 if (FAILED (hResult
))
2674 hResult
= theView
->Initialize (pFolder
);
2675 if (FAILED (hResult
))
2677 *newView
= result
.Detach ();