4 * Copyright 1998,1999 <juergen.schmied@debitel.net>
5 * Copyright 2022 Russell Johnson <russell.johnson@superdark.net>
7 * This is the view visualizing the data provided by the shellfolder.
8 * No direct access to data from pidls should be done from here.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
29 - Load/Save the view state from/into the stream provided by the ShellBrowser.
30 - When editing starts on item, set edit text to for editing value.
31 - Fix shell view to handle view mode popup exec.
32 - The background context menu should have a pidl just like foreground menus. This
33 causes crashes when dynamic handlers try to use the NULL pidl.
34 - Reorder of columns doesn't work - might be bug in comctl32
40 #include <ui/rosctrls.h>
42 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
49 } LISTVIEW_SORT_INFO
, *LPLISTVIEW_SORT_INFO
;
51 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
53 // For the context menu of the def view, the id of the items are based on 1 because we need
54 // to call TrackPopupMenu and let it use the 0 value as an indication that the menu was canceled
55 #define CONTEXT_MENU_BASE_ID 1
57 // Convert client coordinates to listview coordinates
59 ClientToListView(HWND hwndLV
, POINT
*ppt
)
63 // FIXME: LVM_GETORIGIN is broken. See CORE-17266
64 if (!ListView_GetOrigin(hwndLV
, &Origin
))
71 // Helper struct to automatically cleanup the IContextMenu
72 // We want to explicitly reset the Site, so there are no circular references
75 CComPtr
<IContextMenu
> &m_pCM
;
78 MenuCleanup(CComPtr
<IContextMenu
> &pCM
, HMENU
& menu
)
79 : m_pCM(pCM
), m_hMenu(menu
)
91 IUnknown_SetSite(m_pCM
, NULL
);
98 public CWindowImpl
<CDefView
, CWindow
, CControlWinTraits
>,
99 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
102 public IShellFolderView
,
103 public IOleCommandTarget
,
107 public IServiceProvider
110 CComPtr
<IShellFolder
> m_pSFParent
;
111 CComPtr
<IShellFolder2
> m_pSF2Parent
;
112 CComPtr
<IShellFolderViewCB
> m_pShellFolderViewCB
;
113 CComPtr
<IShellBrowser
> m_pShellBrowser
;
114 CComPtr
<ICommDlgBrowser
> m_pCommDlgBrowser
;
115 CComPtr
<IShellFolderViewDual
> m_pShellFolderViewDual
;
116 CListView m_ListView
;
118 FOLDERSETTINGS m_FolderSettings
;
119 HMENU m_hMenu
; // Handle to the menu bar of the browser
120 HMENU m_hMenuArrangeModes
; // Handle to the popup menu with the arrange modes
121 HMENU m_hMenuViewModes
; // Handle to the popup menu with the view modes
122 HMENU m_hContextMenu
; // Handle to the open context menu
123 BOOL m_bmenuBarInitialized
;
126 PCUITEMID_CHILD
*m_apidl
;
127 PIDLIST_ABSOLUTE m_pidlParent
;
128 LISTVIEW_SORT_INFO m_sortInfo
;
129 ULONG m_hNotify
; // Change notification handle
133 CComPtr
<IAdviseSink
> m_pAdvSink
;
135 CComPtr
<IDataObject
> m_pSourceDataObject
;
136 CComPtr
<IDropTarget
> m_pCurDropTarget
; // The sub-item, which is currently dragged over
137 CComPtr
<IDataObject
> m_pCurDataObject
; // The dragged data-object
138 LONG m_iDragOverItem
; // Dragged over item's index, if m_pCurDropTarget != NULL
139 UINT m_cScrollDelay
; // Send a WM_*SCROLL msg every 250 ms during drag-scroll
140 POINT m_ptLastMousePos
; // Mouse position at last DragOver call
141 POINT m_ptFirstMousePos
; // Mouse position when the drag operation started
144 CComPtr
<IContextMenu
> m_pCM
;
145 CComPtr
<IContextMenu
> m_pFileMenu
;
148 BOOL m_isParentFolderSpecial
;
152 SFVM_CUSTOMVIEWINFO_DATA m_viewinfo_data
;
154 HICON m_hMyComputerIcon
;
156 HRESULT
_MergeToolbar();
158 HRESULT
_DoFolderViewCB(UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
159 HRESULT
_GetSnapToGrid();
160 void _MoveSelectionOnAutoArrange(POINT pt
);
161 INT
_FindInsertableIndexFromPoint(POINT pt
);
162 void _HandleStatusBarResize(int width
);
163 void _ForceStatusBarResize();
164 void _DoCopyToMoveToFolder(BOOL bCopy
);
169 HRESULT WINAPI
Initialize(IShellFolder
*shellFolder
);
170 HRESULT
IncludeObject(PCUITEMID_CHILD pidl
);
171 HRESULT
OnDefaultCommand();
172 HRESULT
OnStateChange(UINT uFlags
);
173 void UpdateStatusbar();
176 void UpdateListColors();
178 static INT CALLBACK
ListViewCompareItems(LPARAM lParam1
, LPARAM lParam2
, LPARAM lpData
);
180 PCUITEMID_CHILD
_PidlByItem(int i
);
181 PCUITEMID_CHILD
_PidlByItem(LVITEM
& lvItem
);
182 int LV_FindItemByPidl(PCUITEMID_CHILD pidl
);
183 int LV_AddItem(PCUITEMID_CHILD pidl
);
184 BOOLEAN
LV_DeleteItem(PCUITEMID_CHILD pidl
);
185 BOOLEAN
LV_RenameItem(PCUITEMID_CHILD pidlOld
, PCUITEMID_CHILD pidlNew
);
186 BOOLEAN
LV_ProdItem(PCUITEMID_CHILD pidl
);
187 static INT CALLBACK
fill_list(LPVOID ptr
, LPVOID arg
);
189 HRESULT
FillFileMenu();
190 HRESULT
FillEditMenu();
191 HRESULT
FillViewMenu();
192 HRESULT
FillArrangeAsMenu(HMENU hmenuArrange
);
193 HRESULT
CheckViewMode(HMENU hmenuView
);
194 UINT
GetSelections();
195 HRESULT
OpenSelectedItems();
197 void DoActivate(UINT uState
);
198 HRESULT
drag_notify_subitem(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
);
199 HRESULT
InvokeContextMenuCommand(CComPtr
<IContextMenu
>& pCM
, LPCSTR lpVerb
, POINT
* pt
= NULL
);
200 LRESULT
OnExplorerCommand(UINT uCommand
, BOOL bUseSelection
);
202 // *** IOleWindow methods ***
203 STDMETHOD(GetWindow
)(HWND
*lphwnd
) override
;
204 STDMETHOD(ContextSensitiveHelp
)(BOOL fEnterMode
) override
;
206 // *** IShellView methods ***
207 STDMETHOD(TranslateAccelerator
)(MSG
*pmsg
) override
;
208 STDMETHOD(EnableModeless
)(BOOL fEnable
) override
;
209 STDMETHOD(UIActivate
)(UINT uState
) override
;
210 STDMETHOD(Refresh
)() override
;
211 STDMETHOD(CreateViewWindow
)(IShellView
*psvPrevious
, LPCFOLDERSETTINGS pfs
, IShellBrowser
*psb
, RECT
*prcView
, HWND
*phWnd
) override
;
212 STDMETHOD(DestroyViewWindow
)() override
;
213 STDMETHOD(GetCurrentInfo
)(LPFOLDERSETTINGS pfs
) override
;
214 STDMETHOD(AddPropertySheetPages
)(DWORD dwReserved
, LPFNSVADDPROPSHEETPAGE pfn
, LPARAM lparam
) override
;
215 STDMETHOD(SaveViewState
)() override
;
216 STDMETHOD(SelectItem
)(PCUITEMID_CHILD pidlItem
, SVSIF uFlags
) override
;
217 STDMETHOD(GetItemObject
)(UINT uItem
, REFIID riid
, void **ppv
) override
;
219 // *** IShellView2 methods ***
220 STDMETHOD(GetView
)(SHELLVIEWID
*view_guid
, ULONG view_type
) override
;
221 STDMETHOD(CreateViewWindow2
)(LPSV2CVW2_PARAMS view_params
) override
;
222 STDMETHOD(HandleRename
)(LPCITEMIDLIST new_pidl
) override
;
223 STDMETHOD(SelectAndPositionItem
)(LPCITEMIDLIST item
, UINT flags
, POINT
*point
) override
;
225 // *** IShellView3 methods ***
226 STDMETHOD(CreateViewWindow3
)(
228 IShellView
*psvPrevious
,
229 SV3CVW3_FLAGS view_flags
,
233 const SHELLVIEWID
*view_id
,
235 HWND
*hwnd
) override
;
237 // *** IFolderView methods ***
238 STDMETHOD(GetCurrentViewMode
)(UINT
*pViewMode
) override
;
239 STDMETHOD(SetCurrentViewMode
)(UINT ViewMode
) override
;
240 STDMETHOD(GetFolder
)(REFIID riid
, void **ppv
) override
;
241 STDMETHOD(Item
)(int iItemIndex
, PITEMID_CHILD
*ppidl
) override
;
242 STDMETHOD(ItemCount
)(UINT uFlags
, int *pcItems
) override
;
243 STDMETHOD(Items
)(UINT uFlags
, REFIID riid
, void **ppv
) override
;
244 STDMETHOD(GetSelectionMarkedItem
)(int *piItem
) override
;
245 STDMETHOD(GetFocusedItem
)(int *piItem
) override
;
246 STDMETHOD(GetItemPosition
)(PCUITEMID_CHILD pidl
, POINT
*ppt
) override
;
247 STDMETHOD(GetSpacing
)(POINT
*ppt
) override
;
248 STDMETHOD(GetDefaultSpacing
)(POINT
*ppt
) override
;
249 STDMETHOD(GetAutoArrange
)() override
;
250 STDMETHOD(SelectItem
)(int iItem
, DWORD dwFlags
) override
;
251 STDMETHOD(SelectAndPositionItems
)(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, POINT
*apt
, DWORD dwFlags
) override
;
253 // *** IShellFolderView methods ***
254 STDMETHOD(Rearrange
)(LPARAM sort
) override
;
255 STDMETHOD(GetArrangeParam
)(LPARAM
*sort
) override
;
256 STDMETHOD(ArrangeGrid
)() override
;
257 STDMETHOD(AutoArrange
)() override
;
258 STDMETHOD(AddObject
)(PITEMID_CHILD pidl
, UINT
*item
) override
;
259 STDMETHOD(GetObject
)(PITEMID_CHILD
*pidl
, UINT item
) override
;
260 STDMETHOD(RemoveObject
)(PITEMID_CHILD pidl
, UINT
*item
) override
;
261 STDMETHOD(GetObjectCount
)(UINT
*count
) override
;
262 STDMETHOD(SetObjectCount
)(UINT count
, UINT flags
) override
;
263 STDMETHOD(UpdateObject
)(PITEMID_CHILD pidl_old
, PITEMID_CHILD pidl_new
, UINT
*item
) override
;
264 STDMETHOD(RefreshObject
)(PITEMID_CHILD pidl
, UINT
*item
) override
;
265 STDMETHOD(SetRedraw
)(BOOL redraw
) override
;
266 STDMETHOD(GetSelectedCount
)(UINT
*count
) override
;
267 STDMETHOD(GetSelectedObjects
)(PCUITEMID_CHILD
**pidl
, UINT
*items
) override
;
268 STDMETHOD(IsDropOnSource
)(IDropTarget
*drop_target
) override
;
269 STDMETHOD(GetDragPoint
)(POINT
*pt
) override
;
270 STDMETHOD(GetDropPoint
)(POINT
*pt
) override
;
271 STDMETHOD(MoveIcons
)(IDataObject
*obj
) override
;
272 STDMETHOD(SetItemPos
)(PCUITEMID_CHILD pidl
, POINT
*pt
) override
;
273 STDMETHOD(IsBkDropTarget
)(IDropTarget
*drop_target
) override
;
274 STDMETHOD(SetClipboard
)(BOOL move
) override
;
275 STDMETHOD(SetPoints
)(IDataObject
*obj
) override
;
276 STDMETHOD(GetItemSpacing
)(ITEMSPACING
*spacing
) override
;
277 STDMETHOD(SetCallback
)(IShellFolderViewCB
*new_cb
, IShellFolderViewCB
**old_cb
) override
;
278 STDMETHOD(Select
)(UINT flags
) override
;
279 STDMETHOD(QuerySupport
)(UINT
*support
) override
;
280 STDMETHOD(SetAutomationObject
)(IDispatch
*disp
) override
;
282 // *** IOleCommandTarget methods ***
283 STDMETHOD(QueryStatus
)(const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD prgCmds
[], OLECMDTEXT
*pCmdText
) override
;
284 STDMETHOD(Exec
)(const GUID
*pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
) override
;
286 // *** IDropTarget methods ***
287 STDMETHOD(DragEnter
)(IDataObject
*pDataObj
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
) override
;
288 STDMETHOD(DragOver
)(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
) override
;
289 STDMETHOD(DragLeave
)() override
;
290 STDMETHOD(Drop
)(IDataObject
*pDataObj
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
) override
;
292 // *** IDropSource methods ***
293 STDMETHOD(QueryContinueDrag
)(BOOL fEscapePressed
, DWORD grfKeyState
) override
;
294 STDMETHOD(GiveFeedback
)(DWORD dwEffect
) override
;
296 // *** IViewObject methods ***
297 STDMETHOD(Draw
)(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DVTARGETDEVICE
*ptd
,
298 HDC hdcTargetDev
, HDC hdcDraw
, LPCRECTL lprcBounds
, LPCRECTL lprcWBounds
,
299 BOOL (STDMETHODCALLTYPE
*pfnContinue
)(ULONG_PTR dwContinue
), ULONG_PTR dwContinue
) override
;
300 STDMETHOD(GetColorSet
)(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
,
301 DVTARGETDEVICE
*ptd
, HDC hicTargetDev
, LOGPALETTE
**ppColorSet
) override
;
302 STDMETHOD(Freeze
)(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DWORD
*pdwFreeze
) override
;
303 STDMETHOD(Unfreeze
)(DWORD dwFreeze
) override
;
304 STDMETHOD(SetAdvise
)(DWORD aspects
, DWORD advf
, IAdviseSink
*pAdvSink
) override
;
305 STDMETHOD(GetAdvise
)(DWORD
*pAspects
, DWORD
*pAdvf
, IAdviseSink
**ppAdvSink
) override
;
307 // *** IServiceProvider methods ***
308 STDMETHOD(QueryService
)(REFGUID guidService
, REFIID riid
, void **ppvObject
) override
;
311 LRESULT
OnShowWindow(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
312 LRESULT
OnGetDlgCode(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
313 LRESULT
OnDestroy(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
314 LRESULT
OnEraseBackground(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
315 LRESULT
OnPrintClient(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
316 LRESULT
OnSysColorChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
317 LRESULT
OnGetShellBrowser(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
318 LRESULT
OnNCCreate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
319 LRESULT
OnCreate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
320 LRESULT
OnContextMenu(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
321 LRESULT
OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
322 LRESULT
OnActivate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
323 LRESULT
OnSetFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
324 LRESULT
OnKillFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
325 LRESULT
OnCommand(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
326 LRESULT
OnNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
327 LRESULT
OnChangeNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
328 LRESULT
OnCustomItem(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
329 LRESULT
OnSettingChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
330 LRESULT
OnInitMenuPopup(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
332 virtual VOID
OnFinalMessage(HWND
) override
;
334 static ATL::CWndClassInfo
& GetWndClassInfo()
336 static ATL::CWndClassInfo wc
=
338 { sizeof(WNDCLASSEX
), CS_PARENTDC
, StartWindowProc
,
340 LoadCursor(NULL
, IDC_ARROW
), NULL
, NULL
, L
"SHELLDLL_DefView", NULL
342 NULL
, NULL
, IDC_ARROW
, TRUE
, 0, _T("")
347 virtual WNDPROC
GetWindowProc()
352 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
357 // Must hold a reference during message handling
358 pThis
= reinterpret_cast<CDefView
*>(hWnd
);
360 result
= CWindowImpl
<CDefView
, CWindow
, CControlWinTraits
>::WindowProc(hWnd
, uMsg
, wParam
, lParam
);
365 BEGIN_MSG_MAP(CDefView
)
366 MESSAGE_HANDLER(WM_SIZE
, OnSize
)
367 MESSAGE_HANDLER(WM_SETFOCUS
, OnSetFocus
)
368 MESSAGE_HANDLER(WM_KILLFOCUS
, OnKillFocus
)
369 MESSAGE_HANDLER(WM_NCCREATE
, OnNCCreate
)
370 MESSAGE_HANDLER(WM_CREATE
, OnCreate
)
371 MESSAGE_HANDLER(WM_ACTIVATE
, OnActivate
)
372 MESSAGE_HANDLER(WM_NOTIFY
, OnNotify
)
373 MESSAGE_HANDLER(WM_COMMAND
, OnCommand
)
374 MESSAGE_HANDLER(SHV_CHANGE_NOTIFY
, OnChangeNotify
)
375 MESSAGE_HANDLER(WM_CONTEXTMENU
, OnContextMenu
)
376 MESSAGE_HANDLER(WM_DRAWITEM
, OnCustomItem
)
377 MESSAGE_HANDLER(WM_MEASUREITEM
, OnCustomItem
)
378 MESSAGE_HANDLER(WM_SHOWWINDOW
, OnShowWindow
)
379 MESSAGE_HANDLER(WM_GETDLGCODE
, OnGetDlgCode
)
380 MESSAGE_HANDLER(WM_DESTROY
, OnDestroy
)
381 MESSAGE_HANDLER(WM_ERASEBKGND
, OnEraseBackground
)
382 MESSAGE_HANDLER(WM_PRINTCLIENT
, OnPrintClient
)
383 MESSAGE_HANDLER(WM_SYSCOLORCHANGE
, OnSysColorChange
)
384 MESSAGE_HANDLER(CWM_GETISHELLBROWSER
, OnGetShellBrowser
)
385 MESSAGE_HANDLER(WM_SETTINGCHANGE
, OnSettingChange
)
386 MESSAGE_HANDLER(WM_INITMENUPOPUP
, OnInitMenuPopup
)
389 BEGIN_COM_MAP(CDefView
)
390 // Windows returns E_NOINTERFACE for IOleWindow
391 // COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
392 COM_INTERFACE_ENTRY_IID(IID_IShellView
, IShellView
)
393 COM_INTERFACE_ENTRY_IID(IID_CDefView
, IShellView
)
394 COM_INTERFACE_ENTRY_IID(IID_IShellView2
, IShellView2
)
395 COM_INTERFACE_ENTRY_IID(IID_IShellView3
, IShellView3
)
396 COM_INTERFACE_ENTRY_IID(IID_IFolderView
, IFolderView
)
397 COM_INTERFACE_ENTRY_IID(IID_IShellFolderView
, IShellFolderView
)
398 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget
, IOleCommandTarget
)
399 COM_INTERFACE_ENTRY_IID(IID_IDropTarget
, IDropTarget
)
400 COM_INTERFACE_ENTRY_IID(IID_IDropSource
, IDropSource
)
401 COM_INTERFACE_ENTRY_IID(IID_IViewObject
, IViewObject
)
402 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider
, IServiceProvider
)
407 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
408 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
409 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
411 #define ID_LISTVIEW 1
414 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
415 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
416 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
418 typedef void (CALLBACK
*PFNSHGETSETTINGSPROC
)(LPSHELLFLAGSTATE lpsfs
, DWORD dwMask
);
420 CDefView::CDefView() :
424 m_hMenuArrangeModes(NULL
),
425 m_hMenuViewModes(NULL
),
426 m_hContextMenu(NULL
),
427 m_bmenuBarInitialized(FALSE
),
439 m_isParentFolderSpecial(FALSE
),
442 ZeroMemory(&m_FolderSettings
, sizeof(m_FolderSettings
));
443 ZeroMemory(&m_sortInfo
, sizeof(m_sortInfo
));
444 ZeroMemory(&m_ptLastMousePos
, sizeof(m_ptLastMousePos
));
445 ZeroMemory(&m_Category
, sizeof(m_Category
));
446 m_viewinfo_data
.clrText
= GetSysColor(COLOR_WINDOWTEXT
);
447 m_viewinfo_data
.clrTextBack
= GetSysColor(COLOR_WINDOW
);
448 m_viewinfo_data
.hbmBack
= NULL
;
450 m_hMyComputerIcon
= LoadIconW(shell32_hInstance
, MAKEINTRESOURCEW(IDI_SHELL_COMPUTER_DESKTOP
));
453 CDefView::~CDefView()
455 TRACE(" destroying IShellView(%p)\n", this);
457 _DoFolderViewCB(SFVM_VIEWRELEASE
, 0, 0);
459 if (m_viewinfo_data
.hbmBack
)
461 ::DeleteObject(m_viewinfo_data
.hbmBack
);
462 m_viewinfo_data
.hbmBack
= NULL
;
473 HRESULT WINAPI
CDefView::Initialize(IShellFolder
*shellFolder
)
475 m_pSFParent
= shellFolder
;
476 shellFolder
->QueryInterface(IID_PPV_ARG(IShellFolder2
, &m_pSF2Parent
));
481 // ##### helperfunctions for communication with ICommDlgBrowser #####
483 HRESULT
CDefView::IncludeObject(PCUITEMID_CHILD pidl
)
487 if (m_pCommDlgBrowser
.p
!= NULL
)
489 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl
);
490 ret
= m_pCommDlgBrowser
->IncludeObject(this, pidl
);
491 TRACE("-- returns 0x%08x\n", ret
);
497 HRESULT
CDefView::OnDefaultCommand()
499 HRESULT ret
= S_FALSE
;
501 if (m_pCommDlgBrowser
.p
!= NULL
)
503 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
504 ret
= m_pCommDlgBrowser
->OnDefaultCommand(this);
505 TRACE("-- returns 0x%08x\n", ret
);
511 HRESULT
CDefView::OnStateChange(UINT uFlags
)
513 HRESULT ret
= S_FALSE
;
515 if (m_pCommDlgBrowser
.p
!= NULL
)
517 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags
);
518 ret
= m_pCommDlgBrowser
->OnStateChange(this, uFlags
);
524 /**********************************************************
525 * set the toolbar of the filedialog buttons
527 * - activates the buttons from the shellbrowser according to
530 void CDefView::CheckToolbar()
536 if (m_pCommDlgBrowser
!= NULL
)
538 m_pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_CHECKBUTTON
,
539 FCIDM_TB_SMALLICON
, (m_FolderSettings
.ViewMode
== FVM_LIST
) ? TRUE
: FALSE
, &result
);
540 m_pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_CHECKBUTTON
,
541 FCIDM_TB_REPORTVIEW
, (m_FolderSettings
.ViewMode
== FVM_DETAILS
) ? TRUE
: FALSE
, &result
);
542 m_pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_ENABLEBUTTON
,
543 FCIDM_TB_SMALLICON
, TRUE
, &result
);
544 m_pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_ENABLEBUTTON
,
545 FCIDM_TB_REPORTVIEW
, TRUE
, &result
);
549 void CDefView::UpdateStatusbar()
551 WCHAR szFormat
[MAX_PATH
] = {0};
552 WCHAR szPartText
[MAX_PATH
] = {0};
558 cSelectedItems
= m_ListView
.GetSelectedCount();
561 LoadStringW(shell32_hInstance
, IDS_OBJECTS_SELECTED
, szFormat
, _countof(szFormat
));
562 StringCchPrintfW(szPartText
, _countof(szPartText
), szFormat
, cSelectedItems
);
566 LoadStringW(shell32_hInstance
, IDS_OBJECTS
, szFormat
, _countof(szFormat
));
567 StringCchPrintfW(szPartText
, _countof(szPartText
), szFormat
, m_ListView
.GetItemCount());
571 m_pShellBrowser
->SendControlMsg(FCW_STATUS
, SB_SETTEXT
, 0, (LPARAM
)szPartText
, &lResult
);
573 // Don't bother with the extra processing if we only have one StatusBar part
574 if (!m_isParentFolderSpecial
)
576 DWORD uTotalFileSize
= 0;
577 WORD uFileFlags
= LVNI_ALL
;
580 bool bIsOnlyFoldersSelected
= true;
582 // If we have something selected then only count selected file sizes
585 uFileFlags
= LVNI_SELECTED
;
588 while ((nItem
= m_ListView
.GetNextItem(nItem
, uFileFlags
)) >= 0)
590 PCUITEMID_CHILD pidl
= _PidlByItem(nItem
);
592 uTotalFileSize
+= _ILGetFileSize(pidl
, NULL
, 0);
594 if (!_ILIsFolder(pidl
))
596 bIsOnlyFoldersSelected
= false;
600 // Don't show the file size text if there is 0 bytes in the folder
601 // OR we only have folders selected
602 if ((cSelectedItems
&& !bIsOnlyFoldersSelected
) || uTotalFileSize
)
604 StrFormatByteSizeW(uTotalFileSize
, szPartText
, _countof(szPartText
));
611 m_pShellBrowser
->SendControlMsg(FCW_STATUS
, SB_SETTEXT
, 1, (LPARAM
)szPartText
, &lResult
);
613 // If we are in a Recycle Bin then show no text for the location part
614 if (!_ILIsBitBucket(m_pidlParent
))
616 LoadStringW(shell32_hInstance
, IDS_MYCOMPUTER
, szPartText
, _countof(szPartText
));
617 pIcon
= (LPARAM
)m_hMyComputerIcon
;
620 m_pShellBrowser
->SendControlMsg(FCW_STATUS
, SB_SETICON
, 2, pIcon
, &lResult
);
621 m_pShellBrowser
->SendControlMsg(FCW_STATUS
, SB_SETTEXT
, 2, (LPARAM
)szPartText
, &lResult
);
626 // ##### helperfunctions for initializing the view #####
628 // creates the list view window
629 BOOL
CDefView::CreateList()
632 DWORD dwStyle
, dwExStyle
, ListExStyle
;
637 dwStyle
= WS_TABSTOP
| WS_VISIBLE
| WS_CHILDWINDOW
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
638 LVS_SHAREIMAGELISTS
| LVS_EDITLABELS
| LVS_AUTOARRANGE
; // FIXME: Why is LVS_AUTOARRANGE here?
639 dwExStyle
= WS_EX_CLIENTEDGE
;
642 if (m_FolderSettings
.fFlags
& FWF_DESKTOP
)
644 m_FolderSettings
.fFlags
|= FWF_NOCLIENTEDGE
| FWF_NOSCROLL
;
645 dwStyle
|= LVS_ALIGNLEFT
;
649 dwStyle
|= LVS_SHOWSELALWAYS
; // MSDN says FWF_SHOWSELALWAYS is deprecated, always turn on for folders
650 dwStyle
|= (m_FolderSettings
.fFlags
& FWF_ALIGNLEFT
) ? LVS_ALIGNLEFT
: LVS_ALIGNTOP
;
651 ListExStyle
= LVS_EX_DOUBLEBUFFER
;
654 ViewMode
= m_FolderSettings
.ViewMode
;
655 hr
= _DoFolderViewCB(SFVM_DEFVIEWMODE
, 0, (LPARAM
)&ViewMode
);
658 if (ViewMode
>= FVM_FIRST
&& ViewMode
<= FVM_LAST
)
659 m_FolderSettings
.ViewMode
= ViewMode
;
661 ERR("Ignoring invalid ViewMode from SFVM_DEFVIEWMODE: %u (was: %u)\n", ViewMode
, m_FolderSettings
.ViewMode
);
664 switch (m_FolderSettings
.ViewMode
)
670 dwStyle
|= LVS_REPORT
;
673 dwStyle
|= LVS_SMALLICON
;
683 if (m_FolderSettings
.fFlags
& FWF_AUTOARRANGE
)
684 dwStyle
|= LVS_AUTOARRANGE
;
686 if (m_FolderSettings
.fFlags
& FWF_SNAPTOGRID
)
687 ListExStyle
|= LVS_EX_SNAPTOGRID
;
689 if (m_FolderSettings
.fFlags
& FWF_SINGLESEL
)
690 dwStyle
|= LVS_SINGLESEL
;
692 if (m_FolderSettings
.fFlags
& FWF_FULLROWSELECT
)
693 ListExStyle
|= LVS_EX_FULLROWSELECT
;
695 if (m_FolderSettings
.fFlags
& FWF_SINGLECLICKACTIVATE
)
696 ListExStyle
|= LVS_EX_TRACKSELECT
| LVS_EX_ONECLICKACTIVATE
;
698 if (m_FolderSettings
.fFlags
& FWF_NOCOLUMNHEADER
)
699 dwStyle
|= LVS_NOCOLUMNHEADER
;
702 // FIXME: Because this is a negative, everyone gets the new flag by default unless they
703 // opt out. This code should be enabled when shell looks like Vista instead of 2003
704 if (!(m_FolderSettings
.fFlags
& FWF_NOHEADERINALLVIEWS
))
705 ListExStyle
|= LVS_EX_HEADERINALLVIEWS
;
708 if (m_FolderSettings
.fFlags
& FWF_NOCLIENTEDGE
)
709 dwExStyle
&= ~WS_EX_CLIENTEDGE
;
711 RECT rcListView
= {0,0,0,0};
712 m_ListView
.Create(m_hWnd
, rcListView
, L
"FolderView", dwStyle
, dwExStyle
, ID_LISTVIEW
);
717 m_ListView
.SetExtendedListViewStyle(ListExStyle
);
719 m_sortInfo
.bIsAscending
= TRUE
;
720 m_sortInfo
.nHeaderID
= -1;
721 m_sortInfo
.nLastHeaderID
= -1;
723 /* UpdateShellSettings(); */
727 void CDefView::UpdateListColors()
729 if (m_FolderSettings
.fFlags
& FWF_DESKTOP
)
731 /* Check if drop shadows option is enabled */
732 BOOL bDropShadow
= FALSE
;
733 DWORD cbDropShadow
= sizeof(bDropShadow
);
736 * The desktop ListView always take the default desktop colours, by
737 * remaining transparent and letting user32/win32k paint itself the
738 * desktop background color, if any.
740 m_ListView
.SetBkColor(CLR_NONE
);
742 SHGetValueW(HKEY_CURRENT_USER
, L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
743 L
"ListviewShadow", NULL
, &bDropShadow
, &cbDropShadow
);
746 /* Set the icon background transparent */
747 m_ListView
.SetTextBkColor(CLR_NONE
);
748 m_ListView
.SetTextColor(RGB(255, 255, 255));
749 m_ListView
.SetExtendedListViewStyle(LVS_EX_TRANSPARENTSHADOWTEXT
, LVS_EX_TRANSPARENTSHADOWTEXT
);
753 /* Set the icon background as the same colour as the desktop */
754 COLORREF crDesktop
= GetSysColor(COLOR_DESKTOP
);
755 m_ListView
.SetTextBkColor(crDesktop
);
756 if (GetRValue(crDesktop
) + GetGValue(crDesktop
) + GetBValue(crDesktop
) > 128 * 3)
757 m_ListView
.SetTextColor(RGB(0, 0, 0));
759 m_ListView
.SetTextColor(RGB(255, 255, 255));
760 m_ListView
.SetExtendedListViewStyle(0, LVS_EX_TRANSPARENTSHADOWTEXT
);
765 // text background color
766 COLORREF clrTextBack
= m_viewinfo_data
.clrTextBack
;
767 m_ListView
.SetTextBkColor(clrTextBack
);
771 if (m_viewinfo_data
.clrText
!= CLR_INVALID
)
772 clrText
= m_viewinfo_data
.clrText
;
774 clrText
= GetSysColor(COLOR_WINDOWTEXT
);
776 m_ListView
.SetTextColor(clrText
);
778 // Background is painted by the parent via WM_PRINTCLIENT
779 m_ListView
.SetExtendedListViewStyle(LVS_EX_TRANSPARENTBKGND
, LVS_EX_TRANSPARENTBKGND
);
783 // adds all needed columns to the shellview
784 BOOL
CDefView::InitList()
788 HIMAGELIST big_icons
, small_icons
;
792 m_ListView
.DeleteAllItems();
794 m_hMenuArrangeModes
= CreateMenu();
798 for (int i
= 0; 1; i
++)
800 if (FAILED(m_pSF2Parent
->GetDetailsOf(NULL
, i
, &sd
)))
802 StrRetToStrNW( szTemp
, 50, &sd
.str
, NULL
);
803 m_ListView
.InsertColumn(i
, szTemp
, sd
.fmt
, sd
.cxChar
* 8);
805 InsertMenuW(m_hMenuArrangeModes
, -1, MF_STRING
, 0x30 + i
, szTemp
);
808 InsertMenuW(m_hMenuArrangeModes
, -1, MF_BYPOSITION
| MF_SEPARATOR
, 0, 0);
812 FIXME("no m_pSF2Parent\n");
815 Shell_GetImageLists(&big_icons
, &small_icons
);
816 m_ListView
.SetImageList(big_icons
, LVSIL_NORMAL
);
817 m_ListView
.SetImageList(small_icons
, LVSIL_SMALL
);
822 /*************************************************************************
823 * ShellView_ListViewCompareItems
825 * Compare Function for the Listview (FileOpen Dialog)
828 * lParam1 [I] the first ItemIdList to compare with
829 * lParam2 [I] the second ItemIdList to compare with
830 * lpData [I] The column ID for the header Ctrl to process
833 * A negative value if the first item should precede the second,
834 * a positive value if the first item should follow the second,
835 * or zero if the two items are equivalent
837 INT CALLBACK
CDefView::ListViewCompareItems(LPARAM lParam1
, LPARAM lParam2
, LPARAM lpData
)
839 PCUIDLIST_RELATIVE pidl1
= reinterpret_cast<PCUIDLIST_RELATIVE
>(lParam1
);
840 PCUIDLIST_RELATIVE pidl2
= reinterpret_cast<PCUIDLIST_RELATIVE
>(lParam2
);
841 CDefView
*pThis
= reinterpret_cast<CDefView
*>(lpData
);
843 HRESULT hres
= pThis
->m_pSFParent
->CompareIDs(pThis
->m_sortInfo
.nHeaderID
, pidl1
, pidl2
);
844 if (FAILED_UNEXPECTEDLY(hres
))
847 SHORT nDiff
= HRESULT_CODE(hres
);
848 if (!pThis
->m_sortInfo
.bIsAscending
)
853 BOOL
CDefView::_Sort()
858 if (m_ListView
.GetWindowLongPtr(GWL_STYLE
) & LVS_NOSORTHEADER
)
861 hHeader
= (HWND
)m_ListView
.SendMessage(LVM_GETHEADER
, 0, 0);
862 ZeroMemory(&hColumn
, sizeof(hColumn
));
864 // If the sorting column changed, remove sorting style from the old column
865 if ( (m_sortInfo
.nLastHeaderID
!= -1) &&
866 (m_sortInfo
.nLastHeaderID
!= m_sortInfo
.nHeaderID
) )
868 hColumn
.mask
= HDI_FORMAT
;
869 Header_GetItem(hHeader
, m_sortInfo
.nLastHeaderID
, &hColumn
);
870 hColumn
.fmt
&= ~(HDF_SORTUP
| HDF_SORTDOWN
);
871 Header_SetItem(hHeader
, m_sortInfo
.nLastHeaderID
, &hColumn
);
874 /* Set the sorting style to the new column */
875 hColumn
.mask
= HDI_FORMAT
;
876 Header_GetItem(hHeader
, m_sortInfo
.nHeaderID
, &hColumn
);
878 hColumn
.fmt
&= (m_sortInfo
.bIsAscending
? ~HDF_SORTDOWN
: ~HDF_SORTUP
);
879 hColumn
.fmt
|= (m_sortInfo
.bIsAscending
? HDF_SORTUP
: HDF_SORTDOWN
);
880 Header_SetItem(hHeader
, m_sortInfo
.nHeaderID
, &hColumn
);
882 /* Sort the list, using the current values of nHeaderID and bIsAscending */
883 m_sortInfo
.nLastHeaderID
= m_sortInfo
.nHeaderID
;
884 return m_ListView
.SortItems(ListViewCompareItems
, this);
887 PCUITEMID_CHILD
CDefView::_PidlByItem(int i
)
891 return reinterpret_cast<PCUITEMID_CHILD
>(m_ListView
.GetItemData(i
));
894 PCUITEMID_CHILD
CDefView::_PidlByItem(LVITEM
& lvItem
)
898 return reinterpret_cast<PCUITEMID_CHILD
>(lvItem
.lParam
);
901 int CDefView::LV_FindItemByPidl(PCUITEMID_CHILD pidl
)
905 int cItems
= m_ListView
.GetItemCount();
907 for (int i
= 0; i
<cItems
; i
++)
909 PCUITEMID_CHILD currentpidl
= _PidlByItem(i
);
910 if (ILIsEqual(pidl
, currentpidl
))
916 int CDefView::LV_AddItem(PCUITEMID_CHILD pidl
)
920 TRACE("(%p)(pidl=%p)\n", this, pidl
);
924 if (_DoFolderViewCB(SFVM_ADDINGOBJECT
, 0, (LPARAM
)pidl
) == S_FALSE
)
927 lvItem
.mask
= LVIF_TEXT
| LVIF_IMAGE
| LVIF_PARAM
; // set mask
928 lvItem
.iItem
= m_ListView
.GetItemCount(); // add item to lists end
930 lvItem
.lParam
= reinterpret_cast<LPARAM
>(ILClone(pidl
)); // set item's data
931 lvItem
.pszText
= LPSTR_TEXTCALLBACKW
; // get text on a callback basis
932 lvItem
.iImage
= I_IMAGECALLBACK
; // get image on a callback basis
933 lvItem
.stateMask
= LVIS_CUT
;
935 return m_ListView
.InsertItem(&lvItem
);
938 BOOLEAN
CDefView::LV_DeleteItem(PCUITEMID_CHILD pidl
)
942 TRACE("(%p)(pidl=%p)\n", this, pidl
);
946 nIndex
= LV_FindItemByPidl(pidl
);
950 return m_ListView
.DeleteItem(nIndex
);
953 BOOLEAN
CDefView::LV_RenameItem(PCUITEMID_CHILD pidlOld
, PCUITEMID_CHILD pidlNew
)
958 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", this, pidlOld
, pidlNew
);
962 nItem
= LV_FindItemByPidl(pidlOld
);
966 lvItem
.mask
= LVIF_PARAM
; // only the pidl
967 lvItem
.iItem
= nItem
;
969 m_ListView
.GetItem(&lvItem
);
971 // Store old pidl until new item is replaced
972 LPVOID oldPidl
= reinterpret_cast<LPVOID
>(lvItem
.lParam
);
974 lvItem
.mask
= LVIF_PARAM
| LVIF_IMAGE
| LVIF_TEXT
;
975 lvItem
.iItem
= nItem
;
977 lvItem
.lParam
= reinterpret_cast<LPARAM
>(ILClone(pidlNew
)); // set item's data
978 lvItem
.pszText
= LPSTR_TEXTCALLBACKW
;
979 lvItem
.iImage
= SHMapPIDLToSystemImageListIndex(m_pSFParent
, pidlNew
, 0);
980 m_ListView
.SetItem(&lvItem
);
981 m_ListView
.Update(nItem
);
983 // Now that the new item is in place, we can safely release the old pidl
986 return TRUE
; // FIXME: better handling
992 BOOLEAN
CDefView::LV_ProdItem(PCUITEMID_CHILD pidl
)
997 TRACE("(%p)(pidl=%p)\n", this, pidl
);
1001 nItem
= LV_FindItemByPidl(pidl
);
1005 lvItem
.mask
= LVIF_IMAGE
;
1006 lvItem
.iItem
= nItem
;
1007 lvItem
.iSubItem
= 0;
1008 lvItem
.iImage
= SHMapPIDLToSystemImageListIndex(m_pSFParent
, pidl
, 0);
1009 m_ListView
.SetItem(&lvItem
);
1010 m_ListView
.Update(nItem
);
1017 INT CALLBACK
CDefView::fill_list(LPVOID ptr
, LPVOID arg
)
1019 PITEMID_CHILD pidl
= static_cast<PITEMID_CHILD
>(ptr
);
1020 CDefView
*pThis
= static_cast<CDefView
*>(arg
);
1022 // in a commdlg this works as a filemask
1023 if (pThis
->IncludeObject(pidl
) == S_OK
&& pThis
->m_ListView
)
1024 pThis
->LV_AddItem(pidl
);
1031 // - gets the objectlist from the shellfolder
1033 // - fills the list into the view
1034 HRESULT
CDefView::FillList()
1036 CComPtr
<IEnumIDList
> pEnumIDList
;
1041 DWORD dFlags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
;
1042 DWORD dwValue
, cbValue
;
1044 TRACE("%p\n", this);
1046 // determine if there is a setting to show all the hidden files/folders
1048 cbValue
= sizeof(dwValue
);
1049 SHGetValueW(HKEY_CURRENT_USER
,
1050 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
1051 L
"Hidden", NULL
, &dwValue
, &cbValue
);
1054 dFlags
|= SHCONTF_INCLUDEHIDDEN
;
1055 m_ListView
.SendMessageW(LVM_SETCALLBACKMASK
, LVIS_CUT
, 0);
1059 cbValue
= sizeof(dwValue
);
1060 SHGetValueW(HKEY_CURRENT_USER
,
1061 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
1062 L
"ShowSuperHidden", NULL
, &dwValue
, &cbValue
);
1065 dFlags
|= SHCONTF_INCLUDESUPERHIDDEN
;
1066 m_ListView
.SendMessageW(LVM_SETCALLBACKMASK
, LVIS_CUT
, 0);
1069 // get the itemlist from the shfolder
1070 hRes
= m_pSFParent
->EnumObjects(m_hWnd
, dFlags
, &pEnumIDList
);
1073 if (hRes
== S_FALSE
)
1078 // create a pointer array
1079 hdpa
= DPA_Create(16);
1081 return(E_OUTOFMEMORY
);
1083 // copy the items into the array
1084 while((S_OK
== pEnumIDList
->Next(1, &pidl
, &dwFetched
)) && dwFetched
)
1086 if (DPA_InsertPtr(hdpa
, 0x7fff, pidl
) == -1)
1092 // turn listview's redrawing off
1093 m_ListView
.SetRedraw(FALSE
);
1095 DPA_DestroyCallback( hdpa
, fill_list
, this);
1097 /* sort the array */
1100 m_pSF2Parent
->GetDefaultColumn(NULL
, (ULONG
*)&m_sortInfo
.nHeaderID
, NULL
);
1104 FIXME("no m_pSF2Parent\n");
1106 m_sortInfo
.bIsAscending
= TRUE
;
1109 if (m_viewinfo_data
.hbmBack
)
1111 ::DeleteObject(m_viewinfo_data
.hbmBack
);
1112 m_viewinfo_data
.hbmBack
= NULL
;
1115 // load custom background image and custom text color
1116 m_viewinfo_data
.cbSize
= sizeof(m_viewinfo_data
);
1117 _DoFolderViewCB(SFVM_GET_CUSTOMVIEWINFO
, 0, (LPARAM
)&m_viewinfo_data
);
1119 // turn listview's redrawing back on and force it to draw
1120 m_ListView
.SetRedraw(TRUE
);
1124 if (!(m_FolderSettings
.fFlags
& FWF_DESKTOP
))
1127 m_ListView
.InvalidateRect(NULL
, TRUE
);
1130 _DoFolderViewCB(SFVM_LISTREFRESHED
, 0, 0);
1135 LRESULT
CDefView::OnShowWindow(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1137 if (m_ListView
.IsWindow())
1138 m_ListView
.UpdateWindow();
1143 LRESULT
CDefView::OnGetDlgCode(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1145 return m_ListView
.SendMessageW(uMsg
, 0, 0);
1148 LRESULT
CDefView::OnDestroy(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1155 DestroyMenu(m_hMenu
);
1158 RevokeDragDrop(m_hWnd
);
1159 SHChangeNotifyDeregister(m_hNotify
);
1161 SHFree(m_pidlParent
);
1162 m_pidlParent
= NULL
;
1168 LRESULT
CDefView::OnEraseBackground(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1170 /* redirect to parent */
1171 if (m_FolderSettings
.fFlags
& (FWF_DESKTOP
| FWF_TRANSPARENT
))
1172 return SendMessageW(GetParent(), WM_ERASEBKGND
, wParam
, lParam
);
1179 DrawTileBitmap(HDC hDC
, LPCRECT prc
, HBITMAP hbm
, INT nWidth
, INT nHeight
, INT dx
, INT dy
)
1181 INT x0
= prc
->left
, y0
= prc
->top
, x1
= prc
->right
, y1
= prc
->bottom
;
1185 HDC hMemDC
= CreateCompatibleDC(hDC
);
1186 HGDIOBJ hbmOld
= SelectObject(hMemDC
, hbm
);
1188 for (INT y
= y0
; y
< y1
; y
+= nHeight
)
1190 for (INT x
= x0
; x
< x1
; x
+= nWidth
)
1192 BitBlt(hDC
, x
, y
, nWidth
, nHeight
, hMemDC
, 0, 0, SRCCOPY
);
1196 SelectObject(hMemDC
, hbmOld
);
1200 LRESULT
CDefView::OnPrintClient(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1202 HDC hDC
= (HDC
)wParam
;
1205 ::GetClientRect(m_ListView
, &rc
);
1207 if (m_viewinfo_data
.hbmBack
)
1210 if (::GetObject(m_viewinfo_data
.hbmBack
, sizeof(BITMAP
), &bm
))
1212 INT dx
= -(::GetScrollPos(m_ListView
, SB_HORZ
) % bm
.bmWidth
);
1213 INT dy
= -(::GetScrollPos(m_ListView
, SB_VERT
) % bm
.bmHeight
);
1214 DrawTileBitmap(hDC
, &rc
, m_viewinfo_data
.hbmBack
, bm
.bmWidth
, bm
.bmHeight
, dx
, dy
);
1219 FillRect(hDC
, &rc
, GetSysColorBrush(COLOR_WINDOW
));
1227 LRESULT
CDefView::OnSysColorChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1229 /* Update desktop labels color */
1232 /* Forward WM_SYSCOLORCHANGE to common controls */
1233 return m_ListView
.SendMessageW(uMsg
, 0, 0);
1236 LRESULT
CDefView::OnGetShellBrowser(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1238 return reinterpret_cast<LRESULT
>(m_pShellBrowser
.p
);
1241 LRESULT
CDefView::OnNCCreate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1248 VOID
CDefView::OnFinalMessage(HWND
)
1253 LRESULT
CDefView::OnCreate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1255 CComPtr
<IDropTarget
> pdt
;
1256 CComPtr
<IPersistFolder2
> ppf2
;
1258 TRACE("%p\n", this);
1260 if (SUCCEEDED(QueryInterface(IID_PPV_ARG(IDropTarget
, &pdt
))))
1262 if (FAILED(RegisterDragDrop(m_hWnd
, pdt
)))
1263 ERR("Error Registering DragDrop\n");
1266 /* register for receiving notifications */
1267 m_pSFParent
->QueryInterface(IID_PPV_ARG(IPersistFolder2
, &ppf2
));
1270 ppf2
->GetCurFolder(&m_pidlParent
);
1281 if (m_FolderSettings
.fFlags
& FWF_DESKTOP
)
1284 m_pShellBrowser
->GetWindow(&hwndSB
);
1285 SetShellWindowEx(hwndSB
, m_ListView
);
1288 SHChangeNotifyEntry ntreg
[1];
1289 ntreg
[0].fRecursive
= FALSE
;
1290 ntreg
[0].pidl
= m_pidlParent
;
1291 m_hNotify
= SHChangeNotifyRegister(m_hWnd
,
1292 SHCNRF_InterruptLevel
| SHCNRF_ShellLevel
|
1294 SHCNE_ALLEVENTS
, SHV_CHANGE_NOTIFY
,
1297 //_DoFolderViewCB(SFVM_GETNOTIFY, ?? ??)
1299 m_hAccel
= LoadAcceleratorsW(shell32_hInstance
, MAKEINTRESOURCEW(IDA_SHELLVIEW
));
1301 BOOL bPreviousParentSpecial
= m_isParentFolderSpecial
;
1303 // A folder is special if it is the Desktop folder,
1304 // a network folder, or a Control Panel folder
1305 m_isParentFolderSpecial
= _ILIsDesktop(m_pidlParent
) || _ILIsNetHood(m_pidlParent
)
1306 || _ILIsControlPanel(ILFindLastID(m_pidlParent
));
1308 // Only force StatusBar part refresh if the state
1309 // changed from the previous folder
1310 if (bPreviousParentSpecial
!= m_isParentFolderSpecial
)
1312 // This handles changing StatusBar parts
1313 _ForceStatusBarResize();
1321 // #### Handling of the menus ####
1323 extern "C" DWORD WINAPI
SHMenuIndexFromID(HMENU hMenu
, UINT uID
);
1325 HMENU
GetSubmenuByID(HMENU hmenu
, UINT id
)
1327 MENUITEMINFOW mii
= {sizeof(mii
), MIIM_SUBMENU
};
1328 if (::GetMenuItemInfoW(hmenu
, id
, FALSE
, &mii
))
1329 return mii
.hSubMenu
;
1334 // ReallyGetMenuItemID returns the id of an item even if it opens a submenu,
1335 // GetMenuItemID returns -1 if the specified item opens a submenu
1336 UINT
ReallyGetMenuItemID(HMENU hmenu
, int i
)
1338 MENUITEMINFOW mii
= {sizeof(mii
), MIIM_ID
};
1339 if (::GetMenuItemInfoW(hmenu
, i
, TRUE
, &mii
))
1345 HRESULT
CDefView::FillFileMenu()
1347 HMENU hFileMenu
= GetSubmenuByID(m_hMenu
, FCIDM_MENU_FILE
);
1351 /* Cleanup the items added previously */
1352 for (int i
= GetMenuItemCount(hFileMenu
) - 1; i
>= 0; i
--)
1354 UINT id
= GetMenuItemID(hFileMenu
, i
);
1355 if (id
< FCIDM_BROWSERFIRST
|| id
> FCIDM_BROWSERLAST
)
1356 DeleteMenu(hFileMenu
, i
, MF_BYPOSITION
);
1359 // In case we still have this left over, clean it up
1362 IUnknown_SetSite(m_pFileMenu
, NULL
);
1363 m_pFileMenu
.Release();
1365 // Store context menu in m_pFileMenu and keep it to invoke the selected command later on
1366 HRESULT hr
= GetItemObject(SVGIO_SELECTION
, IID_PPV_ARG(IContextMenu
, &m_pFileMenu
));
1367 if (FAILED_UNEXPECTEDLY(hr
))
1370 HMENU hmenu
= CreatePopupMenu();
1372 hr
= m_pFileMenu
->QueryContextMenu(hmenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, 0);
1373 if (FAILED_UNEXPECTEDLY(hr
))
1376 // TODO: filter or something
1378 Shell_MergeMenus(hFileMenu
, hmenu
, 0, 0, 0xFFFF, MM_ADDSEPARATOR
| MM_SUBMENUSHAVEIDS
);
1380 ::DestroyMenu(hmenu
);
1385 HRESULT
CDefView::FillEditMenu()
1387 HMENU hEditMenu
= GetSubmenuByID(m_hMenu
, FCIDM_MENU_EDIT
);
1391 HMENU hmenuContents
= ::LoadMenuW(shell32_hInstance
, L
"MENU_003");
1395 Shell_MergeMenus(hEditMenu
, hmenuContents
, 0, 0, 0xFFFF, 0);
1397 ::DestroyMenu(hmenuContents
);
1402 HRESULT
CDefView::FillViewMenu()
1404 HMENU hViewMenu
= GetSubmenuByID(m_hMenu
, FCIDM_MENU_VIEW
);
1408 m_hMenuViewModes
= ::LoadMenuW(shell32_hInstance
, L
"MENU_001");
1409 if (!m_hMenuViewModes
)
1412 UINT i
= SHMenuIndexFromID(hViewMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
);
1413 Shell_MergeMenus(hViewMenu
, m_hMenuViewModes
, i
, 0, 0xFFFF, MM_ADDSEPARATOR
| MM_DONTREMOVESEPS
| MM_SUBMENUSHAVEIDS
);
1418 HRESULT
CDefView::FillArrangeAsMenu(HMENU hmenuArrange
)
1420 /* We only need to fill this once */
1421 if (GetMenuItemID(hmenuArrange
, 0) == FCIDM_SHVIEW_AUTOARRANGE
)
1423 Shell_MergeMenus(hmenuArrange
, m_hMenuArrangeModes
, 0, 0, 0xFFFF,0);
1426 /* Also check the menu item according to which we sort */
1427 CheckMenuRadioItem(hmenuArrange
,
1430 m_sortInfo
.nHeaderID
+ 0x30,
1433 if (m_FolderSettings
.ViewMode
== FVM_DETAILS
|| m_FolderSettings
.ViewMode
== FVM_LIST
)
1435 EnableMenuItem(hmenuArrange
, FCIDM_SHVIEW_AUTOARRANGE
, MF_BYCOMMAND
| MF_GRAYED
);
1436 EnableMenuItem(hmenuArrange
, FCIDM_SHVIEW_ALIGNTOGRID
, MF_BYCOMMAND
| MF_GRAYED
);
1440 EnableMenuItem(hmenuArrange
, FCIDM_SHVIEW_AUTOARRANGE
, MF_BYCOMMAND
);
1441 EnableMenuItem(hmenuArrange
, FCIDM_SHVIEW_ALIGNTOGRID
, MF_BYCOMMAND
);
1443 if (GetAutoArrange() == S_OK
)
1444 CheckMenuItem(hmenuArrange
, FCIDM_SHVIEW_AUTOARRANGE
, MF_CHECKED
);
1446 CheckMenuItem(hmenuArrange
, FCIDM_SHVIEW_AUTOARRANGE
, MF_UNCHECKED
);
1448 if (_GetSnapToGrid() == S_OK
)
1449 CheckMenuItem(hmenuArrange
, FCIDM_SHVIEW_ALIGNTOGRID
, MF_CHECKED
);
1451 CheckMenuItem(hmenuArrange
, FCIDM_SHVIEW_ALIGNTOGRID
, MF_UNCHECKED
);
1457 HRESULT
CDefView::CheckViewMode(HMENU hmenuView
)
1459 if (m_FolderSettings
.ViewMode
>= FVM_FIRST
&& m_FolderSettings
.ViewMode
<= FVM_LAST
)
1461 UINT iItemFirst
= FCIDM_SHVIEW_BIGICON
;
1462 UINT iItemLast
= iItemFirst
+ FVM_LAST
- FVM_FIRST
;
1463 UINT iItem
= iItemFirst
+ m_FolderSettings
.ViewMode
- FVM_FIRST
;
1464 CheckMenuRadioItem(hmenuView
, iItemFirst
, iItemLast
, iItem
, MF_BYCOMMAND
);
1471 // - fills the m_apidl list with the selected objects
1474 // number of selected items
1475 UINT
CDefView::GetSelections()
1479 m_cidl
= m_ListView
.GetSelectedCount();
1480 m_apidl
= static_cast<PCUITEMID_CHILD
*>(SHAlloc(m_cidl
* sizeof(PCUITEMID_CHILD
)));
1487 TRACE("-- Items selected =%u\n", m_cidl
);
1493 while ((lvIndex
= m_ListView
.GetNextItem(lvIndex
, LVNI_SELECTED
)) > -1)
1495 m_apidl
[i
] = _PidlByItem(lvIndex
);
1499 TRACE("-- selected Item found\n");
1505 HRESULT
CDefView::InvokeContextMenuCommand(CComPtr
<IContextMenu
>& pCM
, LPCSTR lpVerb
, POINT
* pt
)
1507 CMINVOKECOMMANDINFOEX cmi
;
1509 ZeroMemory(&cmi
, sizeof(cmi
));
1510 cmi
.cbSize
= sizeof(cmi
);
1512 cmi
.lpVerb
= lpVerb
;
1514 if (GetKeyState(VK_SHIFT
) & 0x8000)
1515 cmi
.fMask
|= CMIC_MASK_SHIFT_DOWN
;
1517 if (GetKeyState(VK_CONTROL
) & 0x8000)
1518 cmi
.fMask
|= CMIC_MASK_CONTROL_DOWN
;
1522 cmi
.fMask
|= CMIC_MASK_PTINVOKE
;
1526 HRESULT hr
= pCM
->InvokeCommand((LPCMINVOKECOMMANDINFO
)&cmi
);
1527 // Most of our callers will do this, but if they would forget (File menu!)
1528 IUnknown_SetSite(pCM
, NULL
);
1531 if (FAILED_UNEXPECTEDLY(hr
))
1537 HRESULT
CDefView::OpenSelectedItems()
1543 m_cidl
= m_ListView
.GetSelectedCount();
1547 hResult
= OnDefaultCommand();
1548 if (hResult
== S_OK
)
1551 hMenu
= CreatePopupMenu();
1555 CComPtr
<IContextMenu
> pCM
;
1556 hResult
= GetItemObject(SVGIO_SELECTION
, IID_PPV_ARG(IContextMenu
, &pCM
));
1557 MenuCleanup
_(pCM
, hMenu
);
1558 if (FAILED_UNEXPECTEDLY(hResult
))
1561 hResult
= pCM
->QueryContextMenu(hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, CMF_DEFAULTONLY
);
1562 if (FAILED_UNEXPECTEDLY(hResult
))
1565 uCommand
= GetMenuDefaultItem(hMenu
, FALSE
, 0);
1566 if (uCommand
== (UINT
)-1)
1568 ERR("GetMenuDefaultItem returned -1\n");
1572 InvokeContextMenuCommand(pCM
, MAKEINTRESOURCEA(uCommand
), NULL
);
1577 LRESULT
CDefView::OnContextMenu(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1583 TRACE("(%p)\n", this);
1585 if (m_hContextMenu
!= NULL
)
1587 ERR("HACK: Aborting context menu in nested call\n");
1591 m_hContextMenu
= CreatePopupMenu();
1592 if (!m_hContextMenu
)
1595 if (lParam
!= ~0) // unless app key (menu key) was pressed
1597 pt
.x
= GET_X_LPARAM(lParam
);
1598 pt
.y
= GET_Y_LPARAM(lParam
);
1600 LV_HITTESTINFO hittest
= { pt
};
1601 ScreenToClient(&hittest
.pt
);
1602 m_ListView
.HitTest(&hittest
);
1604 // Right-Clicked item is selected? If selected, no selection change.
1605 // If not selected, then reset the selection and select the item.
1606 if ((hittest
.flags
& LVHT_ONITEM
) &&
1607 m_ListView
.GetItemState(hittest
.iItem
, LVIS_SELECTED
) != LVIS_SELECTED
)
1609 SelectItem(hittest
.iItem
, SVSI_SELECT
| SVSI_DESELECTOTHERS
| SVSI_ENSUREVISIBLE
);
1613 m_cidl
= m_ListView
.GetSelectedCount();
1614 // In case we still have this left over, clean it up
1615 hResult
= GetItemObject(m_cidl
? SVGIO_SELECTION
: SVGIO_BACKGROUND
, IID_PPV_ARG(IContextMenu
, &m_pCM
));
1616 MenuCleanup
_(m_pCM
, m_hContextMenu
);
1617 if (FAILED_UNEXPECTEDLY(hResult
))
1620 // Use 1 as the first id we want. 0 means that user canceled the menu
1621 hResult
= m_pCM
->QueryContextMenu(m_hContextMenu
, 0, CONTEXT_MENU_BASE_ID
, FCIDM_SHVIEWLAST
, CMF_NORMAL
);
1622 if (FAILED_UNEXPECTEDLY(hResult
))
1625 // There is no position requested, so try to find one
1628 HWND hFocus
= ::GetFocus();
1631 if (hFocus
== m_ListView
.m_hWnd
|| m_ListView
.IsChild(hFocus
))
1633 // Is there an item focused and selected?
1634 lvIndex
= m_ListView
.GetNextItem(-1, LVIS_SELECTED
|LVIS_FOCUSED
);
1635 // If not, find the first selected item
1637 lvIndex
= m_ListView
.GetNextItem(-1, LVIS_SELECTED
);
1643 // Find the center of the icon
1644 RECT rc
= { LVIR_ICON
};
1645 m_ListView
.SendMessage(LVM_GETITEMRECT
, lvIndex
, (LPARAM
)&rc
);
1646 pt
.x
= (rc
.right
+ rc
.left
) / 2;
1647 pt
.y
= (rc
.bottom
+ rc
.top
) / 2;
1651 // We have to drop it somewhere
1655 m_ListView
.ClientToScreen(&pt
);
1658 // This runs the message loop, calling back to us with f.e. WM_INITPOPUP (hence why m_hContextMenu and m_pCM exist)
1659 uCommand
= TrackPopupMenu(m_hContextMenu
,
1660 TPM_LEFTALIGN
| TPM_RETURNCMD
| TPM_LEFTBUTTON
| TPM_RIGHTBUTTON
,
1661 pt
.x
, pt
.y
, 0, m_hWnd
, NULL
);
1665 if (uCommand
== FCIDM_SHVIEW_OPEN
&& OnDefaultCommand() == S_OK
)
1668 InvokeContextMenuCommand(m_pCM
, MAKEINTRESOURCEA(uCommand
- CONTEXT_MENU_BASE_ID
), &pt
);
1673 LRESULT
CDefView::OnExplorerCommand(UINT uCommand
, BOOL bUseSelection
)
1678 CComPtr
<IContextMenu
> pCM
;
1679 hResult
= GetItemObject(bUseSelection
? SVGIO_SELECTION
: SVGIO_BACKGROUND
, IID_PPV_ARG(IContextMenu
, &pCM
));
1680 if (FAILED_UNEXPECTEDLY(hResult
))
1683 MenuCleanup
_(pCM
, hMenu
);
1685 if ((uCommand
!= FCIDM_SHVIEW_DELETE
) && (uCommand
!= FCIDM_SHVIEW_RENAME
))
1687 hMenu
= CreatePopupMenu();
1691 hResult
= pCM
->QueryContextMenu(hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, CMF_NORMAL
);
1692 if (FAILED_UNEXPECTEDLY(hResult
))
1698 // FIXME: we should cache this
1699 SFGAOF rfg
= SFGAO_BROWSABLE
| SFGAO_CANCOPY
| SFGAO_CANLINK
| SFGAO_CANMOVE
| SFGAO_CANDELETE
| SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
;
1700 hResult
= m_pSFParent
->GetAttributesOf(m_cidl
, m_apidl
, &rfg
);
1701 if (FAILED_UNEXPECTEDLY(hResult
))
1704 if (!(rfg
& SFGAO_CANMOVE
) && uCommand
== FCIDM_SHVIEW_CUT
)
1706 if (!(rfg
& SFGAO_CANCOPY
) && uCommand
== FCIDM_SHVIEW_COPY
)
1708 if (!(rfg
& SFGAO_CANDELETE
) && uCommand
== FCIDM_SHVIEW_DELETE
)
1710 if (!(rfg
& SFGAO_CANRENAME
) && uCommand
== FCIDM_SHVIEW_RENAME
)
1712 if (!(rfg
& SFGAO_HASPROPSHEET
) && uCommand
== FCIDM_SHVIEW_PROPERTIES
)
1716 // FIXME: We should probably use the objects position?
1717 InvokeContextMenuCommand(pCM
, MAKEINTRESOURCEA(uCommand
), NULL
);
1721 // ##### message handling #####
1723 LRESULT
CDefView::OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1725 WORD wWidth
, wHeight
;
1727 wWidth
= LOWORD(lParam
);
1728 wHeight
= HIWORD(lParam
);
1730 TRACE("%p width=%u height=%u\n", this, wWidth
, wHeight
);
1732 // WM_SIZE can come before WM_CREATE
1736 /* Resize the ListView to fit our window */
1737 ::MoveWindow(m_ListView
, 0, 0, wWidth
, wHeight
, TRUE
);
1739 _DoFolderViewCB(SFVM_SIZE
, 0, 0);
1741 _ForceStatusBarResize();
1748 void CDefView::OnDeactivate()
1750 TRACE("%p\n", this);
1752 if (m_uState
!= SVUIA_DEACTIVATE
)
1754 // TODO: cleanup menu after deactivation
1755 m_uState
= SVUIA_DEACTIVATE
;
1759 void CDefView::DoActivate(UINT uState
)
1761 TRACE("%p uState=%x\n", this, uState
);
1763 // don't do anything if the state isn't really changing
1764 if (m_uState
== uState
)
1769 if (uState
== SVUIA_DEACTIVATE
)
1775 if(m_hMenu
&& !m_bmenuBarInitialized
)
1779 m_pShellBrowser
->SetMenuSB(m_hMenu
, 0, m_hWnd
);
1780 m_bmenuBarInitialized
= TRUE
;
1783 if (SVUIA_ACTIVATE_FOCUS
== uState
)
1785 m_ListView
.SetFocus();
1793 void CDefView::_DoCopyToMoveToFolder(BOOL bCopy
)
1795 if (!GetSelections())
1798 SFGAOF rfg
= SFGAO_CANCOPY
| SFGAO_CANMOVE
| SFGAO_FILESYSTEM
;
1799 HRESULT hr
= m_pSFParent
->GetAttributesOf(m_cidl
, m_apidl
, &rfg
);
1800 if (FAILED_UNEXPECTEDLY(hr
))
1803 if (!bCopy
&& !(rfg
& SFGAO_CANMOVE
))
1805 if (bCopy
&& !(rfg
& SFGAO_CANCOPY
))
1808 CComPtr
<IContextMenu
> pCM
;
1809 hr
= m_pSFParent
->GetUIObjectOf(m_hWnd
, m_cidl
, m_apidl
, IID_IContextMenu
, 0, (void **)&pCM
);
1810 if (FAILED_UNEXPECTEDLY(hr
))
1813 InvokeContextMenuCommand(pCM
, (bCopy
? "copyto" : "moveto"), NULL
);
1816 LRESULT
CDefView::OnActivate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1818 DoActivate(SVUIA_ACTIVATE_FOCUS
);
1822 LRESULT
CDefView::OnSetFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1824 TRACE("%p\n", this);
1826 /* Tell the browser one of our windows has received the focus. This
1827 should always be done before merging menus (OnActivate merges the
1828 menus) if one of our windows has the focus.*/
1830 m_pShellBrowser
->OnViewWindowActive(this);
1831 DoActivate(SVUIA_ACTIVATE_FOCUS
);
1833 /* Set the focus to the listview */
1834 m_ListView
.SetFocus();
1836 /* Notify the ICommDlgBrowser interface */
1837 OnStateChange(CDBOSC_SETFOCUS
);
1842 LRESULT
CDefView::OnKillFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1844 TRACE("(%p) stub\n", this);
1846 DoActivate(SVUIA_ACTIVATE_NOFOCUS
);
1847 /* Notify the ICommDlgBrowser */
1848 OnStateChange(CDBOSC_KILLFOCUS
);
1853 // the CmdID's are the ones from the context menu
1854 LRESULT
CDefView::OnCommand(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1861 dwCmdID
= GET_WM_COMMAND_ID(wParam
, lParam
);
1862 dwCmd
= GET_WM_COMMAND_CMD(wParam
, lParam
);
1863 hwndCmd
= GET_WM_COMMAND_HWND(wParam
, lParam
);
1865 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n", this, dwCmdID
, dwCmd
, hwndCmd
);
1869 case FCIDM_SHVIEW_SMALLICON
:
1870 m_FolderSettings
.ViewMode
= FVM_SMALLICON
;
1871 m_ListView
.ModifyStyle(LVS_TYPEMASK
, LVS_SMALLICON
);
1874 case FCIDM_SHVIEW_BIGICON
:
1875 m_FolderSettings
.ViewMode
= FVM_ICON
;
1876 m_ListView
.ModifyStyle(LVS_TYPEMASK
, LVS_ICON
);
1879 case FCIDM_SHVIEW_LISTVIEW
:
1880 m_FolderSettings
.ViewMode
= FVM_LIST
;
1881 m_ListView
.ModifyStyle(LVS_TYPEMASK
, LVS_LIST
);
1884 case FCIDM_SHVIEW_REPORTVIEW
:
1885 m_FolderSettings
.ViewMode
= FVM_DETAILS
;
1886 m_ListView
.ModifyStyle(LVS_TYPEMASK
, LVS_REPORT
);
1889 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1894 m_sortInfo
.nHeaderID
= dwCmdID
- 0x30;
1895 m_sortInfo
.bIsAscending
= TRUE
;
1898 case FCIDM_SHVIEW_SNAPTOGRID
:
1899 m_ListView
.Arrange(LVA_SNAPTOGRID
);
1901 case FCIDM_SHVIEW_ALIGNTOGRID
:
1902 if (_GetSnapToGrid() == S_OK
)
1903 m_ListView
.SetExtendedListViewStyle(0, LVS_EX_SNAPTOGRID
);
1907 case FCIDM_SHVIEW_AUTOARRANGE
:
1908 if (GetAutoArrange() == S_OK
)
1909 m_ListView
.ModifyStyle(LVS_AUTOARRANGE
, 0);
1913 case FCIDM_SHVIEW_SELECTALL
:
1914 m_ListView
.SetItemState(-1, LVIS_SELECTED
, LVIS_SELECTED
);
1916 case FCIDM_SHVIEW_INVERTSELECTION
:
1917 nCount
= m_ListView
.GetItemCount();
1918 for (int i
=0; i
< nCount
; i
++)
1919 m_ListView
.SetItemState(i
, m_ListView
.GetItemState(i
, LVIS_SELECTED
) ? 0 : LVIS_SELECTED
, LVIS_SELECTED
);
1921 case FCIDM_SHVIEW_REFRESH
:
1924 case FCIDM_SHVIEW_DELETE
:
1925 case FCIDM_SHVIEW_CUT
:
1926 case FCIDM_SHVIEW_COPY
:
1927 case FCIDM_SHVIEW_RENAME
:
1928 case FCIDM_SHVIEW_PROPERTIES
:
1929 if (SHRestricted(REST_NOVIEWCONTEXTMENU
))
1931 return OnExplorerCommand(dwCmdID
, TRUE
);
1932 case FCIDM_SHVIEW_COPYTO
:
1933 case FCIDM_SHVIEW_MOVETO
:
1934 _DoCopyToMoveToFolder(dwCmdID
== FCIDM_SHVIEW_COPYTO
);
1936 case FCIDM_SHVIEW_INSERT
:
1937 case FCIDM_SHVIEW_UNDO
:
1938 case FCIDM_SHVIEW_INSERTLINK
:
1939 case FCIDM_SHVIEW_NEWFOLDER
:
1940 return OnExplorerCommand(dwCmdID
, FALSE
);
1942 // WM_COMMAND messages from file menu are routed to CDefView to let m_pFileMenu handle them
1943 if (m_pFileMenu
&& dwCmd
== 0)
1946 MenuCleanup
_(m_pFileMenu
, Dummy
);
1947 InvokeContextMenuCommand(m_pFileMenu
, MAKEINTRESOURCEA(dwCmdID
), NULL
);
1955 SelectExtOnRename(void)
1959 DWORD dwValue
= FALSE
, cbValue
;
1961 error
= RegOpenKeyExW(HKEY_CURRENT_USER
,
1962 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer",
1963 0, KEY_READ
, &hKey
);
1967 cbValue
= sizeof(dwValue
);
1968 RegQueryValueExW(hKey
, L
"SelectExtOnRename", NULL
, NULL
, (LPBYTE
)&dwValue
, &cbValue
);
1974 LRESULT
CDefView::OnNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1978 LPNMLISTVIEW lpnmlv
;
1979 NMLVDISPINFOW
*lpdi
;
1980 PCUITEMID_CHILD pidl
;
1984 lpnmh
= (LPNMHDR
)lParam
;
1985 lpnmlv
= (LPNMLISTVIEW
)lpnmh
;
1986 lpdi
= (NMLVDISPINFOW
*)lpnmh
;
1988 TRACE("%p CtlID=%u lpnmh->code=%x\n", this, CtlID
, lpnmh
->code
);
1990 switch (lpnmh
->code
)
1993 TRACE("-- NM_SETFOCUS %p\n", this);
1994 OnSetFocus(0, 0, 0, unused
);
1997 TRACE("-- NM_KILLFOCUS %p\n", this);
1999 /* Notify the ICommDlgBrowser interface */
2000 OnStateChange(CDBOSC_KILLFOCUS
);
2003 TRACE("-- NM_CUSTOMDRAW %p\n", this);
2004 return CDRF_DODEFAULT
;
2005 case NM_RELEASEDCAPTURE
:
2006 TRACE("-- NM_RELEASEDCAPTURE %p\n", this);
2009 TRACE("-- NM_CLICK %p\n", this);
2012 TRACE("-- NM_RCLICK %p\n", this);
2015 TRACE("-- NM_DBLCLK %p\n", this);
2016 OpenSelectedItems();
2019 TRACE("-- NM_RETURN %p\n", this);
2020 OpenSelectedItems();
2023 TRACE("-- HDN_ENDTRACKW %p\n", this);
2024 //nColumn1 = m_ListView.GetColumnWidth(0);
2025 //nColumn2 = m_ListView.GetColumnWidth(1);
2027 case LVN_DELETEITEM
:
2028 TRACE("-- LVN_DELETEITEM %p\n", this);
2029 /*delete the pidl because we made a copy of it*/
2030 SHFree(reinterpret_cast<LPVOID
>(lpnmlv
->lParam
));
2032 case LVN_DELETEALLITEMS
:
2033 TRACE("-- LVN_DELETEALLITEMS %p\n", this);
2035 case LVN_INSERTITEM
:
2036 TRACE("-- LVN_INSERTITEM (STUB)%p\n", this);
2038 case LVN_ITEMACTIVATE
:
2039 TRACE("-- LVN_ITEMACTIVATE %p\n", this);
2040 OnStateChange(CDBOSC_SELCHANGE
); // browser will get the IDataObject
2042 case LVN_COLUMNCLICK
:
2043 m_sortInfo
.nHeaderID
= lpnmlv
->iSubItem
;
2044 if (m_sortInfo
.nLastHeaderID
== m_sortInfo
.nHeaderID
)
2045 m_sortInfo
.bIsAscending
= !m_sortInfo
.bIsAscending
;
2047 m_sortInfo
.bIsAscending
= TRUE
;
2050 case LVN_GETDISPINFOA
:
2051 case LVN_GETDISPINFOW
:
2052 TRACE("-- LVN_GETDISPINFO %p\n", this);
2053 pidl
= _PidlByItem(lpdi
->item
);
2055 if (lpdi
->item
.mask
& LVIF_TEXT
) /* text requested */
2060 if (FAILED_UNEXPECTEDLY(m_pSF2Parent
->GetDetailsOf(pidl
, lpdi
->item
.iSubItem
, &sd
)))
2063 if (lpnmh
->code
== LVN_GETDISPINFOA
)
2065 /* shouldn't happen */
2066 NMLVDISPINFOA
*lpdiA
= (NMLVDISPINFOA
*)lpnmh
;
2067 StrRetToStrNA( lpdiA
->item
.pszText
, lpdiA
->item
.cchTextMax
, &sd
.str
, NULL
);
2068 TRACE("-- text=%s\n", lpdiA
->item
.pszText
);
2070 else /* LVN_GETDISPINFOW */
2072 StrRetToStrNW( lpdi
->item
.pszText
, lpdi
->item
.cchTextMax
, &sd
.str
, NULL
);
2073 TRACE("-- text=%s\n", debugstr_w(lpdi
->item
.pszText
));
2078 FIXME("no m_pSF2Parent\n");
2081 if(lpdi
->item
.mask
& LVIF_IMAGE
) /* image requested */
2083 lpdi
->item
.iImage
= SHMapPIDLToSystemImageListIndex(m_pSFParent
, pidl
, 0);
2085 if(lpdi
->item
.mask
& LVIF_STATE
)
2087 ULONG attributes
= SFGAO_HIDDEN
;
2088 if (SUCCEEDED(m_pSFParent
->GetAttributesOf(1, &pidl
, &attributes
)))
2090 if (attributes
& SFGAO_HIDDEN
)
2091 lpdi
->item
.state
|= LVIS_CUT
;
2094 lpdi
->item
.mask
|= LVIF_DI_SETITEM
;
2096 case LVN_ITEMCHANGED
:
2097 TRACE("-- LVN_ITEMCHANGED %p\n", this);
2098 OnStateChange(CDBOSC_SELCHANGE
); // browser will get the IDataObject
2100 _DoFolderViewCB(SFVM_SELECTIONCHANGED
, NULL
/* FIXME */, NULL
/* FIXME */);
2103 case LVN_BEGINRDRAG
:
2104 TRACE("-- LVN_BEGINDRAG\n");
2105 if (GetSelections())
2107 CComPtr
<IDataObject
> pda
;
2108 DWORD dwAttributes
= SFGAO_CANCOPY
| SFGAO_CANLINK
;
2109 DWORD dwEffect
= DROPEFFECT_MOVE
;
2111 if (SUCCEEDED(m_pSFParent
->GetUIObjectOf(m_hWnd
, m_cidl
, m_apidl
, IID_NULL_PPV_ARG(IDataObject
, &pda
))))
2113 LPNMLISTVIEW params
= (LPNMLISTVIEW
)lParam
;
2115 if (SUCCEEDED(m_pSFParent
->GetAttributesOf(m_cidl
, m_apidl
, &dwAttributes
)))
2116 dwEffect
|= dwAttributes
& (SFGAO_CANCOPY
| SFGAO_CANLINK
);
2118 CComPtr
<IAsyncOperation
> piaso
;
2119 if (SUCCEEDED(pda
->QueryInterface(IID_PPV_ARG(IAsyncOperation
, &piaso
))))
2120 piaso
->SetAsyncMode(TRUE
);
2124 m_pSourceDataObject
= pda
;
2125 m_ptFirstMousePos
= params
->ptAction
;
2126 ClientToScreen(&m_ptFirstMousePos
);
2127 ::ClientToListView(m_ListView
, &m_ptFirstMousePos
);
2129 HIMAGELIST big_icons
, small_icons
;
2130 Shell_GetImageLists(&big_icons
, &small_icons
);
2131 PCUITEMID_CHILD pidl
= _PidlByItem(params
->iItem
);
2132 int iIcon
= SHMapPIDLToSystemImageListIndex(m_pSFParent
, pidl
, 0);
2134 m_ListView
.GetItemPosition(params
->iItem
, &ptItem
);
2136 ImageList_BeginDrag(big_icons
, iIcon
, params
->ptAction
.x
- ptItem
.x
, params
->ptAction
.y
- ptItem
.y
);
2137 DoDragDrop(pda
, this, dwEffect
, &dwEffect2
);
2138 m_pSourceDataObject
.Release();
2142 case LVN_BEGINLABELEDITW
:
2144 DWORD dwAttr
= SFGAO_CANRENAME
;
2145 pidl
= _PidlByItem(lpdi
->item
);
2147 TRACE("-- LVN_BEGINLABELEDITW %p\n", this);
2149 m_pSFParent
->GetAttributesOf(1, &pidl
, &dwAttr
);
2150 if (SFGAO_CANRENAME
& dwAttr
)
2152 HWND hEdit
= reinterpret_cast<HWND
>(m_ListView
.SendMessage(LVM_GETEDITCONTROL
));
2153 SHLimitInputEdit(hEdit
, m_pSFParent
);
2155 // smartass-renaming: See CORE-15242
2156 if (!(dwAttr
& SFGAO_FOLDER
) && (dwAttr
& SFGAO_FILESYSTEM
) &&
2157 (lpdi
->item
.mask
& LVIF_TEXT
) && !SelectExtOnRename())
2159 WCHAR szFullPath
[MAX_PATH
];
2160 PIDLIST_ABSOLUTE pidlFull
= ILCombine(m_pidlParent
, pidl
);
2161 SHGetPathFromIDListW(pidlFull
, szFullPath
);
2163 if (!SHELL_FS_HideExtension(szFullPath
))
2165 LPWSTR pszText
= lpdi
->item
.pszText
;
2166 LPWSTR pchDotExt
= PathFindExtensionW(pszText
);
2167 ::PostMessageW(hEdit
, EM_SETSEL
, 0, pchDotExt
- pszText
);
2168 ::PostMessageW(hEdit
, EM_SCROLLCARET
, 0, 0);
2179 case LVN_ENDLABELEDITW
:
2181 TRACE("-- LVN_ENDLABELEDITW %p\n", this);
2182 m_isEditing
= FALSE
;
2184 if (lpdi
->item
.pszText
)
2189 pidl
= _PidlByItem(lpdi
->item
);
2190 PITEMID_CHILD pidlNew
= NULL
;
2191 hr
= m_pSFParent
->SetNameOf(0, pidl
, lpdi
->item
.pszText
, SHGDN_INFOLDER
, &pidlNew
);
2193 if (SUCCEEDED(hr
) && pidlNew
)
2195 lvItem
.mask
= LVIF_PARAM
|LVIF_IMAGE
;
2196 lvItem
.iItem
= lpdi
->item
.iItem
;
2197 lvItem
.iSubItem
= 0;
2198 lvItem
.lParam
= reinterpret_cast<LPARAM
>(pidlNew
);
2199 lvItem
.iImage
= SHMapPIDLToSystemImageListIndex(m_pSFParent
, pidlNew
, 0);
2200 m_ListView
.SetItem(&lvItem
);
2201 m_ListView
.Update(lpdi
->item
.iItem
);
2209 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh
->code
);
2216 // This is just a quick hack to make the desktop work correctly.
2217 // ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the
2218 // way that a folder should know if it should update upon a change notification.
2219 // It is exported by merged folders at a minimum.
2220 static BOOL
ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1
, PCIDLIST_ABSOLUTE pidl2
)
2222 if (!pidl1
|| !pidl2
)
2224 if (ILIsParent(pidl1
, pidl2
, TRUE
))
2227 if (_ILIsDesktop(pidl1
))
2229 PIDLIST_ABSOLUTE deskpidl
;
2230 SHGetFolderLocation(NULL
, CSIDL_DESKTOPDIRECTORY
, NULL
, 0, &deskpidl
);
2231 if (ILIsParent(deskpidl
, pidl2
, TRUE
))
2237 SHGetFolderLocation(NULL
, CSIDL_COMMON_DESKTOPDIRECTORY
, NULL
, 0, &deskpidl
);
2238 if (ILIsParent(deskpidl
, pidl2
, TRUE
))
2246 WCHAR szPath1
[MAX_PATH
], szPath2
[MAX_PATH
];
2247 LPITEMIDLIST pidl2Clone
= ILClone(pidl2
);
2248 ILRemoveLastID(pidl2Clone
);
2249 if (SHGetPathFromIDListW(pidl1
, szPath1
) &&
2250 SHGetPathFromIDListW(pidl2Clone
, szPath2
))
2252 if (lstrcmpiW(szPath1
, szPath2
) == 0)
2263 LRESULT
CDefView::OnChangeNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2265 // The change notify can come before WM_CREATE
2269 HANDLE hChange
= (HANDLE
)wParam
;
2270 DWORD dwProcID
= (DWORD
)lParam
;
2271 PIDLIST_ABSOLUTE
*Pidls
;
2273 HANDLE hLock
= SHChangeNotification_Lock(hChange
, dwProcID
, &Pidls
, &lEvent
);
2276 ERR("hLock == NULL\n");
2280 BOOL bParent0
= ILIsParentOrSpecialParent(m_pidlParent
, Pidls
[0]);
2281 BOOL bParent1
= ILIsParentOrSpecialParent(m_pidlParent
, Pidls
[1]);
2283 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls
[0], Pidls
[1], lParam
);
2285 lEvent
&= ~SHCNE_INTERRUPT
;
2290 case SHCNE_DRIVEADD
:
2293 if (LV_FindItemByPidl(ILFindLastID(Pidls
[0])) == -1)
2294 LV_AddItem(ILFindLastID(Pidls
[0]));
2296 LV_ProdItem(ILFindLastID(Pidls
[0]));
2301 case SHCNE_DRIVEREMOVED
:
2303 LV_DeleteItem(ILFindLastID(Pidls
[0]));
2305 case SHCNE_RENAMEFOLDER
:
2306 case SHCNE_RENAMEITEM
:
2307 if (bParent0
&& bParent1
)
2308 LV_RenameItem(ILFindLastID(Pidls
[0]), ILFindLastID(Pidls
[1]));
2310 LV_DeleteItem(ILFindLastID(Pidls
[0]));
2312 LV_AddItem(ILFindLastID(Pidls
[1]));
2314 case SHCNE_UPDATEITEM
:
2316 LV_RenameItem(ILFindLastID(Pidls
[0]), ILFindLastID(Pidls
[0]));
2318 case SHCNE_UPDATEDIR
:
2323 SHChangeNotification_Unlock(hLock
);
2327 HRESULT
SHGetMenuIdFromMenuMsg(UINT uMsg
, LPARAM lParam
, UINT
*CmdId
);
2328 HRESULT
SHSetMenuIdInMenuMsg(UINT uMsg
, LPARAM lParam
, UINT CmdId
);
2330 LRESULT
CDefView::OnCustomItem(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2335 ERR("no context menu\n");
2339 // lParam of WM_DRAWITEM WM_MEASUREITEM contains a menu id and
2340 // this also needs to be changed to a menu identifier offset
2342 HRESULT hres
= SHGetMenuIdFromMenuMsg(uMsg
, lParam
, &CmdID
);
2343 if (SUCCEEDED(hres
))
2344 SHSetMenuIdInMenuMsg(uMsg
, lParam
, CmdID
- CONTEXT_MENU_BASE_ID
);
2346 /* Forward the message to the IContextMenu2 */
2348 hres
= SHForwardContextMenuMsg(m_pCM
, uMsg
, wParam
, lParam
, &result
, TRUE
);
2350 return (SUCCEEDED(hres
));
2353 LRESULT
CDefView::OnSettingChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2355 /* Wallpaper setting affects drop shadows effect */
2356 if (wParam
== SPI_SETDESKWALLPAPER
|| wParam
== 0)
2362 LRESULT
CDefView::OnInitMenuPopup(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2364 HMENU hmenu
= (HMENU
) wParam
;
2365 int nPos
= LOWORD(lParam
);
2369 OnCustomItem(uMsg
, wParam
, lParam
, bHandled
);
2371 HMENU hViewMenu
= GetSubmenuByID(m_hMenu
, FCIDM_MENU_VIEW
);
2373 if (GetSelections() == 0)
2375 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_CUT
, MF_GRAYED
);
2376 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_COPY
, MF_GRAYED
);
2377 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_RENAME
, MF_GRAYED
);
2378 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_COPYTO
, MF_GRAYED
);
2379 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_MOVETO
, MF_GRAYED
);
2380 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_DELETE
, MF_GRAYED
);
2384 // FIXME: Check copyable
2385 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_CUT
, MF_ENABLED
);
2386 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_COPY
, MF_ENABLED
);
2387 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_RENAME
, MF_ENABLED
);
2388 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_COPYTO
, MF_ENABLED
);
2389 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_MOVETO
, MF_ENABLED
);
2390 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_DELETE
, MF_ENABLED
);
2393 /* Lets try to find out what the hell wParam is */
2394 if (hmenu
== GetSubMenu(m_hMenu
, nPos
))
2395 menuItemId
= ReallyGetMenuItemID(m_hMenu
, nPos
);
2396 else if (hViewMenu
&& hmenu
== GetSubMenu(hViewMenu
, nPos
))
2397 menuItemId
= ReallyGetMenuItemID(hViewMenu
, nPos
);
2398 else if (m_hContextMenu
&& hmenu
== GetSubMenu(m_hContextMenu
, nPos
))
2399 menuItemId
= ReallyGetMenuItemID(m_hContextMenu
, nPos
);
2405 case FCIDM_MENU_FILE
:
2408 case FCIDM_MENU_VIEW
:
2409 case FCIDM_SHVIEW_VIEW
:
2410 CheckViewMode(hmenu
);
2412 case FCIDM_SHVIEW_ARRANGE
:
2413 FillArrangeAsMenu(hmenu
);
2421 // The INTERFACE of the IShellView object
2423 HRESULT WINAPI
CDefView::GetWindow(HWND
*phWnd
)
2425 TRACE("(%p)\n", this);
2432 HRESULT WINAPI
CDefView::ContextSensitiveHelp(BOOL fEnterMode
)
2434 FIXME("(%p) stub\n", this);
2439 // FIXME: use the accel functions
2440 HRESULT WINAPI
CDefView::TranslateAccelerator(LPMSG lpmsg
)
2445 if (lpmsg
->message
>= WM_KEYFIRST
&& lpmsg
->message
<= WM_KEYLAST
)
2447 if (::TranslateAcceleratorW(m_hWnd
, m_hAccel
, lpmsg
) != 0)
2450 TRACE("-- key=0x%04lx\n", lpmsg
->wParam
);
2453 return m_pShellBrowser
->TranslateAcceleratorSB(lpmsg
, 0);
2456 HRESULT WINAPI
CDefView::EnableModeless(BOOL fEnable
)
2458 FIXME("(%p)\n", this);
2462 HRESULT WINAPI
CDefView::UIActivate(UINT uState
)
2464 TRACE("(%p)->(state=%x)\n", this, uState
);
2466 // don't do anything if the state isn't changing
2467 if (m_uState
== uState
)
2470 // OnActivate handles the menu merging and internal state
2473 // only do this if we are active
2474 if (uState
!= SVUIA_DEACTIVATE
)
2476 _ForceStatusBarResize();
2478 // Set the text for the status bar
2485 HRESULT WINAPI
CDefView::Refresh()
2487 TRACE("(%p)\n", this);
2489 _DoFolderViewCB(SFVM_LISTREFRESHED
, TRUE
, 0);
2491 m_ListView
.DeleteAllItems();
2497 HRESULT WINAPI
CDefView::CreateViewWindow(IShellView
*lpPrevView
, LPCFOLDERSETTINGS lpfs
, IShellBrowser
*psb
, RECT
*prcView
, HWND
*phWnd
)
2499 return CreateViewWindow3(psb
, lpPrevView
, SV3CVW3_DEFAULT
,
2500 (FOLDERFLAGS
)lpfs
->fFlags
, (FOLDERFLAGS
)lpfs
->fFlags
, (FOLDERVIEWMODE
)lpfs
->ViewMode
, NULL
, prcView
, phWnd
);
2503 HRESULT WINAPI
CDefView::DestroyViewWindow()
2505 TRACE("(%p)\n", this);
2507 /* Make absolutely sure all our UI is cleaned up */
2508 UIActivate(SVUIA_DEACTIVATE
);
2512 // MSDN: Accelerator tables loaded from resources are freed automatically when application terminates
2516 if (m_hMenuArrangeModes
)
2518 DestroyMenu(m_hMenuArrangeModes
);
2519 m_hMenuArrangeModes
= NULL
;
2522 if (m_hMenuViewModes
)
2524 DestroyMenu(m_hMenuViewModes
);
2525 m_hMenuViewModes
= NULL
;
2530 DestroyMenu(m_hMenu
);
2536 m_ListView
.DestroyWindow();
2541 _DoFolderViewCB(SFVM_WINDOWCLOSING
, (WPARAM
)m_hWnd
, 0);
2545 m_pShellBrowser
.Release();
2546 m_pCommDlgBrowser
.Release();
2551 HRESULT WINAPI
CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs
)
2553 TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs
,
2554 m_FolderSettings
.ViewMode
, m_FolderSettings
.fFlags
);
2557 return E_INVALIDARG
;
2559 *lpfs
= m_FolderSettings
;
2563 HRESULT WINAPI
CDefView::AddPropertySheetPages(DWORD dwReserved
, LPFNADDPROPSHEETPAGE lpfn
, LPARAM lparam
)
2565 FIXME("(%p) stub\n", this);
2570 HRESULT WINAPI
CDefView::SaveViewState()
2572 FIXME("(%p) stub\n", this);
2577 HRESULT WINAPI
CDefView::SelectItem(PCUITEMID_CHILD pidl
, UINT uFlags
)
2581 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl
, uFlags
);
2585 ERR("!m_ListView\n");
2589 i
= LV_FindItemByPidl(pidl
);
2593 LVITEMW lvItem
= {0};
2594 lvItem
.mask
= LVIF_STATE
;
2595 lvItem
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
2597 while (m_ListView
.GetItem(&lvItem
))
2599 if (lvItem
.iItem
== i
)
2601 if (uFlags
& SVSI_SELECT
)
2602 lvItem
.state
|= LVIS_SELECTED
;
2604 lvItem
.state
&= ~LVIS_SELECTED
;
2606 if (uFlags
& SVSI_FOCUSED
)
2607 lvItem
.state
|= LVIS_FOCUSED
;
2609 lvItem
.state
&= ~LVIS_FOCUSED
;
2613 if (uFlags
& SVSI_DESELECTOTHERS
)
2615 lvItem
.state
&= ~LVIS_SELECTED
;
2617 lvItem
.state
&= ~LVIS_FOCUSED
;
2620 m_ListView
.SetItem(&lvItem
);
2624 if (uFlags
& SVSI_ENSUREVISIBLE
)
2625 m_ListView
.EnsureVisible(i
, FALSE
);
2627 if((uFlags
& SVSI_EDIT
) == SVSI_EDIT
)
2628 m_ListView
.EditLabel(i
);
2633 HRESULT WINAPI
CDefView::GetItemObject(UINT uItem
, REFIID riid
, LPVOID
*ppvOut
)
2635 HRESULT hr
= E_NOINTERFACE
;
2637 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem
, debugstr_guid(&riid
), ppvOut
);
2640 return E_INVALIDARG
;
2646 case SVGIO_BACKGROUND
:
2647 if (IsEqualIID(riid
, IID_IContextMenu
))
2649 hr
= CDefViewBckgrndMenu_CreateInstance(m_pSF2Parent
, riid
, ppvOut
);
2650 if (FAILED_UNEXPECTEDLY(hr
))
2653 IUnknown_SetSite(*((IUnknown
**)ppvOut
), (IShellView
*)this);
2655 else if (IsEqualIID(riid
, IID_IDispatch
))
2657 if (m_pShellFolderViewDual
== NULL
)
2659 hr
= CDefViewDual_Constructor(riid
, (LPVOID
*)&m_pShellFolderViewDual
);
2660 if (FAILED_UNEXPECTEDLY(hr
))
2663 hr
= m_pShellFolderViewDual
->QueryInterface(riid
, ppvOut
);
2666 case SVGIO_SELECTION
:
2668 hr
= m_pSFParent
->GetUIObjectOf(m_hWnd
, m_cidl
, m_apidl
, riid
, 0, ppvOut
);
2669 if (FAILED_UNEXPECTEDLY(hr
))
2672 if (IsEqualIID(riid
, IID_IContextMenu
))
2673 IUnknown_SetSite(*((IUnknown
**)ppvOut
), (IShellView
*)this);
2678 TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut
);
2683 HRESULT STDMETHODCALLTYPE
CDefView::GetCurrentViewMode(UINT
*pViewMode
)
2685 TRACE("(%p)->(%p), stub\n", this, pViewMode
);
2688 return E_INVALIDARG
;
2690 *pViewMode
= m_FolderSettings
.ViewMode
;
2694 HRESULT STDMETHODCALLTYPE
CDefView::SetCurrentViewMode(UINT ViewMode
)
2697 TRACE("(%p)->(%u), stub\n", this, ViewMode
);
2699 /* It's not redundant to check FVM_AUTO because it's a (UINT)-1 */
2700 if (((INT
)ViewMode
< FVM_FIRST
|| (INT
)ViewMode
> FVM_LAST
) && ((INT
)ViewMode
!= FVM_AUTO
))
2701 return E_INVALIDARG
;
2703 /* Windows before Vista uses LVM_SETVIEW and possibly
2704 LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview,
2705 while later versions seem to accomplish this through other
2713 dwStyle
= LVS_REPORT
;
2716 dwStyle
= LVS_SMALLICON
;
2723 FIXME("ViewMode %d not implemented\n", ViewMode
);
2729 m_ListView
.ModifyStyle(LVS_TYPEMASK
, dwStyle
);
2731 /* This will not necessarily be the actual mode set above.
2732 This mimics the behavior of Windows XP. */
2733 m_FolderSettings
.ViewMode
= ViewMode
;
2738 HRESULT STDMETHODCALLTYPE
CDefView::GetFolder(REFIID riid
, void **ppv
)
2740 if (m_pSFParent
== NULL
)
2743 return m_pSFParent
->QueryInterface(riid
, ppv
);
2746 HRESULT STDMETHODCALLTYPE
CDefView::Item(int iItemIndex
, PITEMID_CHILD
*ppidl
)
2748 PCUITEMID_CHILD pidl
= _PidlByItem(iItemIndex
);
2751 *ppidl
= ILClone(pidl
);
2756 return E_INVALIDARG
;
2759 HRESULT STDMETHODCALLTYPE
CDefView::ItemCount(UINT uFlags
, int *pcItems
)
2761 TRACE("(%p)->(%u %p)\n", this, uFlags
, pcItems
);
2763 if (uFlags
!= SVGIO_ALLVIEW
)
2764 FIXME("some flags unsupported, %x\n", uFlags
& ~SVGIO_ALLVIEW
);
2766 *pcItems
= m_ListView
.GetItemCount();
2771 HRESULT STDMETHODCALLTYPE
CDefView::Items(UINT uFlags
, REFIID riid
, void **ppv
)
2776 HRESULT STDMETHODCALLTYPE
CDefView::GetSelectionMarkedItem(int *piItem
)
2778 TRACE("(%p)->(%p)\n", this, piItem
);
2780 *piItem
= m_ListView
.GetSelectionMark();
2785 HRESULT STDMETHODCALLTYPE
CDefView::GetFocusedItem(int *piItem
)
2787 TRACE("(%p)->(%p)\n", this, piItem
);
2789 *piItem
= m_ListView
.GetNextItem(-1, LVNI_FOCUSED
);
2794 HRESULT STDMETHODCALLTYPE
CDefView::GetItemPosition(PCUITEMID_CHILD pidl
, POINT
*ppt
)
2798 ERR("!m_ListView\n");
2802 int lvIndex
= LV_FindItemByPidl(pidl
);
2803 if (lvIndex
== -1 || ppt
== NULL
)
2804 return E_INVALIDARG
;
2806 m_ListView
.GetItemPosition(lvIndex
, ppt
);
2810 HRESULT STDMETHODCALLTYPE
CDefView::GetSpacing(POINT
*ppt
)
2812 TRACE("(%p)->(%p)\n", this, ppt
);
2816 ERR("!m_ListView\n");
2823 m_ListView
.GetItemSpacing(spacing
);
2825 ppt
->x
= spacing
.cx
;
2826 ppt
->y
= spacing
.cy
;
2832 HRESULT STDMETHODCALLTYPE
CDefView::GetDefaultSpacing(POINT
*ppt
)
2837 HRESULT STDMETHODCALLTYPE
CDefView::GetAutoArrange()
2839 return ((m_ListView
.GetStyle() & LVS_AUTOARRANGE
) ? S_OK
: S_FALSE
);
2842 HRESULT
CDefView::_GetSnapToGrid()
2844 DWORD dwExStyle
= (DWORD
)m_ListView
.SendMessage(LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
2845 return ((dwExStyle
& LVS_EX_SNAPTOGRID
) ? S_OK
: S_FALSE
);
2848 HRESULT STDMETHODCALLTYPE
CDefView::SelectItem(int iItem
, DWORD dwFlags
)
2852 TRACE("(%p)->(%d, %x)\n", this, iItem
, dwFlags
);
2855 lvItem
.stateMask
= LVIS_SELECTED
;
2857 if (dwFlags
& SVSI_ENSUREVISIBLE
)
2858 m_ListView
.EnsureVisible(iItem
, 0);
2861 if (dwFlags
& SVSI_DESELECTOTHERS
)
2862 m_ListView
.SetItemState(-1, 0, LVIS_SELECTED
);
2865 if (dwFlags
& SVSI_SELECT
)
2866 lvItem
.state
|= LVIS_SELECTED
;
2868 if (dwFlags
& SVSI_FOCUSED
)
2869 lvItem
.stateMask
|= LVIS_FOCUSED
;
2871 m_ListView
.SetItemState(iItem
, lvItem
.state
, lvItem
.stateMask
);
2873 if ((dwFlags
& SVSI_EDIT
) == SVSI_EDIT
)
2874 m_ListView
.EditLabel(iItem
);
2879 HRESULT STDMETHODCALLTYPE
CDefView::SelectAndPositionItems(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, POINT
*apt
, DWORD dwFlags
)
2883 /* Reset the selection */
2884 m_ListView
.SetItemState(-1, 0, LVIS_SELECTED
);
2887 for (UINT i
= 0 ; i
< m_cidl
; i
++)
2889 lvIndex
= LV_FindItemByPidl(apidl
[i
]);
2892 SelectItem(lvIndex
, dwFlags
);
2893 m_ListView
.SetItemPosition(lvIndex
, &apt
[i
]);
2901 // IShellView2 implementation
2903 HRESULT STDMETHODCALLTYPE
CDefView::GetView(SHELLVIEWID
*view_guid
, ULONG view_type
)
2905 FIXME("(%p)->(%p, %lu) stub\n", this, view_guid
, view_type
);
2909 HRESULT STDMETHODCALLTYPE
CDefView::CreateViewWindow2(LPSV2CVW2_PARAMS view_params
)
2911 return CreateViewWindow3(view_params
->psbOwner
, view_params
->psvPrev
,
2912 SV3CVW3_DEFAULT
, (FOLDERFLAGS
)view_params
->pfs
->fFlags
, (FOLDERFLAGS
)view_params
->pfs
->fFlags
,
2913 (FOLDERVIEWMODE
)view_params
->pfs
->ViewMode
, view_params
->pvid
, view_params
->prcView
, &view_params
->hwndView
);
2916 HRESULT STDMETHODCALLTYPE
CDefView::CreateViewWindow3(IShellBrowser
*psb
, IShellView
*psvPrevious
, SV3CVW3_FLAGS view_flags
, FOLDERFLAGS mask
, FOLDERFLAGS flags
, FOLDERVIEWMODE mode
, const SHELLVIEWID
*view_id
, const RECT
*prcView
, HWND
*hwnd
)
2918 OLEMENUGROUPWIDTHS omw
= { { 0, 0, 0, 0, 0, 0 } };
2922 TRACE("(%p)->(shlview=%p shlbrs=%p rec=%p hwnd=%p vmode=%x flags=%x)\n", this, psvPrevious
, psb
, prcView
, hwnd
, mode
, flags
);
2923 if (prcView
!= NULL
)
2924 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView
->left
, prcView
->top
, prcView
->right
, prcView
->bottom
);
2926 /* Validate the Shell Browser */
2927 if (psb
== NULL
|| m_hWnd
)
2928 return E_UNEXPECTED
;
2930 if (view_flags
!= SV3CVW3_DEFAULT
)
2931 FIXME("unsupported view flags 0x%08x\n", view_flags
);
2933 /* Set up the member variables */
2934 m_pShellBrowser
= psb
;
2935 m_FolderSettings
.ViewMode
= mode
;
2936 m_FolderSettings
.fFlags
= mask
& flags
;
2940 if (IsEqualIID(*view_id
, VID_LargeIcons
))
2941 m_FolderSettings
.ViewMode
= FVM_ICON
;
2942 else if (IsEqualIID(*view_id
, VID_SmallIcons
))
2943 m_FolderSettings
.ViewMode
= FVM_SMALLICON
;
2944 else if (IsEqualIID(*view_id
, VID_List
))
2945 m_FolderSettings
.ViewMode
= FVM_LIST
;
2946 else if (IsEqualIID(*view_id
, VID_Details
))
2947 m_FolderSettings
.ViewMode
= FVM_DETAILS
;
2948 else if (IsEqualIID(*view_id
, VID_Thumbnails
))
2949 m_FolderSettings
.ViewMode
= FVM_THUMBNAIL
;
2950 else if (IsEqualIID(*view_id
, VID_Tile
))
2951 m_FolderSettings
.ViewMode
= FVM_TILE
;
2952 else if (IsEqualIID(*view_id
, VID_ThumbStrip
))
2953 m_FolderSettings
.ViewMode
= FVM_THUMBSTRIP
;
2955 FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_id
));
2958 /* Get our parent window */
2959 m_pShellBrowser
->GetWindow(&m_hWndParent
);
2961 /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
2962 m_pCommDlgBrowser
= NULL
;
2963 if (SUCCEEDED(m_pShellBrowser
->QueryInterface(IID_PPV_ARG(ICommDlgBrowser
, &m_pCommDlgBrowser
))))
2965 TRACE("-- CommDlgBrowser\n");
2968 RECT rcView
= *prcView
;
2969 Create(m_hWndParent
, rcView
, NULL
, WS_CHILD
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_TABSTOP
, 0, 0U);
2980 _DoFolderViewCB(SFVM_WINDOWCREATED
, (WPARAM
)m_hWnd
, 0);
2982 SetWindowPos(HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_SHOWWINDOW
);
2987 m_hMenu
= CreateMenu();
2988 m_pShellBrowser
->InsertMenusSB(m_hMenu
, &omw
);
2989 TRACE("-- after fnInsertMenusSB\n");
2997 HRESULT STDMETHODCALLTYPE
CDefView::HandleRename(LPCITEMIDLIST new_pidl
)
2999 FIXME("(%p)->(%p) stub\n", this, new_pidl
);
3003 HRESULT STDMETHODCALLTYPE
CDefView::SelectAndPositionItem(LPCITEMIDLIST item
, UINT flags
, POINT
*point
)
3005 FIXME("(%p)->(%p, %u, %p) stub\n", this, item
, flags
, point
);
3009 // IShellFolderView implementation
3011 HRESULT STDMETHODCALLTYPE
CDefView::Rearrange(LPARAM sort
)
3013 FIXME("(%p)->(%ld) stub\n", this, sort
);
3017 HRESULT STDMETHODCALLTYPE
CDefView::GetArrangeParam(LPARAM
*sort
)
3019 FIXME("(%p)->(%p) stub\n", this, sort
);
3023 HRESULT STDMETHODCALLTYPE
CDefView::ArrangeGrid()
3025 m_ListView
.SetExtendedListViewStyle(LVS_EX_SNAPTOGRID
, LVS_EX_SNAPTOGRID
);
3029 HRESULT STDMETHODCALLTYPE
CDefView::AutoArrange()
3031 m_ListView
.ModifyStyle(0, LVS_AUTOARRANGE
);
3032 m_ListView
.Arrange(LVA_DEFAULT
);
3036 HRESULT STDMETHODCALLTYPE
CDefView::AddObject(PITEMID_CHILD pidl
, UINT
*item
)
3038 TRACE("(%p)->(%p %p)\n", this, pidl
, item
);
3041 ERR("!m_ListView\n");
3044 *item
= LV_AddItem(pidl
);
3045 return (int)*item
>= 0 ? S_OK
: E_OUTOFMEMORY
;
3048 HRESULT STDMETHODCALLTYPE
CDefView::GetObject(PITEMID_CHILD
*pidl
, UINT item
)
3050 TRACE("(%p)->(%p %d)\n", this, pidl
, item
);
3051 return Item(item
, pidl
);
3054 HRESULT STDMETHODCALLTYPE
CDefView::RemoveObject(PITEMID_CHILD pidl
, UINT
*item
)
3056 TRACE("(%p)->(%p %p)\n", this, pidl
, item
);
3060 ERR("!m_ListView\n");
3066 *item
= LV_FindItemByPidl(ILFindLastID(pidl
));
3067 m_ListView
.DeleteItem(*item
);
3072 m_ListView
.DeleteAllItems();
3078 HRESULT STDMETHODCALLTYPE
CDefView::GetObjectCount(UINT
*count
)
3080 TRACE("(%p)->(%p)\n", this, count
);
3081 *count
= m_ListView
.GetItemCount();
3085 HRESULT STDMETHODCALLTYPE
CDefView::SetObjectCount(UINT count
, UINT flags
)
3087 FIXME("(%p)->(%d %x) stub\n", this, count
, flags
);
3091 HRESULT STDMETHODCALLTYPE
CDefView::UpdateObject(PITEMID_CHILD pidl_old
, PITEMID_CHILD pidl_new
, UINT
*item
)
3093 FIXME("(%p)->(%p %p %p) stub\n", this, pidl_old
, pidl_new
, item
);
3097 HRESULT STDMETHODCALLTYPE
CDefView::RefreshObject(PITEMID_CHILD pidl
, UINT
*item
)
3099 FIXME("(%p)->(%p %p) stub\n", this, pidl
, item
);
3103 HRESULT STDMETHODCALLTYPE
CDefView::SetRedraw(BOOL redraw
)
3105 TRACE("(%p)->(%d)\n", this, redraw
);
3107 m_ListView
.SetRedraw(redraw
);
3111 HRESULT STDMETHODCALLTYPE
CDefView::GetSelectedCount(UINT
*count
)
3113 FIXME("(%p)->(%p) stub\n", this, count
);
3117 HRESULT STDMETHODCALLTYPE
CDefView::GetSelectedObjects(PCUITEMID_CHILD
**pidl
, UINT
*items
)
3119 TRACE("(%p)->(%p %p)\n", this, pidl
, items
);
3121 *items
= GetSelections();
3125 *pidl
= static_cast<PCUITEMID_CHILD
*>(LocalAlloc(0, *items
* sizeof(PCUITEMID_CHILD
)));
3128 return E_OUTOFMEMORY
;
3131 /* it's documented that caller shouldn't PIDLs, only array itself */
3132 memcpy(*pidl
, m_apidl
, *items
* sizeof(PCUITEMID_CHILD
));
3138 HRESULT STDMETHODCALLTYPE
CDefView::IsDropOnSource(IDropTarget
*drop_target
)
3140 if ((m_iDragOverItem
== -1 || m_pCurDropTarget
== NULL
) &&
3141 (m_pSourceDataObject
.p
))
3149 HRESULT STDMETHODCALLTYPE
CDefView::GetDragPoint(POINT
*pt
)
3152 return E_INVALIDARG
;
3154 *pt
= m_ptFirstMousePos
;
3158 HRESULT STDMETHODCALLTYPE
CDefView::GetDropPoint(POINT
*pt
)
3160 FIXME("(%p)->(%p) stub\n", this, pt
);
3164 HRESULT STDMETHODCALLTYPE
CDefView::MoveIcons(IDataObject
*obj
)
3166 TRACE("(%p)->(%p)\n", this, obj
);
3170 HRESULT STDMETHODCALLTYPE
CDefView::SetItemPos(PCUITEMID_CHILD pidl
, POINT
*pt
)
3172 FIXME("(%p)->(%p %p) stub\n", this, pidl
, pt
);
3176 HRESULT STDMETHODCALLTYPE
CDefView::IsBkDropTarget(IDropTarget
*drop_target
)
3178 FIXME("(%p)->(%p) stub\n", this, drop_target
);
3182 HRESULT STDMETHODCALLTYPE
CDefView::SetClipboard(BOOL move
)
3184 FIXME("(%p)->(%d) stub\n", this, move
);
3188 HRESULT STDMETHODCALLTYPE
CDefView::SetPoints(IDataObject
*obj
)
3190 FIXME("(%p)->(%p) stub\n", this, obj
);
3194 HRESULT STDMETHODCALLTYPE
CDefView::GetItemSpacing(ITEMSPACING
*spacing
)
3196 FIXME("(%p)->(%p) stub\n", this, spacing
);
3200 HRESULT STDMETHODCALLTYPE
CDefView::SetCallback(IShellFolderViewCB
*new_cb
, IShellFolderViewCB
**old_cb
)
3203 *old_cb
= m_pShellFolderViewCB
.Detach();
3205 m_pShellFolderViewCB
= new_cb
;
3209 HRESULT STDMETHODCALLTYPE
CDefView::Select(UINT flags
)
3211 FIXME("(%p)->(%d) stub\n", this, flags
);
3215 HRESULT STDMETHODCALLTYPE
CDefView::QuerySupport(UINT
*support
)
3217 TRACE("(%p)->(%p)\n", this, support
);
3221 HRESULT STDMETHODCALLTYPE
CDefView::SetAutomationObject(IDispatch
*disp
)
3223 FIXME("(%p)->(%p) stub\n", this, disp
);
3227 HRESULT WINAPI
CDefView::QueryStatus(const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD
*prgCmds
, OLECMDTEXT
*pCmdText
)
3229 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
3230 this, pguidCmdGroup
, debugstr_guid(pguidCmdGroup
), cCmds
, prgCmds
, pCmdText
);
3233 return E_INVALIDARG
;
3235 for (UINT i
= 0; i
< cCmds
; i
++)
3237 FIXME("\tprgCmds[%d].cmdID = %d\n", i
, prgCmds
[i
].cmdID
);
3238 prgCmds
[i
].cmdf
= 0;
3241 return OLECMDERR_E_UNKNOWNGROUP
;
3245 // ISVOleCmdTarget_Exec(IOleCommandTarget)
3247 // nCmdID is the OLECMDID_* enumeration
3248 HRESULT WINAPI
CDefView::Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
3250 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
3251 this, debugstr_guid(pguidCmdGroup
), nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
3254 return OLECMDERR_E_UNKNOWNGROUP
;
3256 if (IsEqualCLSID(*pguidCmdGroup
, m_Category
))
3258 if (nCmdID
== FCIDM_SHVIEW_AUTOARRANGE
)
3260 if (V_VT(pvaIn
) != VT_INT_PTR
)
3261 return OLECMDERR_E_NOTSUPPORTED
;
3264 params
.cbSize
= sizeof(params
);
3265 params
.rcExclude
= *(RECT
*) V_INTREF(pvaIn
);
3267 if (m_hMenuViewModes
)
3269 // Duplicate all but the last two items of the view modes menu
3270 HMENU hmenuViewPopup
= CreatePopupMenu();
3271 Shell_MergeMenus(hmenuViewPopup
, m_hMenuViewModes
, 0, 0, 0xFFFF, 0);
3272 DeleteMenu(hmenuViewPopup
, GetMenuItemCount(hmenuViewPopup
) - 1, MF_BYPOSITION
);
3273 DeleteMenu(hmenuViewPopup
, GetMenuItemCount(hmenuViewPopup
) - 1, MF_BYPOSITION
);
3274 CheckViewMode(hmenuViewPopup
);
3275 TrackPopupMenuEx(hmenuViewPopup
, TPM_LEFTALIGN
| TPM_TOPALIGN
, params
.rcExclude
.left
, params
.rcExclude
.bottom
, m_hWndParent
, ¶ms
);
3276 ::DestroyMenu(hmenuViewPopup
);
3279 // pvaOut is VT_I4 with value 0x403 (cmd id of the new mode maybe?)
3280 V_VT(pvaOut
) = VT_I4
;
3281 V_I4(pvaOut
) = 0x403;
3285 if (IsEqualIID(*pguidCmdGroup
, CGID_Explorer
) &&
3287 (nCmdexecopt
== 4) && pvaOut
)
3290 if (IsEqualIID(*pguidCmdGroup
, CGID_ShellDocView
) &&
3295 return OLECMDERR_E_UNKNOWNGROUP
;
3298 /**********************************************************
3299 * ISVDropTarget implementation
3302 /******************************************************************************
3303 * drag_notify_subitem [Internal]
3305 * Figure out the shellfolder object, which is currently under the mouse cursor
3306 * and notify it via the IDropTarget interface.
3309 #define SCROLLAREAWIDTH 20
3311 HRESULT
CDefView::drag_notify_subitem(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
3317 /* The key state on drop doesn't have MK_LBUTTON or MK_RBUTTON because it
3318 reflects the key state after the user released the button, so we need
3319 to remember the last key state when the button was pressed */
3320 m_grfKeyState
= grfKeyState
;
3322 // Map from global to client coordinates and query the index of the
3323 // listview-item, which is currently under the mouse cursor.
3324 LVHITTESTINFO htinfo
= {{pt
.x
, pt
.y
}, LVHT_ONITEM
};
3325 ScreenToClient(&htinfo
.pt
);
3326 lResult
= m_ListView
.HitTest(&htinfo
);
3328 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
3329 ::GetClientRect(m_ListView
, &clientRect
);
3330 if (htinfo
.pt
.x
== m_ptLastMousePos
.x
&& htinfo
.pt
.y
== m_ptLastMousePos
.y
&&
3331 (htinfo
.pt
.x
< SCROLLAREAWIDTH
|| htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
||
3332 htinfo
.pt
.y
< SCROLLAREAWIDTH
|| htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
))
3334 m_cScrollDelay
= (m_cScrollDelay
+ 1) % 5; // DragOver is called every 50 ms
3335 if (m_cScrollDelay
== 0)
3337 /* Mouse did hover another 250 ms over the scroll-area */
3338 if (htinfo
.pt
.x
< SCROLLAREAWIDTH
)
3339 m_ListView
.SendMessageW(WM_HSCROLL
, SB_LINEUP
, 0);
3341 if (htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
)
3342 m_ListView
.SendMessageW(WM_HSCROLL
, SB_LINEDOWN
, 0);
3344 if (htinfo
.pt
.y
< SCROLLAREAWIDTH
)
3345 m_ListView
.SendMessageW(WM_VSCROLL
, SB_LINEUP
, 0);
3347 if (htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
)
3348 m_ListView
.SendMessageW(WM_VSCROLL
, SB_LINEDOWN
, 0);
3353 m_cScrollDelay
= 0; // Reset, if cursor is not over the listview's scroll-area
3356 m_ptLastMousePos
= htinfo
.pt
;
3357 ::ClientToListView(m_ListView
, &m_ptLastMousePos
);
3359 /* We need to check if we drag the selection over itself */
3360 if (lResult
!= -1 && m_pSourceDataObject
.p
!= NULL
)
3362 PCUITEMID_CHILD pidl
= _PidlByItem(lResult
);
3364 for (UINT i
= 0; i
< m_cidl
; i
++)
3366 if (pidl
== m_apidl
[i
])
3368 /* The item that is being draged is hovering itself. */
3375 // If we are still over the previous sub-item, notify it via DragOver and return
3376 if (m_pCurDropTarget
&& lResult
== m_iDragOverItem
)
3377 return m_pCurDropTarget
->DragOver(grfKeyState
, pt
, pdwEffect
);
3379 // We've left the previous sub-item, notify it via DragLeave and release it
3380 if (m_pCurDropTarget
)
3382 PCUITEMID_CHILD pidl
= _PidlByItem(m_iDragOverItem
);
3384 SelectItem(pidl
, 0);
3386 m_pCurDropTarget
->DragLeave();
3387 m_pCurDropTarget
.Release();
3390 m_iDragOverItem
= lResult
;
3394 // We are not above one of the listview's subitems. Bind to the
3395 // parent folder's DropTarget interface.
3396 hr
= m_pSFParent
->CreateViewObject(NULL
, IID_PPV_ARG(IDropTarget
,&m_pCurDropTarget
));
3400 // Query the relative PIDL of the shellfolder object represented
3401 // by the currently dragged over listview-item ...
3402 PCUITEMID_CHILD pidl
= _PidlByItem(lResult
);
3404 // ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object
3405 hr
= m_pSFParent
->GetUIObjectOf(m_ListView
, 1, &pidl
, IID_NULL_PPV_ARG(IDropTarget
, &m_pCurDropTarget
));
3408 IUnknown_SetSite(m_pCurDropTarget
, (IShellView
*)this);
3410 // If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state
3413 *pdwEffect
= DROPEFFECT_NONE
;
3417 if (m_iDragOverItem
!= -1)
3419 SelectItem(m_iDragOverItem
, SVSI_SELECT
);
3422 // Notify the item just entered via DragEnter
3423 return m_pCurDropTarget
->DragEnter(m_pCurDataObject
, grfKeyState
, pt
, pdwEffect
);
3426 HRESULT WINAPI
CDefView::DragEnter(IDataObject
*pDataObject
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
3428 if (*pdwEffect
== DROPEFFECT_NONE
)
3431 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
3432 m_pCurDataObject
= pDataObject
;
3434 HRESULT hr
= drag_notify_subitem(grfKeyState
, pt
, pdwEffect
);
3437 POINT ptClient
= {pt
.x
, pt
.y
};
3438 ScreenToClient(&ptClient
);
3439 ImageList_DragEnter(m_hWnd
, ptClient
.x
, ptClient
.y
);
3445 HRESULT WINAPI
CDefView::DragOver(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
3447 POINT ptClient
= {pt
.x
, pt
.y
};
3448 ScreenToClient(&ptClient
);
3449 ImageList_DragMove(ptClient
.x
, ptClient
.y
);
3450 return drag_notify_subitem(grfKeyState
, pt
, pdwEffect
);
3453 HRESULT WINAPI
CDefView::DragLeave()
3455 ImageList_DragLeave(m_hWnd
);
3457 if (m_pCurDropTarget
)
3459 m_pCurDropTarget
->DragLeave();
3460 m_pCurDropTarget
.Release();
3463 if (m_pCurDataObject
!= NULL
)
3465 m_pCurDataObject
.Release();
3468 m_iDragOverItem
= 0;
3473 INT
CDefView::_FindInsertableIndexFromPoint(POINT pt
)
3476 INT i
, nCount
= m_ListView
.GetItemCount();
3479 BOOL bSmall
= ((m_ListView
.GetStyle() & LVS_TYPEMASK
) != LVS_ICON
);
3481 // FIXME: LVM_GETORIGIN is broken. See CORE-17266
3482 pt
.x
+= m_ListView
.GetScrollPos(SB_HORZ
);
3483 pt
.y
+= m_ListView
.GetScrollPos(SB_VERT
);
3485 if (m_ListView
.GetStyle() & LVS_ALIGNLEFT
)
3488 for (i
= 0; i
< nCount
; ++i
)
3490 dwSpacing
= ListView_GetItemSpacing(m_ListView
, bSmall
);
3491 dx
= LOWORD(dwSpacing
);
3492 dy
= HIWORD(dwSpacing
);
3493 ListView_GetItemRect(m_ListView
, i
, &rcBound
, LVIR_SELECTBOUNDS
);
3494 rcBound
.right
= rcBound
.left
+ dx
;
3495 rcBound
.bottom
= rcBound
.top
+ dy
;
3496 if (pt
.x
< rcBound
.right
&& pt
.y
< (rcBound
.top
+ rcBound
.bottom
) / 2)
3501 for (i
= nCount
- 1; i
>= 0; --i
)
3503 ListView_GetItemRect(m_ListView
, i
, &rcBound
, LVIR_SELECTBOUNDS
);
3504 if (rcBound
.left
< pt
.x
&& rcBound
.top
< pt
.y
)
3513 for (i
= 0; i
< nCount
; ++i
)
3515 dwSpacing
= ListView_GetItemSpacing(m_ListView
, bSmall
);
3516 dx
= LOWORD(dwSpacing
);
3517 dy
= HIWORD(dwSpacing
);
3518 ListView_GetItemRect(m_ListView
, i
, &rcBound
, LVIR_SELECTBOUNDS
);
3519 rcBound
.right
= rcBound
.left
+ dx
;
3520 rcBound
.bottom
= rcBound
.top
+ dy
;
3521 if (pt
.y
< rcBound
.bottom
&& pt
.x
< rcBound
.left
)
3525 if (pt
.y
< rcBound
.bottom
&& pt
.x
< rcBound
.right
)
3530 for (i
= nCount
- 1; i
>= 0; --i
)
3532 ListView_GetItemRect(m_ListView
, i
, &rcBound
, LVIR_SELECTBOUNDS
);
3533 if (rcBound
.left
< pt
.x
&& rcBound
.top
< pt
.y
)
3543 void CDefView::_HandleStatusBarResize(int nWidth
)
3547 if (m_isParentFolderSpecial
)
3549 int nPartArray
[] = {-1};
3550 m_pShellBrowser
->SendControlMsg(FCW_STATUS
, SB_SETPARTS
, _countof(nPartArray
), (LPARAM
)nPartArray
, &lResult
);
3554 int nFileSizePartLength
= 125;
3555 const int nLocationPartLength
= 150;
3556 const int nRightPartsLength
= nFileSizePartLength
+ nLocationPartLength
;
3557 int nObjectsPartLength
= nWidth
- nRightPartsLength
;
3559 // If the window is small enough just divide each part into thirds
3560 // to match the behavior of Windows Server 2003
3561 if (nObjectsPartLength
<= nLocationPartLength
)
3562 nObjectsPartLength
= nFileSizePartLength
= nWidth
/ 3;
3564 int nPartArray
[] = {nObjectsPartLength
, nObjectsPartLength
+ nFileSizePartLength
, -1};
3566 m_pShellBrowser
->SendControlMsg(FCW_STATUS
, SB_SETPARTS
, _countof(nPartArray
), (LPARAM
)nPartArray
, &lResult
);
3569 void CDefView::_ForceStatusBarResize()
3571 // Get the handle for the status bar
3573 m_pShellBrowser
->GetControlWindow(FCW_STATUS
, &fStatusBar
);
3575 // Get the size of our status bar
3577 ::GetWindowRect(fStatusBar
, &statusBarSize
);
3579 // Resize the status bar
3580 _HandleStatusBarResize(statusBarSize
.right
- statusBarSize
.left
);
3583 typedef CSimpleMap
<LPARAM
, INT
> CLParamIndexMap
;
3586 SelectionMoveCompareFunc(LPARAM lParam1
, LPARAM lParam2
, LPARAM lParamSort
)
3588 CLParamIndexMap
*pmap
= (CLParamIndexMap
*)lParamSort
;
3589 INT i1
= pmap
->Lookup(lParam1
), i2
= pmap
->Lookup(lParam2
);
3597 void CDefView::_MoveSelectionOnAutoArrange(POINT pt
)
3599 // get insertable index from position
3600 INT iPosition
= _FindInsertableIndexFromPoint(pt
);
3602 // create identity mapping of indexes
3603 CSimpleArray
<INT
> array
;
3604 INT nCount
= m_ListView
.GetItemCount();
3605 for (INT i
= 0; i
< nCount
; ++i
)
3610 // re-ordering mapping
3612 while ((iItem
= m_ListView
.GetNextItem(iItem
, LVNI_SELECTED
)) >= 0)
3614 INT iFrom
= iItem
, iTo
= iPosition
;
3617 if (iFrom
>= nCount
)
3622 // shift indexes by swapping (like a bucket relay)
3625 for (INT i
= iFrom
; i
< iTo
; ++i
)
3627 // swap array[i] and array[i + 1]
3629 array
[i
] = array
[i
+ 1];
3635 for (INT i
= iFrom
; i
> iTo
; --i
)
3637 // swap array[i] and array[i - 1]
3639 array
[i
] = array
[i
- 1];
3645 // create mapping (ListView's lParam to index) from array
3646 CLParamIndexMap map
;
3647 for (INT i
= 0; i
< nCount
; ++i
)
3649 LPARAM lParam
= m_ListView
.GetItemData(array
[i
]);
3654 m_ListView
.SortItems(SelectionMoveCompareFunc
, &map
);
3657 HRESULT WINAPI
CDefView::Drop(IDataObject
* pDataObject
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
3659 ImageList_DragLeave(m_hWnd
);
3660 ImageList_EndDrag();
3662 if ((IsDropOnSource(NULL
) == S_OK
) &&
3663 (*pdwEffect
& DROPEFFECT_MOVE
) &&
3664 (m_grfKeyState
& MK_LBUTTON
))
3666 if (m_pCurDropTarget
)
3668 m_pCurDropTarget
->DragLeave();
3669 m_pCurDropTarget
.Release();
3672 POINT ptDrop
= { pt
.x
, pt
.y
};
3673 ::ScreenToClient(m_ListView
, &ptDrop
);
3674 ::ClientToListView(m_ListView
, &ptDrop
);
3675 m_ptLastMousePos
= ptDrop
;
3677 m_ListView
.SetRedraw(FALSE
);
3678 if (m_ListView
.GetStyle() & LVS_AUTOARRANGE
)
3680 _MoveSelectionOnAutoArrange(m_ptLastMousePos
);
3686 while ((iItem
= m_ListView
.GetNextItem(iItem
, LVNI_SELECTED
)) >= 0)
3688 if (m_ListView
.GetItemPosition(iItem
, &ptItem
))
3690 ptItem
.x
+= m_ptLastMousePos
.x
- m_ptFirstMousePos
.x
;
3691 ptItem
.y
+= m_ptLastMousePos
.y
- m_ptFirstMousePos
.y
;
3692 m_ListView
.SetItemPosition(iItem
, &ptItem
);
3696 m_ListView
.SetRedraw(TRUE
);
3698 else if (m_pCurDropTarget
)
3700 m_pCurDropTarget
->Drop(pDataObject
, grfKeyState
, pt
, pdwEffect
);
3701 m_pCurDropTarget
.Release();
3704 m_pCurDataObject
.Release();
3705 m_iDragOverItem
= 0;
3709 HRESULT WINAPI
CDefView::QueryContinueDrag(BOOL fEscapePressed
, DWORD grfKeyState
)
3711 TRACE("(%p)\n", this);
3714 return DRAGDROP_S_CANCEL
;
3715 else if (!(grfKeyState
& MK_LBUTTON
) && !(grfKeyState
& MK_RBUTTON
))
3716 return DRAGDROP_S_DROP
;
3721 HRESULT WINAPI
CDefView::GiveFeedback(DWORD dwEffect
)
3723 TRACE("(%p)\n", this);
3725 return DRAGDROP_S_USEDEFAULTCURSORS
;
3728 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
)
3730 FIXME("Stub: this=%p\n", this);
3734 HRESULT WINAPI
CDefView::GetColorSet(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DVTARGETDEVICE
*ptd
, HDC hicTargetDevice
, LOGPALETTE
**ppColorSet
)
3736 FIXME("Stub: this=%p\n", this);
3740 HRESULT WINAPI
CDefView::Freeze(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DWORD
*pdwFreeze
)
3742 FIXME("Stub: this=%p\n", this);
3746 HRESULT WINAPI
CDefView::Unfreeze(DWORD dwFreeze
)
3748 FIXME("Stub: this=%p\n", this);
3752 HRESULT WINAPI
CDefView::SetAdvise(DWORD aspects
, DWORD advf
, IAdviseSink
*pAdvSink
)
3754 FIXME("partial stub: %p 0x%08x 0x%08x %p\n", this, aspects
, advf
, pAdvSink
);
3756 // FIXME: we set the AdviseSink, but never use it to send any advice
3757 m_pAdvSink
= pAdvSink
;
3758 m_dwAspects
= aspects
;
3764 HRESULT WINAPI
CDefView::GetAdvise(DWORD
*pAspects
, DWORD
*pAdvf
, IAdviseSink
**ppAdvSink
)
3766 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects
, pAdvf
, ppAdvSink
);
3770 *ppAdvSink
= m_pAdvSink
;
3771 m_pAdvSink
.p
->AddRef();
3775 *pAspects
= m_dwAspects
;
3783 HRESULT STDMETHODCALLTYPE
CDefView::QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
)
3785 if (IsEqualIID(guidService
, SID_IShellBrowser
))
3786 return m_pShellBrowser
->QueryInterface(riid
, ppvObject
);
3787 else if(IsEqualIID(guidService
, SID_IFolderView
))
3788 return QueryInterface(riid
, ppvObject
);
3790 return E_NOINTERFACE
;
3793 HRESULT
CDefView::_MergeToolbar()
3795 CComPtr
<IExplorerToolbar
> ptb
;
3798 hr
= IUnknown_QueryService(m_pShellBrowser
, IID_IExplorerToolbar
, IID_PPV_ARG(IExplorerToolbar
, &ptb
));
3802 m_Category
= CGID_DefViewFrame
;
3804 hr
= ptb
->SetCommandTarget(static_cast<IOleCommandTarget
*>(this), &m_Category
, 0);
3812 hr
= ptb
->AddButtons(&m_Category
, buttonsCount
, buttons
);
3820 HRESULT
CDefView::_DoFolderViewCB(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3822 HRESULT hr
= E_NOTIMPL
;
3824 if (m_pShellFolderViewCB
)
3826 hr
= m_pShellFolderViewCB
->MessageSFVCB(uMsg
, wParam
, lParam
);
3832 HRESULT
CDefView_CreateInstance(IShellFolder
*pFolder
, REFIID riid
, LPVOID
* ppvOut
)
3834 return ShellObjectCreatorInit
<CDefView
>(pFolder
, riid
, ppvOut
);
3837 HRESULT WINAPI
SHCreateShellFolderViewEx(
3838 LPCSFV psvcbi
, // [in] shelltemplate struct
3839 IShellView
**ppsv
) // [out] IShellView pointer
3841 CComPtr
<IShellView
> psv
;
3844 TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n",
3845 psvcbi
->pshf
, psvcbi
->pidl
, psvcbi
->pfnCallback
,
3846 psvcbi
->fvm
, psvcbi
->psvOuter
);
3849 hRes
= CDefView_CreateInstance(psvcbi
->pshf
, IID_PPV_ARG(IShellView
, &psv
));
3850 if (FAILED_UNEXPECTEDLY(hRes
))
3853 *ppsv
= psv
.Detach();
3857 HRESULT WINAPI
SHCreateShellFolderView(const SFV_CREATE
*pcsfv
,
3860 CComPtr
<IShellView
> psv
;
3864 return E_INVALIDARG
;
3868 if (!pcsfv
|| pcsfv
->cbSize
!= sizeof(*pcsfv
))
3869 return E_INVALIDARG
;
3871 TRACE("sf=%p outer=%p callback=%p\n",
3872 pcsfv
->pshf
, pcsfv
->psvOuter
, pcsfv
->psfvcb
);
3874 hRes
= CDefView_CreateInstance(pcsfv
->pshf
, IID_PPV_ARG(IShellView
, &psv
));
3880 CComPtr
<IShellFolderView
> sfv
;
3881 if (SUCCEEDED(psv
->QueryInterface(IID_PPV_ARG(IShellFolderView
, &sfv
))))
3883 sfv
->SetCallback(pcsfv
->psfvcb
, NULL
);
3887 *ppsv
= psv
.Detach();