4 * Copyright 1998,1999 <juergen.schmied@debitel.net>
6 * This is the view visualizing the data provided by the shellfolder.
7 * No direct access to data from pidls should be done from here.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
28 - Load/Save the view state from/into the stream provided by the ShellBrowser.
29 - When editing starts on item, set edit text to for editing value.
30 - Fix shell view to handle view mode popup exec.
31 - The background context menu should have a pidl just like foreground menus. This
32 causes crashes when dynamic handlers try to use the NULL pidl.
33 - Reorder of columns doesn't work - might be bug in comctl32
41 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
45 static const WCHAR SV_CLASS_NAME
[] = {'S', 'H', 'E', 'L', 'L', 'D', 'L', 'L', '_', 'D', 'e', 'f', 'V', 'i', 'e', 'w', 0};
52 } LISTVIEW_SORT_INFO
, *LPLISTVIEW_SORT_INFO
;
54 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
56 /* For the context menu of the def view, the id of the items are based on 1 because we need
57 to call TrackPopupMenu and let it use the 0 value as an indication that the menu was canceled */
58 #define CONTEXT_MENU_BASE_ID 1
60 /* Convert client coordinates to listview coordinates */
62 ClientToListView(HWND hwndLV
, POINT
*ppt
)
66 /* FIXME: LVM_GETORIGIN is broken. See CORE-17266 */
67 if (!ListView_GetOrigin(hwndLV
, &Origin
))
75 public CWindowImpl
<CDefView
, CWindow
, CControlWinTraits
>,
76 public CComObjectRootEx
<CComMultiThreadModelNoCS
>,
79 public IShellFolderView
,
80 public IOleCommandTarget
,
84 public IServiceProvider
87 CComPtr
<IShellFolder
> m_pSFParent
;
88 CComPtr
<IShellFolder2
> m_pSF2Parent
;
89 CComPtr
<IShellFolderViewCB
> m_pShellFolderViewCB
;
90 CComPtr
<IShellBrowser
> m_pShellBrowser
;
91 CComPtr
<ICommDlgBrowser
> m_pCommDlgBrowser
;
92 CComPtr
<IShellFolderViewDual
> m_pShellFolderViewDual
;
95 FOLDERSETTINGS m_FolderSettings
;
96 HMENU m_hMenu
; /* Handle to the menu bar of the browser */
97 HMENU m_hMenuArrangeModes
; /* Handle to the popup menu with the arrange modes */
98 HMENU m_hMenuViewModes
; /* Handle to the popup menu with the view modes */
99 HMENU m_hContextMenu
; /* Handle to the open context menu */
100 BOOL m_bmenuBarInitialized
;
103 PCUITEMID_CHILD
*m_apidl
;
104 PIDLIST_ABSOLUTE m_pidlParent
;
105 LISTVIEW_SORT_INFO m_sortInfo
;
106 ULONG m_hNotify
; /* Change notification handle */
110 CComPtr
<IAdviseSink
> m_pAdvSink
;
112 CComPtr
<IDataObject
> m_pSourceDataObject
;
113 CComPtr
<IDropTarget
> m_pCurDropTarget
; /* The sub-item, which is currently dragged over */
114 CComPtr
<IDataObject
> m_pCurDataObject
; /* The dragged data-object */
115 LONG m_iDragOverItem
; /* Dragged over item's index, iff m_pCurDropTarget != NULL */
116 UINT m_cScrollDelay
; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
117 POINT m_ptLastMousePos
; /* Mouse position at last DragOver call */
118 POINT m_ptFirstMousePos
; /* Mouse position when the drag operation started */
121 CComPtr
<IContextMenu
> m_pCM
;
127 SFVM_CUSTOMVIEWINFO_DATA m_viewinfo_data
;
130 HRESULT
_MergeToolbar();
132 HRESULT
_DoFolderViewCB(UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
133 HRESULT
_GetSnapToGrid();
134 void _MoveSelectionOnAutoArrange(POINT pt
);
135 INT
_FindInsertableIndexFromPoint(POINT pt
);
140 HRESULT WINAPI
Initialize(IShellFolder
*shellFolder
);
141 HRESULT
IncludeObject(PCUITEMID_CHILD pidl
);
142 HRESULT
OnDefaultCommand();
143 HRESULT
OnStateChange(UINT uFlags
);
144 void UpdateStatusbar();
147 void UpdateListColors();
149 static INT CALLBACK
ListViewCompareItems(LPARAM lParam1
, LPARAM lParam2
, LPARAM lpData
);
151 PCUITEMID_CHILD
_PidlByItem(int i
);
152 PCUITEMID_CHILD
_PidlByItem(LVITEM
& lvItem
);
153 int LV_FindItemByPidl(PCUITEMID_CHILD pidl
);
154 int LV_AddItem(PCUITEMID_CHILD pidl
);
155 BOOLEAN
LV_DeleteItem(PCUITEMID_CHILD pidl
);
156 BOOLEAN
LV_RenameItem(PCUITEMID_CHILD pidlOld
, PCUITEMID_CHILD pidlNew
);
157 BOOLEAN
LV_ProdItem(PCUITEMID_CHILD pidl
);
158 static INT CALLBACK
fill_list(LPVOID ptr
, LPVOID arg
);
160 HRESULT
FillFileMenu();
161 HRESULT
FillEditMenu();
162 HRESULT
FillViewMenu();
163 HRESULT
FillArrangeAsMenu(HMENU hmenuArrange
);
164 HRESULT
CheckViewMode(HMENU hmenuView
);
165 UINT
GetSelections();
166 HRESULT
OpenSelectedItems();
168 void DoActivate(UINT uState
);
169 HRESULT
drag_notify_subitem(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
);
170 HRESULT
InvokeContextMenuCommand(UINT uCommand
);
171 LRESULT
OnExplorerCommand(UINT uCommand
, BOOL bUseSelection
);
173 // *** IOleWindow methods ***
174 virtual HRESULT STDMETHODCALLTYPE
GetWindow(HWND
*lphwnd
);
175 virtual HRESULT STDMETHODCALLTYPE
ContextSensitiveHelp(BOOL fEnterMode
);
177 // *** IShellView methods ***
178 virtual HRESULT STDMETHODCALLTYPE
TranslateAccelerator(MSG
*pmsg
);
179 virtual HRESULT STDMETHODCALLTYPE
EnableModeless(BOOL fEnable
);
180 virtual HRESULT STDMETHODCALLTYPE
UIActivate(UINT uState
);
181 virtual HRESULT STDMETHODCALLTYPE
Refresh();
182 virtual HRESULT STDMETHODCALLTYPE
CreateViewWindow(IShellView
*psvPrevious
, LPCFOLDERSETTINGS pfs
, IShellBrowser
*psb
, RECT
*prcView
, HWND
*phWnd
);
183 virtual HRESULT STDMETHODCALLTYPE
DestroyViewWindow();
184 virtual HRESULT STDMETHODCALLTYPE
GetCurrentInfo(LPFOLDERSETTINGS pfs
);
185 virtual HRESULT STDMETHODCALLTYPE
AddPropertySheetPages(DWORD dwReserved
, LPFNSVADDPROPSHEETPAGE pfn
, LPARAM lparam
);
186 virtual HRESULT STDMETHODCALLTYPE
SaveViewState();
187 virtual HRESULT STDMETHODCALLTYPE
SelectItem(PCUITEMID_CHILD pidlItem
, SVSIF uFlags
);
188 virtual HRESULT STDMETHODCALLTYPE
GetItemObject(UINT uItem
, REFIID riid
, void **ppv
);
190 // *** IShellView2 methods ***
191 virtual HRESULT STDMETHODCALLTYPE
GetView(SHELLVIEWID
*view_guid
, ULONG view_type
);
192 virtual HRESULT STDMETHODCALLTYPE
CreateViewWindow2(LPSV2CVW2_PARAMS view_params
);
193 virtual HRESULT STDMETHODCALLTYPE
HandleRename(LPCITEMIDLIST new_pidl
);
194 virtual HRESULT STDMETHODCALLTYPE
SelectAndPositionItem(LPCITEMIDLIST item
, UINT flags
, POINT
*point
);
196 // *** IShellView3 methods ***
197 virtual HRESULT STDMETHODCALLTYPE
CreateViewWindow3(IShellBrowser
*psb
, IShellView
*psvPrevious
, SV3CVW3_FLAGS view_flags
, FOLDERFLAGS mask
, FOLDERFLAGS flags
, FOLDERVIEWMODE mode
, const SHELLVIEWID
*view_id
, RECT
*prcView
, HWND
*hwnd
);
199 // *** IFolderView methods ***
200 virtual HRESULT STDMETHODCALLTYPE
GetCurrentViewMode(UINT
*pViewMode
);
201 virtual HRESULT STDMETHODCALLTYPE
SetCurrentViewMode(UINT ViewMode
);
202 virtual HRESULT STDMETHODCALLTYPE
GetFolder(REFIID riid
, void **ppv
);
203 virtual HRESULT STDMETHODCALLTYPE
Item(int iItemIndex
, PITEMID_CHILD
*ppidl
);
204 virtual HRESULT STDMETHODCALLTYPE
ItemCount(UINT uFlags
, int *pcItems
);
205 virtual HRESULT STDMETHODCALLTYPE
Items(UINT uFlags
, REFIID riid
, void **ppv
);
206 virtual HRESULT STDMETHODCALLTYPE
GetSelectionMarkedItem(int *piItem
);
207 virtual HRESULT STDMETHODCALLTYPE
GetFocusedItem(int *piItem
);
208 virtual HRESULT STDMETHODCALLTYPE
GetItemPosition(PCUITEMID_CHILD pidl
, POINT
*ppt
);
209 virtual HRESULT STDMETHODCALLTYPE
GetSpacing(POINT
*ppt
);
210 virtual HRESULT STDMETHODCALLTYPE
GetDefaultSpacing(POINT
*ppt
);
211 virtual HRESULT STDMETHODCALLTYPE
GetAutoArrange();
212 virtual HRESULT STDMETHODCALLTYPE
SelectItem(int iItem
, DWORD dwFlags
);
213 virtual HRESULT STDMETHODCALLTYPE
SelectAndPositionItems(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, POINT
*apt
, DWORD dwFlags
);
215 // *** IShellFolderView methods ***
216 virtual HRESULT STDMETHODCALLTYPE
Rearrange(LPARAM sort
);
217 virtual HRESULT STDMETHODCALLTYPE
GetArrangeParam(LPARAM
*sort
);
218 virtual HRESULT STDMETHODCALLTYPE
ArrangeGrid();
219 virtual HRESULT STDMETHODCALLTYPE
AutoArrange();
220 virtual HRESULT STDMETHODCALLTYPE
AddObject(PITEMID_CHILD pidl
, UINT
*item
);
221 virtual HRESULT STDMETHODCALLTYPE
GetObject(PITEMID_CHILD
*pidl
, UINT item
);
222 virtual HRESULT STDMETHODCALLTYPE
RemoveObject(PITEMID_CHILD pidl
, UINT
*item
);
223 virtual HRESULT STDMETHODCALLTYPE
GetObjectCount(UINT
*count
);
224 virtual HRESULT STDMETHODCALLTYPE
SetObjectCount(UINT count
, UINT flags
);
225 virtual HRESULT STDMETHODCALLTYPE
UpdateObject(PITEMID_CHILD pidl_old
, PITEMID_CHILD pidl_new
, UINT
*item
);
226 virtual HRESULT STDMETHODCALLTYPE
RefreshObject(PITEMID_CHILD pidl
, UINT
*item
);
227 virtual HRESULT STDMETHODCALLTYPE
SetRedraw(BOOL redraw
);
228 virtual HRESULT STDMETHODCALLTYPE
GetSelectedCount(UINT
*count
);
229 virtual HRESULT STDMETHODCALLTYPE
GetSelectedObjects(PCUITEMID_CHILD
**pidl
, UINT
*items
);
230 virtual HRESULT STDMETHODCALLTYPE
IsDropOnSource(IDropTarget
*drop_target
);
231 virtual HRESULT STDMETHODCALLTYPE
GetDragPoint(POINT
*pt
);
232 virtual HRESULT STDMETHODCALLTYPE
GetDropPoint(POINT
*pt
);
233 virtual HRESULT STDMETHODCALLTYPE
MoveIcons(IDataObject
*obj
);
234 virtual HRESULT STDMETHODCALLTYPE
SetItemPos(PCUITEMID_CHILD pidl
, POINT
*pt
);
235 virtual HRESULT STDMETHODCALLTYPE
IsBkDropTarget(IDropTarget
*drop_target
);
236 virtual HRESULT STDMETHODCALLTYPE
SetClipboard(BOOL move
);
237 virtual HRESULT STDMETHODCALLTYPE
SetPoints(IDataObject
*obj
);
238 virtual HRESULT STDMETHODCALLTYPE
GetItemSpacing(ITEMSPACING
*spacing
);
239 virtual HRESULT STDMETHODCALLTYPE
SetCallback(IShellFolderViewCB
*new_cb
, IShellFolderViewCB
**old_cb
);
240 virtual HRESULT STDMETHODCALLTYPE
Select(UINT flags
);
241 virtual HRESULT STDMETHODCALLTYPE
QuerySupport(UINT
*support
);
242 virtual HRESULT STDMETHODCALLTYPE
SetAutomationObject(IDispatch
*disp
);
244 // *** IOleCommandTarget methods ***
245 virtual HRESULT STDMETHODCALLTYPE
QueryStatus(const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD prgCmds
[ ], OLECMDTEXT
*pCmdText
);
246 virtual HRESULT STDMETHODCALLTYPE
Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
);
248 // *** IDropTarget methods ***
249 virtual HRESULT STDMETHODCALLTYPE
DragEnter(IDataObject
*pDataObj
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
);
250 virtual HRESULT STDMETHODCALLTYPE
DragOver(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
);
251 virtual HRESULT STDMETHODCALLTYPE
DragLeave();
252 virtual HRESULT STDMETHODCALLTYPE
Drop(IDataObject
*pDataObj
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
);
254 // *** IDropSource methods ***
255 virtual HRESULT STDMETHODCALLTYPE
QueryContinueDrag(BOOL fEscapePressed
, DWORD grfKeyState
);
256 virtual HRESULT STDMETHODCALLTYPE
GiveFeedback(DWORD dwEffect
);
258 // *** IViewObject methods ***
259 virtual HRESULT STDMETHODCALLTYPE
Draw(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DVTARGETDEVICE
*ptd
,
260 HDC hdcTargetDev
, HDC hdcDraw
, LPCRECTL lprcBounds
, LPCRECTL lprcWBounds
,
261 BOOL ( STDMETHODCALLTYPE
*pfnContinue
)(ULONG_PTR dwContinue
), ULONG_PTR dwContinue
);
262 virtual HRESULT STDMETHODCALLTYPE
GetColorSet(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
,
263 DVTARGETDEVICE
*ptd
, HDC hicTargetDev
, LOGPALETTE
**ppColorSet
);
264 virtual HRESULT STDMETHODCALLTYPE
Freeze(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DWORD
*pdwFreeze
);
265 virtual HRESULT STDMETHODCALLTYPE
Unfreeze(DWORD dwFreeze
);
266 virtual HRESULT STDMETHODCALLTYPE
SetAdvise(DWORD aspects
, DWORD advf
, IAdviseSink
*pAdvSink
);
267 virtual HRESULT STDMETHODCALLTYPE
GetAdvise(DWORD
*pAspects
, DWORD
*pAdvf
, IAdviseSink
**ppAdvSink
);
269 // *** IServiceProvider methods ***
270 virtual HRESULT STDMETHODCALLTYPE
QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
);
273 LRESULT
OnShowWindow(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
274 LRESULT
OnGetDlgCode(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
275 LRESULT
OnDestroy(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
276 LRESULT
OnEraseBackground(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
277 LRESULT
OnPrintClient(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
278 LRESULT
OnSysColorChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
279 LRESULT
OnGetShellBrowser(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
280 LRESULT
OnNCCreate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
281 LRESULT
OnNCDestroy(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
282 LRESULT
OnCreate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
283 LRESULT
OnContextMenu(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
284 LRESULT
OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
285 LRESULT
OnActivate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
286 LRESULT
OnSetFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
287 LRESULT
OnKillFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
288 LRESULT
OnCommand(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
289 LRESULT
OnNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
290 LRESULT
OnChangeNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
291 LRESULT
OnCustomItem(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
292 LRESULT
OnSettingChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
293 LRESULT
OnInitMenuPopup(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
);
295 static ATL::CWndClassInfo
& GetWndClassInfo()
297 static ATL::CWndClassInfo wc
=
299 { sizeof(WNDCLASSEX
), CS_PARENTDC
, StartWindowProc
,
301 LoadCursor(NULL
, IDC_ARROW
), NULL
, NULL
, SV_CLASS_NAME
, NULL
303 NULL
, NULL
, IDC_ARROW
, TRUE
, 0, _T("")
308 virtual WNDPROC
GetWindowProc()
313 static LRESULT CALLBACK
WindowProc(HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
318 // Must hold a reference during message handling
319 pThis
= reinterpret_cast<CDefView
*>(hWnd
);
321 result
= CWindowImpl
<CDefView
, CWindow
, CControlWinTraits
>::WindowProc(hWnd
, uMsg
, wParam
, lParam
);
326 BEGIN_MSG_MAP(CDefView
)
327 MESSAGE_HANDLER(WM_SIZE
, OnSize
)
328 MESSAGE_HANDLER(WM_SETFOCUS
, OnSetFocus
)
329 MESSAGE_HANDLER(WM_KILLFOCUS
, OnKillFocus
)
330 MESSAGE_HANDLER(WM_NCCREATE
, OnNCCreate
)
331 MESSAGE_HANDLER(WM_NCDESTROY
, OnNCDestroy
)
332 MESSAGE_HANDLER(WM_CREATE
, OnCreate
)
333 MESSAGE_HANDLER(WM_ACTIVATE
, OnActivate
)
334 MESSAGE_HANDLER(WM_NOTIFY
, OnNotify
)
335 MESSAGE_HANDLER(WM_COMMAND
, OnCommand
)
336 MESSAGE_HANDLER(SHV_CHANGE_NOTIFY
, OnChangeNotify
)
337 MESSAGE_HANDLER(WM_CONTEXTMENU
, OnContextMenu
)
338 MESSAGE_HANDLER(WM_DRAWITEM
, OnCustomItem
)
339 MESSAGE_HANDLER(WM_MEASUREITEM
, OnCustomItem
)
340 MESSAGE_HANDLER(WM_SHOWWINDOW
, OnShowWindow
)
341 MESSAGE_HANDLER(WM_GETDLGCODE
, OnGetDlgCode
)
342 MESSAGE_HANDLER(WM_DESTROY
, OnDestroy
)
343 MESSAGE_HANDLER(WM_ERASEBKGND
, OnEraseBackground
)
344 MESSAGE_HANDLER(WM_PRINTCLIENT
, OnPrintClient
)
345 MESSAGE_HANDLER(WM_SYSCOLORCHANGE
, OnSysColorChange
)
346 MESSAGE_HANDLER(CWM_GETISHELLBROWSER
, OnGetShellBrowser
)
347 MESSAGE_HANDLER(WM_SETTINGCHANGE
, OnSettingChange
)
348 MESSAGE_HANDLER(WM_INITMENUPOPUP
, OnInitMenuPopup
)
351 BEGIN_COM_MAP(CDefView
)
352 // Windows returns E_NOINTERFACE for IOleWindow
353 // COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
354 COM_INTERFACE_ENTRY_IID(IID_IShellView
, IShellView
)
355 COM_INTERFACE_ENTRY_IID(IID_CDefView
, IShellView
)
356 COM_INTERFACE_ENTRY_IID(IID_IShellView2
, IShellView2
)
357 COM_INTERFACE_ENTRY_IID(IID_IFolderView
, IFolderView
)
358 COM_INTERFACE_ENTRY_IID(IID_IShellFolderView
, IShellFolderView
)
359 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget
, IOleCommandTarget
)
360 COM_INTERFACE_ENTRY_IID(IID_IDropTarget
, IDropTarget
)
361 COM_INTERFACE_ENTRY_IID(IID_IDropSource
, IDropSource
)
362 COM_INTERFACE_ENTRY_IID(IID_IViewObject
, IViewObject
)
363 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider
, IServiceProvider
)
368 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
369 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
370 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
372 #define ID_LISTVIEW 1
375 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
376 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
377 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
379 typedef void (CALLBACK
*PFNSHGETSETTINGSPROC
)(LPSHELLFLAGSTATE lpsfs
, DWORD dwMask
);
381 CDefView::CDefView() :
385 m_hMenuArrangeModes(NULL
),
386 m_hMenuViewModes(NULL
),
387 m_hContextMenu(NULL
),
388 m_bmenuBarInitialized(FALSE
),
402 ZeroMemory(&m_FolderSettings
, sizeof(m_FolderSettings
));
403 ZeroMemory(&m_sortInfo
, sizeof(m_sortInfo
));
404 ZeroMemory(&m_ptLastMousePos
, sizeof(m_ptLastMousePos
));
405 ZeroMemory(&m_Category
, sizeof(m_Category
));
406 m_viewinfo_data
.clrText
= GetSysColor(COLOR_WINDOWTEXT
);
407 m_viewinfo_data
.clrTextBack
= GetSysColor(COLOR_WINDOW
);
408 m_viewinfo_data
.hbmBack
= NULL
;
411 CDefView::~CDefView()
413 TRACE(" destroying IShellView(%p)\n", this);
415 _DoFolderViewCB(SFVM_VIEWRELEASE
, 0, 0);
417 if (m_viewinfo_data
.hbmBack
)
419 ::DeleteObject(m_viewinfo_data
.hbmBack
);
420 m_viewinfo_data
.hbmBack
= NULL
;
431 HRESULT WINAPI
CDefView::Initialize(IShellFolder
*shellFolder
)
433 m_pSFParent
= shellFolder
;
434 shellFolder
->QueryInterface(IID_PPV_ARG(IShellFolder2
, &m_pSF2Parent
));
439 /**********************************************************
441 * ##### helperfunctions for communication with ICommDlgBrowser #####
443 HRESULT
CDefView::IncludeObject(PCUITEMID_CHILD pidl
)
447 if (m_pCommDlgBrowser
.p
!= NULL
)
449 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl
);
450 ret
= m_pCommDlgBrowser
->IncludeObject(this, pidl
);
451 TRACE("-- returns 0x%08x\n", ret
);
457 HRESULT
CDefView::OnDefaultCommand()
459 HRESULT ret
= S_FALSE
;
461 if (m_pCommDlgBrowser
.p
!= NULL
)
463 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
464 ret
= m_pCommDlgBrowser
->OnDefaultCommand(this);
465 TRACE("-- returns 0x%08x\n", ret
);
471 HRESULT
CDefView::OnStateChange(UINT uFlags
)
473 HRESULT ret
= S_FALSE
;
475 if (m_pCommDlgBrowser
.p
!= NULL
)
477 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags
);
478 ret
= m_pCommDlgBrowser
->OnStateChange(this, uFlags
);
484 /**********************************************************
485 * set the toolbar of the filedialog buttons
487 * - activates the buttons from the shellbrowser according to
490 void CDefView::CheckToolbar()
496 if (m_pCommDlgBrowser
!= NULL
)
498 m_pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_CHECKBUTTON
,
499 FCIDM_TB_SMALLICON
, (m_FolderSettings
.ViewMode
== FVM_LIST
) ? TRUE
: FALSE
, &result
);
500 m_pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_CHECKBUTTON
,
501 FCIDM_TB_REPORTVIEW
, (m_FolderSettings
.ViewMode
== FVM_DETAILS
) ? TRUE
: FALSE
, &result
);
502 m_pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_ENABLEBUTTON
,
503 FCIDM_TB_SMALLICON
, TRUE
, &result
);
504 m_pShellBrowser
->SendControlMsg(FCW_TOOLBAR
, TB_ENABLEBUTTON
,
505 FCIDM_TB_REPORTVIEW
, TRUE
, &result
);
509 void CDefView::UpdateStatusbar()
511 WCHAR szFormat
[MAX_PATH
] = {0};
512 WCHAR szObjects
[MAX_PATH
] = {0};
515 cSelectedItems
= m_ListView
.GetSelectedCount();
518 LoadStringW(shell32_hInstance
, IDS_OBJECTS_SELECTED
, szFormat
, _countof(szFormat
));
519 StringCchPrintfW(szObjects
, MAX_PATH
, szFormat
, cSelectedItems
);
523 LoadStringW(shell32_hInstance
, IDS_OBJECTS
, szFormat
, _countof(szFormat
));
524 StringCchPrintfW(szObjects
, MAX_PATH
, szFormat
, m_ListView
.GetItemCount());
526 m_pShellBrowser
->SetStatusTextSB(szObjects
);
529 /**********************************************************
531 * ##### helperfunctions for initializing the view #####
534 /**********************************************************
535 * ShellView_CreateList()
537 * - creates the list view window
539 BOOL
CDefView::CreateList()
542 DWORD dwStyle
, dwExStyle
;
547 dwStyle
= WS_TABSTOP
| WS_VISIBLE
| WS_CHILDWINDOW
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
|
548 LVS_SHAREIMAGELISTS
| LVS_EDITLABELS
| LVS_AUTOARRANGE
;
549 dwExStyle
= WS_EX_CLIENTEDGE
;
551 if (m_FolderSettings
.fFlags
& FWF_DESKTOP
)
552 dwStyle
|= LVS_ALIGNLEFT
;
554 dwStyle
|= LVS_ALIGNTOP
| LVS_SHOWSELALWAYS
;
556 ViewMode
= m_FolderSettings
.ViewMode
;
557 hr
= _DoFolderViewCB(SFVM_DEFVIEWMODE
, 0, (LPARAM
)&ViewMode
);
560 if (ViewMode
>= FVM_FIRST
&& ViewMode
<= FVM_LAST
)
561 m_FolderSettings
.ViewMode
= ViewMode
;
563 ERR("Ignoring invalid ViewMode from SFVM_DEFVIEWMODE: %u (was: %u)\n", ViewMode
, m_FolderSettings
.ViewMode
);
566 switch (m_FolderSettings
.ViewMode
)
573 dwStyle
|= LVS_REPORT
;
577 dwStyle
|= LVS_SMALLICON
;
589 if (m_FolderSettings
.fFlags
& FWF_AUTOARRANGE
)
590 dwStyle
|= LVS_AUTOARRANGE
;
592 if (m_FolderSettings
.fFlags
& FWF_SNAPTOGRID
)
593 dwExStyle
|= LVS_EX_SNAPTOGRID
;
595 if (m_FolderSettings
.fFlags
& FWF_DESKTOP
)
596 m_FolderSettings
.fFlags
|= FWF_NOCLIENTEDGE
| FWF_NOSCROLL
;
598 if (m_FolderSettings
.fFlags
& FWF_SINGLESEL
)
599 dwStyle
|= LVS_SINGLESEL
;
601 if (m_FolderSettings
.fFlags
& FWF_NOCLIENTEDGE
)
602 dwExStyle
&= ~WS_EX_CLIENTEDGE
;
604 RECT rcListView
= {0,0,0,0};
605 m_ListView
.Create(m_hWnd
, rcListView
, L
"FolderView", dwStyle
, dwExStyle
, ID_LISTVIEW
);
610 m_sortInfo
.bIsAscending
= TRUE
;
611 m_sortInfo
.nHeaderID
= -1;
612 m_sortInfo
.nLastHeaderID
= -1;
614 /* UpdateShellSettings(); */
618 void CDefView::UpdateListColors()
620 if (m_FolderSettings
.fFlags
& FWF_DESKTOP
)
622 /* Check if drop shadows option is enabled */
623 BOOL bDropShadow
= FALSE
;
624 DWORD cbDropShadow
= sizeof(bDropShadow
);
627 * The desktop ListView always take the default desktop colours, by
628 * remaining transparent and letting user32/win32k paint itself the
629 * desktop background color, if any.
631 m_ListView
.SetBkColor(CLR_NONE
);
633 SHGetValueW(HKEY_CURRENT_USER
, L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
634 L
"ListviewShadow", NULL
, &bDropShadow
, &cbDropShadow
);
637 /* Set the icon background transparent */
638 m_ListView
.SetTextBkColor(CLR_NONE
);
639 m_ListView
.SetTextColor(RGB(255, 255, 255));
640 m_ListView
.SetExtendedListViewStyle(LVS_EX_TRANSPARENTSHADOWTEXT
, LVS_EX_TRANSPARENTSHADOWTEXT
);
644 /* Set the icon background as the same colour as the desktop */
645 COLORREF crDesktop
= GetSysColor(COLOR_DESKTOP
);
646 m_ListView
.SetTextBkColor(crDesktop
);
647 if (GetRValue(crDesktop
) + GetGValue(crDesktop
) + GetBValue(crDesktop
) > 128 * 3)
648 m_ListView
.SetTextColor(RGB(0, 0, 0));
650 m_ListView
.SetTextColor(RGB(255, 255, 255));
651 m_ListView
.SetExtendedListViewStyle(0, LVS_EX_TRANSPARENTSHADOWTEXT
);
656 // text background color
657 COLORREF clrTextBack
= m_viewinfo_data
.clrTextBack
;
658 m_ListView
.SetTextBkColor(clrTextBack
);
662 if (m_viewinfo_data
.clrText
!= CLR_INVALID
)
663 clrText
= m_viewinfo_data
.clrText
;
665 clrText
= GetSysColor(COLOR_WINDOWTEXT
);
667 m_ListView
.SetTextColor(clrText
);
669 // Background is painted by the parent via WM_PRINTCLIENT.
670 m_ListView
.SetExtendedListViewStyle(LVS_EX_TRANSPARENTBKGND
, LVS_EX_TRANSPARENTBKGND
);
674 /**********************************************************
675 * ShellView_InitList()
677 * - adds all needed columns to the shellview
679 BOOL
CDefView::InitList()
683 HIMAGELIST big_icons
, small_icons
;
687 m_ListView
.DeleteAllItems();
689 m_hMenuArrangeModes
= CreateMenu();
693 for (int i
= 0; 1; i
++)
695 if (FAILED(m_pSF2Parent
->GetDetailsOf(NULL
, i
, &sd
)))
697 StrRetToStrNW( szTemp
, 50, &sd
.str
, NULL
);
698 m_ListView
.InsertColumn(i
, szTemp
, sd
.fmt
, sd
.cxChar
* 8);
700 InsertMenuW(m_hMenuArrangeModes
, -1, MF_STRING
, 0x30 + i
, szTemp
);
703 InsertMenuW(m_hMenuArrangeModes
, -1, MF_BYPOSITION
| MF_SEPARATOR
, 0, 0);
707 FIXME("no m_pSF2Parent\n");
710 Shell_GetImageLists(&big_icons
, &small_icons
);
711 m_ListView
.SetImageList(big_icons
, LVSIL_NORMAL
);
712 m_ListView
.SetImageList(small_icons
, LVSIL_SMALL
);
717 /*************************************************************************
718 * ShellView_ListViewCompareItems
720 * Compare Function for the Listview (FileOpen Dialog)
723 * lParam1 [I] the first ItemIdList to compare with
724 * lParam2 [I] the second ItemIdList to compare with
725 * lpData [I] The column ID for the header Ctrl to process
728 * A negative value if the first item should precede the second,
729 * a positive value if the first item should follow the second,
730 * or zero if the two items are equivalent
732 INT CALLBACK
CDefView::ListViewCompareItems(LPARAM lParam1
, LPARAM lParam2
, LPARAM lpData
)
734 PCUIDLIST_RELATIVE pidl1
= reinterpret_cast<PCUIDLIST_RELATIVE
>(lParam1
);
735 PCUIDLIST_RELATIVE pidl2
= reinterpret_cast<PCUIDLIST_RELATIVE
>(lParam2
);
736 CDefView
*pThis
= reinterpret_cast<CDefView
*>(lpData
);
738 HRESULT hres
= pThis
->m_pSFParent
->CompareIDs(pThis
->m_sortInfo
.nHeaderID
, pidl1
, pidl2
);
739 if (FAILED_UNEXPECTEDLY(hres
))
742 SHORT nDiff
= HRESULT_CODE(hres
);
743 if (!pThis
->m_sortInfo
.bIsAscending
)
748 BOOL
CDefView::_Sort()
753 if (m_ListView
.GetWindowLongPtr(GWL_STYLE
) & LVS_NOSORTHEADER
)
756 hHeader
= (HWND
)m_ListView
.SendMessage(LVM_GETHEADER
, 0, 0);
757 ZeroMemory(&hColumn
, sizeof(hColumn
));
759 /* If the sorting column changed, remove the sorting style from the old column */
760 if ( (m_sortInfo
.nLastHeaderID
!= -1) &&
761 (m_sortInfo
.nLastHeaderID
!= m_sortInfo
.nHeaderID
) )
763 hColumn
.mask
= HDI_FORMAT
;
764 Header_GetItem(hHeader
, m_sortInfo
.nLastHeaderID
, &hColumn
);
765 hColumn
.fmt
&= ~(HDF_SORTUP
| HDF_SORTDOWN
);
766 Header_SetItem(hHeader
, m_sortInfo
.nLastHeaderID
, &hColumn
);
769 /* Set the sorting style to the new column */
770 hColumn
.mask
= HDI_FORMAT
;
771 Header_GetItem(hHeader
, m_sortInfo
.nHeaderID
, &hColumn
);
773 hColumn
.fmt
&= (m_sortInfo
.bIsAscending
? ~HDF_SORTDOWN
: ~HDF_SORTUP
);
774 hColumn
.fmt
|= (m_sortInfo
.bIsAscending
? HDF_SORTUP
: HDF_SORTDOWN
);
775 Header_SetItem(hHeader
, m_sortInfo
.nHeaderID
, &hColumn
);
777 /* Sort the list, using the current values of nHeaderID and bIsAscending */
778 m_sortInfo
.nLastHeaderID
= m_sortInfo
.nHeaderID
;
779 return m_ListView
.SortItems(ListViewCompareItems
, this);
782 PCUITEMID_CHILD
CDefView::_PidlByItem(int i
)
784 return reinterpret_cast<PCUITEMID_CHILD
>(m_ListView
.GetItemData(i
));
787 PCUITEMID_CHILD
CDefView::_PidlByItem(LVITEM
& lvItem
)
789 return reinterpret_cast<PCUITEMID_CHILD
>(lvItem
.lParam
);
792 /**********************************************************
793 * LV_FindItemByPidl()
795 int CDefView::LV_FindItemByPidl(PCUITEMID_CHILD pidl
)
797 int cItems
= m_ListView
.GetItemCount();
799 for (int i
= 0; i
<cItems
; i
++)
801 PCUITEMID_CHILD currentpidl
= _PidlByItem(i
);
802 if (ILIsEqual(pidl
, currentpidl
))
808 /**********************************************************
811 int CDefView::LV_AddItem(PCUITEMID_CHILD pidl
)
815 TRACE("(%p)(pidl=%p)\n", this, pidl
);
817 if (_DoFolderViewCB(SFVM_ADDINGOBJECT
, 0, (LPARAM
)pidl
) == S_FALSE
)
820 lvItem
.mask
= LVIF_TEXT
| LVIF_IMAGE
| LVIF_PARAM
; /*set the mask*/
821 lvItem
.iItem
= m_ListView
.GetItemCount(); /*add the item to the end of the list*/
823 lvItem
.lParam
= reinterpret_cast<LPARAM
>(ILClone(pidl
)); /*set the item's data*/
824 lvItem
.pszText
= LPSTR_TEXTCALLBACKW
; /*get text on a callback basis*/
825 lvItem
.iImage
= I_IMAGECALLBACK
; /*get the image on a callback basis*/
826 lvItem
.stateMask
= LVIS_CUT
;
828 return m_ListView
.InsertItem(&lvItem
);
831 /**********************************************************
834 BOOLEAN
CDefView::LV_DeleteItem(PCUITEMID_CHILD pidl
)
838 TRACE("(%p)(pidl=%p)\n", this, pidl
);
840 nIndex
= LV_FindItemByPidl(pidl
);
842 return m_ListView
.DeleteItem(nIndex
);
845 /**********************************************************
848 BOOLEAN
CDefView::LV_RenameItem(PCUITEMID_CHILD pidlOld
, PCUITEMID_CHILD pidlNew
)
853 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", this, pidlOld
, pidlNew
);
855 nItem
= LV_FindItemByPidl(pidlOld
);
859 lvItem
.mask
= LVIF_PARAM
; /* only the pidl */
860 lvItem
.iItem
= nItem
;
862 m_ListView
.GetItem(&lvItem
);
864 LPVOID oldPidl
= reinterpret_cast<LPVOID
>(lvItem
.lParam
); /* Store the old pidl until the new item is replaced */
866 lvItem
.mask
= LVIF_PARAM
| LVIF_IMAGE
| LVIF_TEXT
;
867 lvItem
.iItem
= nItem
;
869 lvItem
.lParam
= reinterpret_cast<LPARAM
>(ILClone(pidlNew
)); /* set the item's data */
870 lvItem
.pszText
= LPSTR_TEXTCALLBACKW
;
871 lvItem
.iImage
= SHMapPIDLToSystemImageListIndex(m_pSFParent
, pidlNew
, 0);
872 m_ListView
.SetItem(&lvItem
);
873 m_ListView
.Update(nItem
);
875 SHFree(oldPidl
); /* Now that the new item is in place, we can safely release the old pidl */
877 return TRUE
; /* FIXME: better handling */
883 /**********************************************************
886 BOOLEAN
CDefView::LV_ProdItem(PCUITEMID_CHILD pidl
)
891 TRACE("(%p)(pidl=%p)\n", this, pidl
);
893 nItem
= LV_FindItemByPidl(pidl
);
897 lvItem
.mask
= LVIF_IMAGE
;
898 lvItem
.iItem
= nItem
;
900 lvItem
.iImage
= SHMapPIDLToSystemImageListIndex(m_pSFParent
, pidl
, 0);
901 m_ListView
.SetItem(&lvItem
);
902 m_ListView
.Update(nItem
);
909 /**********************************************************
910 * ShellView_FillList()
912 * - gets the objectlist from the shellfolder
914 * - fills the list into the view
916 INT CALLBACK
CDefView::fill_list(LPVOID ptr
, LPVOID arg
)
918 PITEMID_CHILD pidl
= static_cast<PITEMID_CHILD
>(ptr
);
919 CDefView
*pThis
= static_cast<CDefView
*>(arg
);
921 /* in a commdlg This works as a filemask*/
922 if (pThis
->IncludeObject(pidl
) == S_OK
)
923 pThis
->LV_AddItem(pidl
);
929 HRESULT
CDefView::FillList()
931 CComPtr
<IEnumIDList
> pEnumIDList
;
936 DWORD dFlags
= SHCONTF_NONFOLDERS
| SHCONTF_FOLDERS
;
937 DWORD dwValue
, cbValue
;
941 /* determine if there is a setting to show all the hidden files/folders */
943 cbValue
= sizeof(dwValue
);
944 SHGetValueW(HKEY_CURRENT_USER
,
945 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
946 L
"Hidden", NULL
, &dwValue
, &cbValue
);
949 dFlags
|= SHCONTF_INCLUDEHIDDEN
;
950 m_ListView
.SendMessageW(LVM_SETCALLBACKMASK
, LVIS_CUT
, 0);
954 cbValue
= sizeof(dwValue
);
955 SHGetValueW(HKEY_CURRENT_USER
,
956 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
957 L
"ShowSuperHidden", NULL
, &dwValue
, &cbValue
);
960 dFlags
|= SHCONTF_INCLUDESUPERHIDDEN
;
961 m_ListView
.SendMessageW(LVM_SETCALLBACKMASK
, LVIS_CUT
, 0);
964 /* get the itemlist from the shfolder */
965 hRes
= m_pSFParent
->EnumObjects(m_hWnd
, dFlags
, &pEnumIDList
);
973 /* create a pointer array */
974 hdpa
= DPA_Create(16);
977 return(E_OUTOFMEMORY
);
980 /* copy the items into the array*/
981 while((S_OK
== pEnumIDList
->Next(1, &pidl
, &dwFetched
)) && dwFetched
)
983 if (DPA_InsertPtr(hdpa
, 0x7fff, pidl
) == -1)
989 /*turn the listview's redrawing off*/
990 m_ListView
.SetRedraw(FALSE
);
992 DPA_DestroyCallback( hdpa
, fill_list
, this);
997 m_pSF2Parent
->GetDefaultColumn(NULL
, (ULONG
*)&m_sortInfo
.nHeaderID
, NULL
);
1001 FIXME("no m_pSF2Parent\n");
1003 m_sortInfo
.bIsAscending
= TRUE
;
1006 if (m_viewinfo_data
.hbmBack
)
1008 ::DeleteObject(m_viewinfo_data
.hbmBack
);
1009 m_viewinfo_data
.hbmBack
= NULL
;
1012 // load custom background image and custom text color
1013 m_viewinfo_data
.cbSize
= sizeof(m_viewinfo_data
);
1014 _DoFolderViewCB(SFVM_GET_CUSTOMVIEWINFO
, 0, (LPARAM
)&m_viewinfo_data
);
1016 /*turn the listview's redrawing back on and force it to draw*/
1017 m_ListView
.SetRedraw(TRUE
);
1021 if (!(m_FolderSettings
.fFlags
& FWF_DESKTOP
))
1024 m_ListView
.InvalidateRect(NULL
, TRUE
);
1027 _DoFolderViewCB(SFVM_LISTREFRESHED
, 0, 0);
1032 LRESULT
CDefView::OnShowWindow(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1034 m_ListView
.UpdateWindow();
1039 LRESULT
CDefView::OnGetDlgCode(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1041 return m_ListView
.SendMessageW(uMsg
, 0, 0);
1044 LRESULT
CDefView::OnDestroy(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1051 DestroyMenu(m_hMenu
);
1054 RevokeDragDrop(m_hWnd
);
1055 SHChangeNotifyDeregister(m_hNotify
);
1057 SHFree(m_pidlParent
);
1058 m_pidlParent
= NULL
;
1064 LRESULT
CDefView::OnEraseBackground(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1066 /* redirect to parent */
1067 if (m_FolderSettings
.fFlags
& (FWF_DESKTOP
| FWF_TRANSPARENT
))
1068 return SendMessageW(GetParent(), WM_ERASEBKGND
, wParam
, lParam
);
1075 DrawTileBitmap(HDC hDC
, LPCRECT prc
, HBITMAP hbm
, INT nWidth
, INT nHeight
, INT dx
, INT dy
)
1077 INT x0
= prc
->left
, y0
= prc
->top
, x1
= prc
->right
, y1
= prc
->bottom
;
1081 HDC hMemDC
= CreateCompatibleDC(hDC
);
1082 HGDIOBJ hbmOld
= SelectObject(hMemDC
, hbm
);
1084 for (INT y
= y0
; y
< y1
; y
+= nHeight
)
1086 for (INT x
= x0
; x
< x1
; x
+= nWidth
)
1088 BitBlt(hDC
, x
, y
, nWidth
, nHeight
, hMemDC
, 0, 0, SRCCOPY
);
1092 SelectObject(hMemDC
, hbmOld
);
1096 LRESULT
CDefView::OnPrintClient(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1098 HDC hDC
= (HDC
)wParam
;
1101 ::GetClientRect(m_ListView
, &rc
);
1103 if (m_viewinfo_data
.hbmBack
)
1106 if (::GetObject(m_viewinfo_data
.hbmBack
, sizeof(BITMAP
), &bm
))
1108 INT dx
= -(::GetScrollPos(m_ListView
, SB_HORZ
) % bm
.bmWidth
);
1109 INT dy
= -(::GetScrollPos(m_ListView
, SB_VERT
) % bm
.bmHeight
);
1110 DrawTileBitmap(hDC
, &rc
, m_viewinfo_data
.hbmBack
, bm
.bmWidth
, bm
.bmHeight
, dx
, dy
);
1115 FillRect(hDC
, &rc
, GetSysColorBrush(COLOR_WINDOW
));
1123 LRESULT
CDefView::OnSysColorChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1125 /* Update desktop labels color */
1128 /* Forward WM_SYSCOLORCHANGE to common controls */
1129 return m_ListView
.SendMessageW(uMsg
, 0, 0);
1132 LRESULT
CDefView::OnGetShellBrowser(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1134 return reinterpret_cast<LRESULT
>(m_pShellBrowser
.p
);
1137 LRESULT
CDefView::OnNCCreate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1144 LRESULT
CDefView::OnNCDestroy(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1151 /**********************************************************
1152 * ShellView_OnCreate()
1154 LRESULT
CDefView::OnCreate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1156 CComPtr
<IDropTarget
> pdt
;
1157 CComPtr
<IPersistFolder2
> ppf2
;
1159 TRACE("%p\n", this);
1161 if (SUCCEEDED(QueryInterface(IID_PPV_ARG(IDropTarget
, &pdt
))))
1163 if (FAILED(RegisterDragDrop(m_hWnd
, pdt
)))
1164 ERR("Registering Drag Drop Failed");
1167 /* register for receiving notifications */
1168 m_pSFParent
->QueryInterface(IID_PPV_ARG(IPersistFolder2
, &ppf2
));
1171 ppf2
->GetCurFolder(&m_pidlParent
);
1182 if (m_FolderSettings
.fFlags
& FWF_DESKTOP
)
1185 m_pShellBrowser
->GetWindow(&hwndSB
);
1186 SetShellWindowEx(hwndSB
, m_ListView
);
1189 SHChangeNotifyEntry ntreg
[1];
1190 ntreg
[0].fRecursive
= FALSE
;
1191 ntreg
[0].pidl
= m_pidlParent
;
1192 m_hNotify
= SHChangeNotifyRegister(m_hWnd
,
1193 SHCNRF_InterruptLevel
| SHCNRF_ShellLevel
|
1195 SHCNE_ALLEVENTS
, SHV_CHANGE_NOTIFY
,
1198 /* _DoFolderViewCB(SFVM_GETNOTIFY, ?? ??) */
1200 m_hAccel
= LoadAcceleratorsW(shell32_hInstance
, MAKEINTRESOURCEW(IDA_SHELLVIEW
));
1207 /**********************************************************
1208 * #### Handling of the menus ####
1211 extern "C" DWORD WINAPI
SHMenuIndexFromID(HMENU hMenu
, UINT uID
);
1213 HMENU
GetSubmenuByID(HMENU hmenu
, UINT id
)
1215 MENUITEMINFOW mii
= {sizeof(mii
), MIIM_SUBMENU
};
1216 if (::GetMenuItemInfoW(hmenu
, id
, FALSE
, &mii
))
1217 return mii
.hSubMenu
;
1222 /* ReallyGetMenuItemID returns the id of an item even if it opens a submenu,
1223 GetMenuItemID returns -1 if the specified item opens a submenu */
1224 UINT
ReallyGetMenuItemID(HMENU hmenu
, int i
)
1226 MENUITEMINFOW mii
= {sizeof(mii
), MIIM_ID
};
1227 if (::GetMenuItemInfoW(hmenu
, i
, TRUE
, &mii
))
1233 HRESULT
CDefView::FillFileMenu()
1235 HMENU hFileMenu
= GetSubmenuByID(m_hMenu
, FCIDM_MENU_FILE
);
1239 /* Cleanup the items added previously */
1240 for (int i
= GetMenuItemCount(hFileMenu
) - 1; i
>= 0; i
--)
1242 UINT id
= GetMenuItemID(hFileMenu
, i
);
1243 if (id
< FCIDM_BROWSERFIRST
|| id
> FCIDM_BROWSERLAST
)
1244 DeleteMenu(hFileMenu
, i
, MF_BYPOSITION
);
1247 m_cidl
= m_ListView
.GetSelectedCount();
1249 /* Store the context menu in m_pCM and keep it in order to invoke the selected command later on */
1250 HRESULT hr
= GetItemObject((m_cidl
? SVGIO_SELECTION
: SVGIO_BACKGROUND
),
1251 IID_PPV_ARG(IContextMenu
, &m_pCM
));
1252 if (FAILED_UNEXPECTEDLY(hr
))
1255 HMENU hmenu
= CreatePopupMenu();
1257 hr
= m_pCM
->QueryContextMenu(hmenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, 0);
1258 if (FAILED_UNEXPECTEDLY(hr
))
1261 // TODO: filter or something
1263 Shell_MergeMenus(hFileMenu
, hmenu
, 0, 0, 0xFFFF, MM_ADDSEPARATOR
| MM_SUBMENUSHAVEIDS
);
1265 ::DestroyMenu(hmenu
);
1270 HRESULT
CDefView::FillEditMenu()
1272 HMENU hEditMenu
= GetSubmenuByID(m_hMenu
, FCIDM_MENU_EDIT
);
1276 HMENU hmenuContents
= ::LoadMenuW(shell32_hInstance
, L
"MENU_003");
1280 Shell_MergeMenus(hEditMenu
, hmenuContents
, 0, 0, 0xFFFF, 0);
1282 ::DestroyMenu(hmenuContents
);
1287 HRESULT
CDefView::FillViewMenu()
1289 HMENU hViewMenu
= GetSubmenuByID(m_hMenu
, FCIDM_MENU_VIEW
);
1293 m_hMenuViewModes
= ::LoadMenuW(shell32_hInstance
, L
"MENU_001");
1294 if (!m_hMenuViewModes
)
1297 UINT i
= SHMenuIndexFromID(hViewMenu
, FCIDM_MENU_VIEW_SEP_OPTIONS
);
1298 Shell_MergeMenus(hViewMenu
, m_hMenuViewModes
, i
, 0, 0xFFFF, MM_ADDSEPARATOR
| MM_DONTREMOVESEPS
| MM_SUBMENUSHAVEIDS
);
1303 HRESULT
CDefView::FillArrangeAsMenu(HMENU hmenuArrange
)
1305 /* We only need to fill this once */
1306 if (GetMenuItemID(hmenuArrange
, 0) == FCIDM_SHVIEW_AUTOARRANGE
)
1308 Shell_MergeMenus(hmenuArrange
, m_hMenuArrangeModes
, 0, 0, 0xFFFF,0);
1311 /* Also check the menu item according to which we sort */
1312 CheckMenuRadioItem(hmenuArrange
,
1315 m_sortInfo
.nHeaderID
+ 0x30,
1318 if (m_FolderSettings
.ViewMode
== FVM_DETAILS
|| m_FolderSettings
.ViewMode
== FVM_LIST
)
1320 EnableMenuItem(hmenuArrange
, FCIDM_SHVIEW_AUTOARRANGE
, MF_BYCOMMAND
| MF_GRAYED
);
1321 EnableMenuItem(hmenuArrange
, FCIDM_SHVIEW_ALIGNTOGRID
, MF_BYCOMMAND
| MF_GRAYED
);
1325 EnableMenuItem(hmenuArrange
, FCIDM_SHVIEW_AUTOARRANGE
, MF_BYCOMMAND
);
1326 EnableMenuItem(hmenuArrange
, FCIDM_SHVIEW_ALIGNTOGRID
, MF_BYCOMMAND
);
1328 if (GetAutoArrange() == S_OK
)
1329 CheckMenuItem(hmenuArrange
, FCIDM_SHVIEW_AUTOARRANGE
, MF_CHECKED
);
1331 CheckMenuItem(hmenuArrange
, FCIDM_SHVIEW_AUTOARRANGE
, MF_UNCHECKED
);
1333 if (_GetSnapToGrid() == S_OK
)
1334 CheckMenuItem(hmenuArrange
, FCIDM_SHVIEW_ALIGNTOGRID
, MF_CHECKED
);
1336 CheckMenuItem(hmenuArrange
, FCIDM_SHVIEW_ALIGNTOGRID
, MF_UNCHECKED
);
1343 HRESULT
CDefView::CheckViewMode(HMENU hmenuView
)
1345 if (m_FolderSettings
.ViewMode
>= FVM_FIRST
&& m_FolderSettings
.ViewMode
<= FVM_LAST
)
1347 UINT iItemFirst
= FCIDM_SHVIEW_BIGICON
;
1348 UINT iItemLast
= iItemFirst
+ FVM_LAST
- FVM_FIRST
;
1349 UINT iItem
= iItemFirst
+ m_FolderSettings
.ViewMode
- FVM_FIRST
;
1350 CheckMenuRadioItem(hmenuView
, iItemFirst
, iItemLast
, iItem
, MF_BYCOMMAND
);
1356 /**********************************************************
1357 * ShellView_GetSelections()
1359 * - fills the m_apidl list with the selected objects
1362 * number of selected items
1364 UINT
CDefView::GetSelections()
1368 m_cidl
= m_ListView
.GetSelectedCount();
1369 m_apidl
= static_cast<PCUITEMID_CHILD
*>(SHAlloc(m_cidl
* sizeof(PCUITEMID_CHILD
)));
1376 TRACE("-- Items selected =%u\n", m_cidl
);
1380 while ((lvIndex
= m_ListView
.GetNextItem(lvIndex
, LVNI_SELECTED
)) > -1)
1382 m_apidl
[i
] = _PidlByItem(lvIndex
);
1386 TRACE("-- selected Item found\n");
1392 HRESULT
CDefView::InvokeContextMenuCommand(UINT uCommand
)
1394 CMINVOKECOMMANDINFO cmi
;
1396 ZeroMemory(&cmi
, sizeof(cmi
));
1397 cmi
.cbSize
= sizeof(cmi
);
1398 cmi
.lpVerb
= MAKEINTRESOURCEA(uCommand
);
1401 if (GetKeyState(VK_SHIFT
) & 0x8000)
1402 cmi
.fMask
|= CMIC_MASK_SHIFT_DOWN
;
1404 if (GetKeyState(VK_CONTROL
) & 0x8000)
1405 cmi
.fMask
|= CMIC_MASK_CONTROL_DOWN
;
1407 HRESULT hr
= m_pCM
->InvokeCommand(&cmi
);
1408 if (FAILED_UNEXPECTEDLY(hr
))
1414 /**********************************************************
1415 * ShellView_OpenSelectedItems()
1417 HRESULT
CDefView::OpenSelectedItems()
1423 m_cidl
= m_ListView
.GetSelectedCount();
1427 hResult
= OnDefaultCommand();
1428 if (hResult
== S_OK
)
1431 hMenu
= CreatePopupMenu();
1435 hResult
= GetItemObject(SVGIO_SELECTION
, IID_PPV_ARG(IContextMenu
, &m_pCM
));
1436 if (FAILED_UNEXPECTEDLY(hResult
))
1439 hResult
= m_pCM
->QueryContextMenu(hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, CMF_DEFAULTONLY
);
1440 if (FAILED_UNEXPECTEDLY(hResult
))
1443 uCommand
= GetMenuDefaultItem(hMenu
, FALSE
, 0);
1444 if (uCommand
== (UINT
)-1)
1450 InvokeContextMenuCommand(uCommand
);
1459 IUnknown_SetSite(m_pCM
, NULL
);
1466 /**********************************************************
1467 * ShellView_DoContextMenu()
1469 LRESULT
CDefView::OnContextMenu(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1475 TRACE("(%p)\n", this);
1477 m_hContextMenu
= CreatePopupMenu();
1478 if (!m_hContextMenu
)
1481 if (lParam
!= ~0) // unless app key (menu key) was pressed
1483 x
= GET_X_LPARAM(lParam
);
1484 y
= GET_Y_LPARAM(lParam
);
1486 LV_HITTESTINFO hittest
= { { x
, y
} };
1487 ScreenToClient(&hittest
.pt
);
1488 m_ListView
.HitTest(&hittest
);
1490 // Right-Clicked item is selected? If selected, no selection change.
1491 // If not selected, then reset the selection and select the item.
1492 if ((hittest
.flags
& LVHT_ONITEM
) &&
1493 m_ListView
.GetItemState(hittest
.iItem
, LVIS_SELECTED
) != LVIS_SELECTED
)
1495 SelectItem(hittest
.iItem
, SVSI_SELECT
| SVSI_DESELECTOTHERS
| SVSI_ENSUREVISIBLE
);
1499 m_cidl
= m_ListView
.GetSelectedCount();
1501 hResult
= GetItemObject( m_cidl
? SVGIO_SELECTION
: SVGIO_BACKGROUND
, IID_PPV_ARG(IContextMenu
, &m_pCM
));
1502 if (FAILED_UNEXPECTEDLY(hResult
))
1505 /* Use 1 as the first id as we want 0 the mean that the user canceled the menu */
1506 hResult
= m_pCM
->QueryContextMenu(m_hContextMenu
, 0, CONTEXT_MENU_BASE_ID
, FCIDM_SHVIEWLAST
, CMF_NORMAL
);
1507 if (FAILED_UNEXPECTEDLY(hResult
))
1510 /* There is no position requested, so try to find one */
1513 HWND hFocus
= ::GetFocus();
1517 if (hFocus
== m_ListView
.m_hWnd
|| m_ListView
.IsChild(hFocus
))
1519 /* Is there an item focused and selected? */
1520 lvIndex
= m_ListView
.GetNextItem(-1, LVIS_SELECTED
|LVIS_FOCUSED
);
1521 /* If not, find the first selected item */
1523 lvIndex
= m_ListView
.GetNextItem(-1, LVIS_SELECTED
);
1526 /* We got something */
1529 /* Let's find the center of the icon */
1530 RECT rc
= { LVIR_ICON
};
1531 m_ListView
.SendMessage(LVM_GETITEMRECT
, lvIndex
, (LPARAM
)&rc
);
1532 pt
.x
= (rc
.right
+ rc
.left
) / 2;
1533 pt
.y
= (rc
.bottom
+ rc
.top
) / 2;
1537 /* We have to drop it somewhere.. */
1541 m_ListView
.ClientToScreen(&pt
);
1546 uCommand
= TrackPopupMenu(m_hContextMenu
,
1547 TPM_LEFTALIGN
| TPM_RETURNCMD
| TPM_LEFTBUTTON
| TPM_RIGHTBUTTON
,
1548 x
, y
, 0, m_hWnd
, NULL
);
1552 if (uCommand
== FCIDM_SHVIEW_OPEN
&& OnDefaultCommand() == S_OK
)
1555 InvokeContextMenuCommand(uCommand
- CONTEXT_MENU_BASE_ID
);
1560 IUnknown_SetSite(m_pCM
, NULL
);
1566 DestroyMenu(m_hContextMenu
);
1567 m_hContextMenu
= NULL
;
1573 LRESULT
CDefView::OnExplorerCommand(UINT uCommand
, BOOL bUseSelection
)
1578 hMenu
= CreatePopupMenu();
1582 hResult
= GetItemObject( bUseSelection
? SVGIO_SELECTION
: SVGIO_BACKGROUND
, IID_PPV_ARG(IContextMenu
, &m_pCM
));
1583 if (FAILED_UNEXPECTEDLY( hResult
))
1586 hResult
= m_pCM
->QueryContextMenu(hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, CMF_NORMAL
);
1587 if (FAILED_UNEXPECTEDLY( hResult
))
1592 // FIXME: we should cache this....
1593 SFGAOF rfg
= SFGAO_BROWSABLE
| SFGAO_CANCOPY
| SFGAO_CANLINK
| SFGAO_CANMOVE
| SFGAO_CANDELETE
| SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
;
1594 hResult
= m_pSFParent
->GetAttributesOf(m_cidl
, m_apidl
, &rfg
);
1595 if (FAILED_UNEXPECTEDLY(hResult
))
1598 if (!(rfg
& SFGAO_CANMOVE
) && uCommand
== FCIDM_SHVIEW_CUT
)
1600 if (!(rfg
& SFGAO_CANCOPY
) && uCommand
== FCIDM_SHVIEW_COPY
)
1602 if (!(rfg
& SFGAO_CANDELETE
) && uCommand
== FCIDM_SHVIEW_DELETE
)
1604 if (!(rfg
& SFGAO_CANRENAME
) && uCommand
== FCIDM_SHVIEW_RENAME
)
1606 if (!(rfg
& SFGAO_HASPROPSHEET
) && uCommand
== FCIDM_SHVIEW_PROPERTIES
)
1610 InvokeContextMenuCommand(uCommand
);
1615 IUnknown_SetSite(m_pCM
, NULL
);
1625 /**********************************************************
1626 * ##### message handling #####
1629 /**********************************************************
1630 * ShellView_OnSize()
1632 LRESULT
CDefView::OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1634 WORD wWidth
, wHeight
;
1636 wWidth
= LOWORD(lParam
);
1637 wHeight
= HIWORD(lParam
);
1639 TRACE("%p width=%u height=%u\n", this, wWidth
, wHeight
);
1641 /* Resize the ListView to fit our window */
1644 ::MoveWindow(m_ListView
, 0, 0, wWidth
, wHeight
, TRUE
);
1647 _DoFolderViewCB(SFVM_SIZE
, 0, 0);
1652 /**********************************************************
1653 * ShellView_OnDeactivate()
1658 void CDefView::OnDeactivate()
1660 TRACE("%p\n", this);
1662 if (m_uState
!= SVUIA_DEACTIVATE
)
1664 // TODO: cleanup menu after deactivation
1666 m_uState
= SVUIA_DEACTIVATE
;
1670 void CDefView::DoActivate(UINT uState
)
1672 TRACE("%p uState=%x\n", this, uState
);
1674 /*don't do anything if the state isn't really changing */
1675 if (m_uState
== uState
)
1680 if (uState
== SVUIA_DEACTIVATE
)
1686 if(m_hMenu
&& !m_bmenuBarInitialized
)
1690 m_pShellBrowser
->SetMenuSB(m_hMenu
, 0, m_hWnd
);
1691 m_bmenuBarInitialized
= TRUE
;
1694 if (SVUIA_ACTIVATE_FOCUS
== uState
)
1696 m_ListView
.SetFocus();
1704 /**********************************************************
1705 * ShellView_OnActivate()
1707 LRESULT
CDefView::OnActivate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1709 DoActivate(SVUIA_ACTIVATE_FOCUS
);
1713 /**********************************************************
1714 * ShellView_OnSetFocus()
1717 LRESULT
CDefView::OnSetFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1719 TRACE("%p\n", this);
1721 /* Tell the browser one of our windows has received the focus. This
1722 should always be done before merging menus (OnActivate merges the
1723 menus) if one of our windows has the focus.*/
1725 m_pShellBrowser
->OnViewWindowActive(this);
1726 DoActivate(SVUIA_ACTIVATE_FOCUS
);
1728 /* Set the focus to the listview */
1729 m_ListView
.SetFocus();
1731 /* Notify the ICommDlgBrowser interface */
1732 OnStateChange(CDBOSC_SETFOCUS
);
1737 /**********************************************************
1738 * ShellView_OnKillFocus()
1740 LRESULT
CDefView::OnKillFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1742 TRACE("(%p) stub\n", this);
1744 DoActivate(SVUIA_ACTIVATE_NOFOCUS
);
1745 /* Notify the ICommDlgBrowser */
1746 OnStateChange(CDBOSC_KILLFOCUS
);
1751 /**********************************************************
1752 * ShellView_OnCommand()
1755 * the CmdID's are the ones from the context menu
1757 LRESULT
CDefView::OnCommand(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1764 dwCmdID
= GET_WM_COMMAND_ID(wParam
, lParam
);
1765 dwCmd
= GET_WM_COMMAND_CMD(wParam
, lParam
);
1766 hwndCmd
= GET_WM_COMMAND_HWND(wParam
, lParam
);
1768 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n", this, dwCmdID
, dwCmd
, hwndCmd
);
1772 case FCIDM_SHVIEW_SMALLICON
:
1773 m_FolderSettings
.ViewMode
= FVM_SMALLICON
;
1774 m_ListView
.ModifyStyle(LVS_TYPEMASK
, LVS_SMALLICON
);
1778 case FCIDM_SHVIEW_BIGICON
:
1779 m_FolderSettings
.ViewMode
= FVM_ICON
;
1780 m_ListView
.ModifyStyle(LVS_TYPEMASK
, LVS_ICON
);
1784 case FCIDM_SHVIEW_LISTVIEW
:
1785 m_FolderSettings
.ViewMode
= FVM_LIST
;
1786 m_ListView
.ModifyStyle(LVS_TYPEMASK
, LVS_LIST
);
1790 case FCIDM_SHVIEW_REPORTVIEW
:
1791 m_FolderSettings
.ViewMode
= FVM_DETAILS
;
1792 m_ListView
.ModifyStyle(LVS_TYPEMASK
, LVS_REPORT
);
1796 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1801 m_sortInfo
.nHeaderID
= dwCmdID
- 0x30;
1802 m_sortInfo
.bIsAscending
= TRUE
;
1806 case FCIDM_SHVIEW_SNAPTOGRID
:
1807 m_ListView
.Arrange(LVA_SNAPTOGRID
);
1809 case FCIDM_SHVIEW_ALIGNTOGRID
:
1810 if (_GetSnapToGrid() == S_OK
)
1811 m_ListView
.SetExtendedListViewStyle(0, LVS_EX_SNAPTOGRID
);
1815 case FCIDM_SHVIEW_AUTOARRANGE
:
1816 if (GetAutoArrange() == S_OK
)
1817 m_ListView
.ModifyStyle(LVS_AUTOARRANGE
, 0);
1821 case FCIDM_SHVIEW_SELECTALL
:
1822 m_ListView
.SetItemState(-1, LVIS_SELECTED
, LVIS_SELECTED
);
1825 case FCIDM_SHVIEW_INVERTSELECTION
:
1826 nCount
= m_ListView
.GetItemCount();
1827 for (int i
=0; i
< nCount
; i
++)
1828 m_ListView
.SetItemState(i
, m_ListView
.GetItemState(i
, LVIS_SELECTED
) ? 0 : LVIS_SELECTED
, LVIS_SELECTED
);
1831 case FCIDM_SHVIEW_REFRESH
:
1835 case FCIDM_SHVIEW_DELETE
:
1836 case FCIDM_SHVIEW_CUT
:
1837 case FCIDM_SHVIEW_COPY
:
1838 case FCIDM_SHVIEW_RENAME
:
1839 case FCIDM_SHVIEW_PROPERTIES
:
1840 case FCIDM_SHVIEW_COPYTO
:
1841 case FCIDM_SHVIEW_MOVETO
:
1842 if (SHRestricted(REST_NOVIEWCONTEXTMENU
))
1845 return OnExplorerCommand(dwCmdID
, TRUE
);
1847 case FCIDM_SHVIEW_INSERT
:
1848 case FCIDM_SHVIEW_UNDO
:
1849 case FCIDM_SHVIEW_INSERTLINK
:
1850 case FCIDM_SHVIEW_NEWFOLDER
:
1851 return OnExplorerCommand(dwCmdID
, FALSE
);
1853 /* WM_COMMAND messages from the file menu are routed to the CDefView so as to let m_pCM handle the command */
1854 if (m_pCM
&& dwCmd
== 0)
1856 InvokeContextMenuCommand(dwCmdID
);
1864 SelectExtOnRename(void)
1868 DWORD dwValue
= FALSE
, cbValue
;
1870 error
= RegOpenKeyExW(HKEY_CURRENT_USER
,
1871 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer",
1872 0, KEY_READ
, &hKey
);
1876 cbValue
= sizeof(dwValue
);
1877 RegQueryValueExW(hKey
, L
"SelectExtOnRename", NULL
, NULL
, (LPBYTE
)&dwValue
, &cbValue
);
1883 /**********************************************************
1884 * ShellView_OnNotify()
1887 LRESULT
CDefView::OnNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1891 LPNMLISTVIEW lpnmlv
;
1892 NMLVDISPINFOW
*lpdi
;
1893 PCUITEMID_CHILD pidl
;
1897 lpnmh
= (LPNMHDR
)lParam
;
1898 lpnmlv
= (LPNMLISTVIEW
)lpnmh
;
1899 lpdi
= (NMLVDISPINFOW
*)lpnmh
;
1901 TRACE("%p CtlID=%u lpnmh->code=%x\n", this, CtlID
, lpnmh
->code
);
1903 switch (lpnmh
->code
)
1906 TRACE("-- NM_SETFOCUS %p\n", this);
1907 OnSetFocus(0, 0, 0, unused
);
1911 TRACE("-- NM_KILLFOCUS %p\n", this);
1913 /* Notify the ICommDlgBrowser interface */
1914 OnStateChange(CDBOSC_KILLFOCUS
);
1918 TRACE("-- NM_CUSTOMDRAW %p\n", this);
1919 return CDRF_DODEFAULT
;
1921 case NM_RELEASEDCAPTURE
:
1922 TRACE("-- NM_RELEASEDCAPTURE %p\n", this);
1926 TRACE("-- NM_CLICK %p\n", this);
1930 TRACE("-- NM_RCLICK %p\n", this);
1934 TRACE("-- NM_DBLCLK %p\n", this);
1935 OpenSelectedItems();
1939 TRACE("-- NM_RETURN %p\n", this);
1940 OpenSelectedItems();
1944 TRACE("-- HDN_ENDTRACKW %p\n", this);
1945 /*nColumn1 = m_ListView.GetColumnWidth(0);
1946 nColumn2 = m_ListView.GetColumnWidth(1);*/
1949 case LVN_DELETEITEM
:
1950 TRACE("-- LVN_DELETEITEM %p\n", this);
1952 /*delete the pidl because we made a copy of it*/
1953 SHFree(reinterpret_cast<LPVOID
>(lpnmlv
->lParam
));
1957 case LVN_DELETEALLITEMS
:
1958 TRACE("-- LVN_DELETEALLITEMS %p\n", this);
1961 case LVN_INSERTITEM
:
1962 TRACE("-- LVN_INSERTITEM (STUB)%p\n", this);
1965 case LVN_ITEMACTIVATE
:
1966 TRACE("-- LVN_ITEMACTIVATE %p\n", this);
1967 OnStateChange(CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1970 case LVN_COLUMNCLICK
:
1971 m_sortInfo
.nHeaderID
= lpnmlv
->iSubItem
;
1972 if (m_sortInfo
.nLastHeaderID
== m_sortInfo
.nHeaderID
)
1973 m_sortInfo
.bIsAscending
= !m_sortInfo
.bIsAscending
;
1975 m_sortInfo
.bIsAscending
= TRUE
;
1979 case LVN_GETDISPINFOA
:
1980 case LVN_GETDISPINFOW
:
1981 TRACE("-- LVN_GETDISPINFO %p\n", this);
1982 pidl
= _PidlByItem(lpdi
->item
);
1984 if (lpdi
->item
.mask
& LVIF_TEXT
) /* text requested */
1989 if (FAILED_UNEXPECTEDLY(m_pSF2Parent
->GetDetailsOf(pidl
, lpdi
->item
.iSubItem
, &sd
)))
1992 if (lpnmh
->code
== LVN_GETDISPINFOA
)
1994 /* shouldn't happen */
1995 NMLVDISPINFOA
*lpdiA
= (NMLVDISPINFOA
*)lpnmh
;
1996 StrRetToStrNA( lpdiA
->item
.pszText
, lpdiA
->item
.cchTextMax
, &sd
.str
, NULL
);
1997 TRACE("-- text=%s\n", lpdiA
->item
.pszText
);
1999 else /* LVN_GETDISPINFOW */
2001 StrRetToStrNW( lpdi
->item
.pszText
, lpdi
->item
.cchTextMax
, &sd
.str
, NULL
);
2002 TRACE("-- text=%s\n", debugstr_w(lpdi
->item
.pszText
));
2007 FIXME("no m_pSF2Parent\n");
2010 if(lpdi
->item
.mask
& LVIF_IMAGE
) /* image requested */
2012 lpdi
->item
.iImage
= SHMapPIDLToSystemImageListIndex(m_pSFParent
, pidl
, 0);
2014 if(lpdi
->item
.mask
& LVIF_STATE
)
2016 ULONG attributes
= SFGAO_HIDDEN
;
2017 if (SUCCEEDED(m_pSFParent
->GetAttributesOf(1, &pidl
, &attributes
)))
2019 if (attributes
& SFGAO_HIDDEN
)
2021 lpdi
->item
.state
|= LVIS_CUT
;
2025 lpdi
->item
.mask
|= LVIF_DI_SETITEM
;
2028 case LVN_ITEMCHANGED
:
2029 TRACE("-- LVN_ITEMCHANGED %p\n", this);
2030 OnStateChange(CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
2032 _DoFolderViewCB(SFVM_SELECTIONCHANGED
, NULL
/* FIXME */, NULL
/* FIXME */);
2036 case LVN_BEGINRDRAG
:
2037 TRACE("-- LVN_BEGINDRAG\n");
2039 if (GetSelections())
2041 CComPtr
<IDataObject
> pda
;
2042 DWORD dwAttributes
= SFGAO_CANCOPY
| SFGAO_CANLINK
;
2043 DWORD dwEffect
= DROPEFFECT_MOVE
;
2045 if (SUCCEEDED(m_pSFParent
->GetUIObjectOf(m_hWnd
, m_cidl
, m_apidl
, IID_NULL_PPV_ARG(IDataObject
, &pda
))))
2047 LPNMLISTVIEW params
= (LPNMLISTVIEW
)lParam
;
2049 if (SUCCEEDED(m_pSFParent
->GetAttributesOf(m_cidl
, m_apidl
, &dwAttributes
)))
2051 dwEffect
|= dwAttributes
& (SFGAO_CANCOPY
| SFGAO_CANLINK
);
2054 CComPtr
<IAsyncOperation
> piaso
;
2055 if (SUCCEEDED(pda
->QueryInterface(IID_PPV_ARG(IAsyncOperation
, &piaso
))))
2057 piaso
->SetAsyncMode(TRUE
);
2062 m_pSourceDataObject
= pda
;
2063 m_ptFirstMousePos
= params
->ptAction
;
2064 ClientToScreen(&m_ptFirstMousePos
);
2065 ::ClientToListView(m_ListView
, &m_ptFirstMousePos
);
2067 HIMAGELIST big_icons
, small_icons
;
2068 Shell_GetImageLists(&big_icons
, &small_icons
);
2069 PCUITEMID_CHILD pidl
= _PidlByItem(params
->iItem
);
2070 int iIcon
= SHMapPIDLToSystemImageListIndex(m_pSFParent
, pidl
, 0);
2072 m_ListView
.GetItemPosition(params
->iItem
, &ptItem
);
2074 ImageList_BeginDrag(big_icons
, iIcon
, params
->ptAction
.x
- ptItem
.x
, params
->ptAction
.y
- ptItem
.y
);
2076 DoDragDrop(pda
, this, dwEffect
, &dwEffect2
);
2078 m_pSourceDataObject
.Release();
2083 case LVN_BEGINLABELEDITW
:
2085 DWORD dwAttr
= SFGAO_CANRENAME
;
2086 pidl
= _PidlByItem(lpdi
->item
);
2088 TRACE("-- LVN_BEGINLABELEDITW %p\n", this);
2090 m_pSFParent
->GetAttributesOf(1, &pidl
, &dwAttr
);
2091 if (SFGAO_CANRENAME
& dwAttr
)
2093 HWND hEdit
= reinterpret_cast<HWND
>(m_ListView
.SendMessage(LVM_GETEDITCONTROL
));
2094 SHLimitInputEdit(hEdit
, m_pSFParent
);
2096 /* smartass-renaming: See CORE-15242 */
2097 if (!(dwAttr
& SFGAO_FOLDER
) && (dwAttr
& SFGAO_FILESYSTEM
) &&
2098 (lpdi
->item
.mask
& LVIF_TEXT
) && !SelectExtOnRename())
2100 WCHAR szFullPath
[MAX_PATH
];
2101 PIDLIST_ABSOLUTE pidlFull
= ILCombine(m_pidlParent
, pidl
);
2102 SHGetPathFromIDListW(pidlFull
, szFullPath
);
2104 if (!SHELL_FS_HideExtension(szFullPath
))
2106 LPWSTR pszText
= lpdi
->item
.pszText
;
2107 LPWSTR pchDotExt
= PathFindExtensionW(pszText
);
2108 ::PostMessageW(hEdit
, EM_SETSEL
, 0, pchDotExt
- pszText
);
2109 ::PostMessageW(hEdit
, EM_SCROLLCARET
, 0, 0);
2122 case LVN_ENDLABELEDITW
:
2124 TRACE("-- LVN_ENDLABELEDITW %p\n", this);
2126 m_isEditing
= FALSE
;
2128 if (lpdi
->item
.pszText
)
2133 pidl
= _PidlByItem(lpdi
->item
);
2134 PITEMID_CHILD pidlNew
= NULL
;
2135 hr
= m_pSFParent
->SetNameOf(0, pidl
, lpdi
->item
.pszText
, SHGDN_INFOLDER
, &pidlNew
);
2137 if (SUCCEEDED(hr
) && pidlNew
)
2139 lvItem
.mask
= LVIF_PARAM
|LVIF_IMAGE
;
2140 lvItem
.iItem
= lpdi
->item
.iItem
;
2141 lvItem
.iSubItem
= 0;
2142 lvItem
.lParam
= reinterpret_cast<LPARAM
>(pidlNew
);
2143 lvItem
.iImage
= SHMapPIDLToSystemImageListIndex(m_pSFParent
, pidlNew
, 0);
2144 m_ListView
.SetItem(&lvItem
);
2145 m_ListView
.Update(lpdi
->item
.iItem
);
2154 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh
->code
);
2162 * This is just a quick hack to make the desktop work correctly.
2163 * ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the way that
2164 * a folder should know if it should update upon a change notification.
2165 * It is exported by merged folders at a minimum.
2167 static BOOL
ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1
, PCIDLIST_ABSOLUTE pidl2
)
2169 if (!pidl1
|| !pidl2
)
2171 if (ILIsParent(pidl1
, pidl2
, TRUE
))
2174 if (_ILIsDesktop(pidl1
))
2176 PIDLIST_ABSOLUTE deskpidl
;
2177 SHGetFolderLocation(NULL
, CSIDL_DESKTOPDIRECTORY
, NULL
, 0, &deskpidl
);
2178 if (ILIsParent(deskpidl
, pidl2
, TRUE
))
2184 SHGetFolderLocation(NULL
, CSIDL_COMMON_DESKTOPDIRECTORY
, NULL
, 0, &deskpidl
);
2185 if (ILIsParent(deskpidl
, pidl2
, TRUE
))
2193 WCHAR szPath1
[MAX_PATH
], szPath2
[MAX_PATH
];
2194 LPITEMIDLIST pidl2Clone
= ILClone(pidl2
);
2195 ILRemoveLastID(pidl2Clone
);
2196 if (SHGetPathFromIDListW(pidl1
, szPath1
) &&
2197 SHGetPathFromIDListW(pidl2Clone
, szPath2
))
2199 if (lstrcmpiW(szPath1
, szPath2
) == 0)
2210 /**********************************************************
2211 * ShellView_OnChange()
2213 LRESULT
CDefView::OnChangeNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2215 HANDLE hChange
= (HANDLE
)wParam
;
2216 DWORD dwProcID
= (DWORD
)lParam
;
2217 PIDLIST_ABSOLUTE
*Pidls
;
2219 HANDLE hLock
= SHChangeNotification_Lock(hChange
, dwProcID
, &Pidls
, &lEvent
);
2222 ERR("hLock == NULL\n");
2226 BOOL bParent0
= ILIsParentOrSpecialParent(m_pidlParent
, Pidls
[0]);
2227 BOOL bParent1
= ILIsParentOrSpecialParent(m_pidlParent
, Pidls
[1]);
2229 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls
[0], Pidls
[1], lParam
);
2231 lEvent
&= ~SHCNE_INTERRUPT
;
2238 if (LV_FindItemByPidl(ILFindLastID(Pidls
[0])) == -1)
2240 LV_AddItem(ILFindLastID(Pidls
[0]));
2244 LV_ProdItem(ILFindLastID(Pidls
[0]));
2252 LV_DeleteItem(ILFindLastID(Pidls
[0]));
2255 case SHCNE_RENAMEFOLDER
:
2256 case SHCNE_RENAMEITEM
:
2257 if (bParent0
&& bParent1
)
2258 LV_RenameItem(ILFindLastID(Pidls
[0]), ILFindLastID(Pidls
[1]));
2260 LV_DeleteItem(ILFindLastID(Pidls
[0]));
2262 LV_AddItem(ILFindLastID(Pidls
[1]));
2265 case SHCNE_UPDATEITEM
:
2267 LV_RenameItem(ILFindLastID(Pidls
[0]), ILFindLastID(Pidls
[0]));
2270 case SHCNE_UPDATEDIR
:
2275 SHChangeNotification_Unlock(hLock
);
2279 HRESULT
SHGetMenuIdFromMenuMsg(UINT uMsg
, LPARAM lParam
, UINT
*CmdId
);
2280 HRESULT
SHSetMenuIdInMenuMsg(UINT uMsg
, LPARAM lParam
, UINT CmdId
);
2282 /**********************************************************
2283 * CDefView::OnCustomItem
2285 LRESULT
CDefView::OnCustomItem(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2290 ERR("no menu!!!\n");
2294 /* The lParam of WM_DRAWITEM WM_MEASUREITEM contain a menu id and this also needs to
2295 be changed to a menu identifier offset */
2297 HRESULT hres
= SHGetMenuIdFromMenuMsg(uMsg
, lParam
, &CmdID
);
2298 if (SUCCEEDED(hres
))
2299 SHSetMenuIdInMenuMsg(uMsg
, lParam
, CmdID
- CONTEXT_MENU_BASE_ID
);
2301 /* Forward the message to the IContextMenu2 */
2303 hres
= SHForwardContextMenuMsg(m_pCM
, uMsg
, wParam
, lParam
, &result
, TRUE
);
2305 return (SUCCEEDED(hres
));
2308 LRESULT
CDefView::OnSettingChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2310 /* Wallpaper setting affects drop shadows effect */
2311 if (wParam
== SPI_SETDESKWALLPAPER
|| wParam
== 0)
2317 /**********************************************************
2318 * CDefView::OnInitMenuPopup
2320 LRESULT
CDefView::OnInitMenuPopup(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2322 HMENU hmenu
= (HMENU
) wParam
;
2323 int nPos
= LOWORD(lParam
);
2326 OnCustomItem(uMsg
, wParam
, lParam
, bHandled
);
2328 HMENU hViewMenu
= GetSubmenuByID(m_hMenu
, FCIDM_MENU_VIEW
);
2330 if (GetSelections() == 0)
2332 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_CUT
, MF_GRAYED
);
2333 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_COPY
, MF_GRAYED
);
2334 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_RENAME
, MF_GRAYED
);
2335 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_COPYTO
, MF_GRAYED
);
2336 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_MOVETO
, MF_GRAYED
);
2337 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_DELETE
, MF_GRAYED
);
2341 // FIXME: Check copyable
2342 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_CUT
, MF_ENABLED
);
2343 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_COPY
, MF_ENABLED
);
2344 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_RENAME
, MF_ENABLED
);
2345 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_COPYTO
, MF_ENABLED
);
2346 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_MOVETO
, MF_ENABLED
);
2347 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_DELETE
, MF_ENABLED
);
2350 /* Lets try to find out what the hell wParam is */
2351 if (hmenu
== GetSubMenu(m_hMenu
, nPos
))
2352 menuItemId
= ReallyGetMenuItemID(m_hMenu
, nPos
);
2353 else if (hViewMenu
&& hmenu
== GetSubMenu(hViewMenu
, nPos
))
2354 menuItemId
= ReallyGetMenuItemID(hViewMenu
, nPos
);
2355 else if (m_hContextMenu
&& hmenu
== GetSubMenu(m_hContextMenu
, nPos
))
2356 menuItemId
= ReallyGetMenuItemID(m_hContextMenu
, nPos
);
2362 case FCIDM_MENU_FILE
:
2365 case FCIDM_MENU_VIEW
:
2366 case FCIDM_SHVIEW_VIEW
:
2367 CheckViewMode(hmenu
);
2369 case FCIDM_SHVIEW_ARRANGE
:
2370 FillArrangeAsMenu(hmenu
);
2377 /**********************************************************
2380 * The INTERFACE of the IShellView object
2383 **********************************************************
2386 /**********************************************************
2387 * ShellView_GetWindow
2389 HRESULT WINAPI
CDefView::GetWindow(HWND
*phWnd
)
2391 TRACE("(%p)\n", this);
2398 HRESULT WINAPI
CDefView::ContextSensitiveHelp(BOOL fEnterMode
)
2400 FIXME("(%p) stub\n", this);
2405 /**********************************************************
2406 * IShellView_TranslateAccelerator
2409 * use the accel functions
2411 HRESULT WINAPI
CDefView::TranslateAccelerator(LPMSG lpmsg
)
2416 if (lpmsg
->message
>= WM_KEYFIRST
&& lpmsg
->message
<= WM_KEYLAST
)
2418 if (::TranslateAcceleratorW(m_hWnd
, m_hAccel
, lpmsg
) != 0)
2421 TRACE("-- key=0x%04lx\n", lpmsg
->wParam
) ;
2424 return m_pShellBrowser
->TranslateAcceleratorSB(lpmsg
, 0);
2427 HRESULT WINAPI
CDefView::EnableModeless(BOOL fEnable
)
2429 FIXME("(%p) stub\n", this);
2434 HRESULT WINAPI
CDefView::UIActivate(UINT uState
)
2436 // CHAR szName[MAX_PATH];
2438 int nPartArray
[1] = { -1};
2440 TRACE("(%p)->(state=%x) stub\n", this, uState
);
2442 /* don't do anything if the state isn't really changing */
2443 if (m_uState
== uState
)
2448 /* OnActivate handles the menu merging and internal state */
2451 /* only do This if we are active */
2452 if (uState
!= SVUIA_DEACTIVATE
)
2456 GetFolderPath is not a method of IShellFolder
2457 IShellFolder_GetFolderPath( m_pSFParent, szName, sizeof(szName) );
2459 /* set the number of parts */
2460 m_pShellBrowser
->SendControlMsg(FCW_STATUS
, SB_SETPARTS
, 1, (LPARAM
)nPartArray
, &lResult
);
2462 /* set the text for the parts */
2464 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult);
2471 HRESULT WINAPI
CDefView::Refresh()
2473 TRACE("(%p)\n", this);
2475 _DoFolderViewCB(SFVM_LISTREFRESHED
, TRUE
, 0);
2477 m_ListView
.DeleteAllItems();
2483 HRESULT WINAPI
CDefView::CreateViewWindow(IShellView
*lpPrevView
, LPCFOLDERSETTINGS lpfs
, IShellBrowser
*psb
, RECT
*prcView
, HWND
*phWnd
)
2485 return CreateViewWindow3(psb
, lpPrevView
, SV3CVW3_DEFAULT
,
2486 (FOLDERFLAGS
)lpfs
->fFlags
, (FOLDERFLAGS
)lpfs
->fFlags
, (FOLDERVIEWMODE
)lpfs
->ViewMode
, NULL
, prcView
, phWnd
);
2489 HRESULT WINAPI
CDefView::DestroyViewWindow()
2491 TRACE("(%p)\n", this);
2493 /* Make absolutely sure all our UI is cleaned up */
2494 UIActivate(SVUIA_DEACTIVATE
);
2498 // "Accelerator tables loaded from resources are freed automatically when the application terminates." -- MSDN
2502 if (m_hMenuArrangeModes
)
2504 DestroyMenu(m_hMenuArrangeModes
);
2505 m_hMenuArrangeModes
= NULL
;
2508 if (m_hMenuViewModes
)
2510 DestroyMenu(m_hMenuViewModes
);
2511 m_hMenuViewModes
= NULL
;
2516 DestroyMenu(m_hMenu
);
2522 m_ListView
.DestroyWindow();
2527 _DoFolderViewCB(SFVM_WINDOWCLOSING
, (WPARAM
)m_hWnd
, 0);
2531 m_pShellBrowser
.Release();
2532 m_pCommDlgBrowser
.Release();
2537 HRESULT WINAPI
CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs
)
2539 TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs
,
2540 m_FolderSettings
.ViewMode
, m_FolderSettings
.fFlags
);
2543 return E_INVALIDARG
;
2545 *lpfs
= m_FolderSettings
;
2549 HRESULT WINAPI
CDefView::AddPropertySheetPages(DWORD dwReserved
, LPFNADDPROPSHEETPAGE lpfn
, LPARAM lparam
)
2551 FIXME("(%p) stub\n", this);
2556 HRESULT WINAPI
CDefView::SaveViewState()
2558 FIXME("(%p) stub\n", this);
2563 HRESULT WINAPI
CDefView::SelectItem(PCUITEMID_CHILD pidl
, UINT uFlags
)
2567 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl
, uFlags
);
2569 i
= LV_FindItemByPidl(pidl
);
2573 LVITEMW lvItem
= {0};
2574 lvItem
.mask
= LVIF_STATE
;
2575 lvItem
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
2577 while (m_ListView
.GetItem(&lvItem
))
2579 if (lvItem
.iItem
== i
)
2581 if (uFlags
& SVSI_SELECT
)
2582 lvItem
.state
|= LVIS_SELECTED
;
2584 lvItem
.state
&= ~LVIS_SELECTED
;
2586 if (uFlags
& SVSI_FOCUSED
)
2587 lvItem
.state
|= LVIS_FOCUSED
;
2589 lvItem
.state
&= ~LVIS_FOCUSED
;
2593 if (uFlags
& SVSI_DESELECTOTHERS
)
2595 lvItem
.state
&= ~LVIS_SELECTED
;
2597 lvItem
.state
&= ~LVIS_FOCUSED
;
2600 m_ListView
.SetItem(&lvItem
);
2604 if (uFlags
& SVSI_ENSUREVISIBLE
)
2605 m_ListView
.EnsureVisible(i
, FALSE
);
2607 if((uFlags
& SVSI_EDIT
) == SVSI_EDIT
)
2608 m_ListView
.EditLabel(i
);
2613 HRESULT WINAPI
CDefView::GetItemObject(UINT uItem
, REFIID riid
, LPVOID
*ppvOut
)
2615 HRESULT hr
= E_NOINTERFACE
;
2617 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem
, debugstr_guid(&riid
), ppvOut
);
2620 return E_INVALIDARG
;
2626 case SVGIO_BACKGROUND
:
2627 if (IsEqualIID(riid
, IID_IContextMenu
))
2629 hr
= CDefViewBckgrndMenu_CreateInstance(m_pSF2Parent
, riid
, ppvOut
);
2630 if (FAILED_UNEXPECTEDLY(hr
))
2633 IUnknown_SetSite(*((IUnknown
**)ppvOut
), (IShellView
*)this);
2635 else if (IsEqualIID(riid
, IID_IDispatch
))
2637 if (m_pShellFolderViewDual
== NULL
)
2639 hr
= CDefViewDual_Constructor(riid
, (LPVOID
*)&m_pShellFolderViewDual
);
2640 if (FAILED_UNEXPECTEDLY(hr
))
2643 hr
= m_pShellFolderViewDual
->QueryInterface(riid
, ppvOut
);
2647 case SVGIO_SELECTION
:
2649 hr
= m_pSFParent
->GetUIObjectOf(m_hWnd
, m_cidl
, m_apidl
, riid
, 0, ppvOut
);
2650 if (FAILED_UNEXPECTEDLY(hr
))
2653 if (IsEqualIID(riid
, IID_IContextMenu
))
2654 IUnknown_SetSite(*((IUnknown
**)ppvOut
), (IShellView
*)this);
2659 TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut
);
2664 HRESULT STDMETHODCALLTYPE
CDefView::GetCurrentViewMode(UINT
*pViewMode
)
2666 TRACE("(%p)->(%p), stub\n", this, pViewMode
);
2669 return E_INVALIDARG
;
2671 *pViewMode
= m_FolderSettings
.ViewMode
;
2675 HRESULT STDMETHODCALLTYPE
CDefView::SetCurrentViewMode(UINT ViewMode
)
2678 TRACE("(%p)->(%u), stub\n", this, ViewMode
);
2680 /* It's not redundant to check FVM_AUTO because it's a (UINT)-1 */
2681 if (((INT
)ViewMode
< FVM_FIRST
|| (INT
)ViewMode
> FVM_LAST
) && ((INT
)ViewMode
!= FVM_AUTO
))
2682 return E_INVALIDARG
;
2684 /* Windows before Vista uses LVM_SETVIEW and possibly
2685 LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview,
2686 while later versions seem to accomplish this through other
2694 dwStyle
= LVS_REPORT
;
2697 dwStyle
= LVS_SMALLICON
;
2704 FIXME("ViewMode %d not implemented\n", ViewMode
);
2710 m_ListView
.ModifyStyle(LVS_TYPEMASK
, dwStyle
);
2712 /* This will not necessarily be the actual mode set above.
2713 This mimics the behavior of Windows XP. */
2714 m_FolderSettings
.ViewMode
= ViewMode
;
2719 HRESULT STDMETHODCALLTYPE
CDefView::GetFolder(REFIID riid
, void **ppv
)
2721 if (m_pSFParent
== NULL
)
2724 return m_pSFParent
->QueryInterface(riid
, ppv
);
2727 HRESULT STDMETHODCALLTYPE
CDefView::Item(int iItemIndex
, PITEMID_CHILD
*ppidl
)
2729 PCUITEMID_CHILD pidl
= _PidlByItem(iItemIndex
);
2732 *ppidl
= ILClone(pidl
);
2737 return E_INVALIDARG
;
2740 HRESULT STDMETHODCALLTYPE
CDefView::ItemCount(UINT uFlags
, int *pcItems
)
2742 TRACE("(%p)->(%u %p)\n", this, uFlags
, pcItems
);
2744 if (uFlags
!= SVGIO_ALLVIEW
)
2745 FIXME("some flags unsupported, %x\n", uFlags
& ~SVGIO_ALLVIEW
);
2747 *pcItems
= m_ListView
.GetItemCount();
2752 HRESULT STDMETHODCALLTYPE
CDefView::Items(UINT uFlags
, REFIID riid
, void **ppv
)
2757 HRESULT STDMETHODCALLTYPE
CDefView::GetSelectionMarkedItem(int *piItem
)
2759 TRACE("(%p)->(%p)\n", this, piItem
);
2761 *piItem
= m_ListView
.GetSelectionMark();
2766 HRESULT STDMETHODCALLTYPE
CDefView::GetFocusedItem(int *piItem
)
2768 TRACE("(%p)->(%p)\n", this, piItem
);
2770 *piItem
= m_ListView
.GetNextItem(-1, LVNI_FOCUSED
);
2775 HRESULT STDMETHODCALLTYPE
CDefView::GetItemPosition(PCUITEMID_CHILD pidl
, POINT
*ppt
)
2777 int lvIndex
= LV_FindItemByPidl(pidl
);
2778 if (lvIndex
== -1 || ppt
== NULL
)
2779 return E_INVALIDARG
;
2781 m_ListView
.GetItemPosition(lvIndex
, ppt
);
2785 HRESULT STDMETHODCALLTYPE
CDefView::GetSpacing(POINT
*ppt
)
2787 TRACE("(%p)->(%p)\n", this, ppt
);
2795 m_ListView
.GetItemSpacing(spacing
);
2797 ppt
->x
= spacing
.cx
;
2798 ppt
->y
= spacing
.cy
;
2804 HRESULT STDMETHODCALLTYPE
CDefView::GetDefaultSpacing(POINT
*ppt
)
2809 HRESULT STDMETHODCALLTYPE
CDefView::GetAutoArrange()
2811 return ((m_ListView
.GetStyle() & LVS_AUTOARRANGE
) ? S_OK
: S_FALSE
);
2814 HRESULT
CDefView::_GetSnapToGrid()
2816 DWORD dwExStyle
= (DWORD
)m_ListView
.SendMessage(LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
2817 return ((dwExStyle
& LVS_EX_SNAPTOGRID
) ? S_OK
: S_FALSE
);
2820 HRESULT STDMETHODCALLTYPE
CDefView::SelectItem(int iItem
, DWORD dwFlags
)
2824 TRACE("(%p)->(%d, %x)\n", this, iItem
, dwFlags
);
2827 lvItem
.stateMask
= LVIS_SELECTED
;
2829 if (dwFlags
& SVSI_ENSUREVISIBLE
)
2830 m_ListView
.EnsureVisible(iItem
, 0);
2833 if (dwFlags
& SVSI_DESELECTOTHERS
)
2834 m_ListView
.SetItemState(-1, 0, LVIS_SELECTED
);
2837 if (dwFlags
& SVSI_SELECT
)
2838 lvItem
.state
|= LVIS_SELECTED
;
2840 if (dwFlags
& SVSI_FOCUSED
)
2841 lvItem
.stateMask
|= LVIS_FOCUSED
;
2843 m_ListView
.SetItemState(iItem
, lvItem
.state
, lvItem
.stateMask
);
2845 if ((dwFlags
& SVSI_EDIT
) == SVSI_EDIT
)
2846 m_ListView
.EditLabel(iItem
);
2851 HRESULT STDMETHODCALLTYPE
CDefView::SelectAndPositionItems(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, POINT
*apt
, DWORD dwFlags
)
2853 /* Reset the selection */
2854 m_ListView
.SetItemState(-1, 0, LVIS_SELECTED
);
2857 for (UINT i
= 0 ; i
< m_cidl
; i
++)
2859 lvIndex
= LV_FindItemByPidl(apidl
[i
]);
2862 SelectItem(lvIndex
, dwFlags
);
2863 m_ListView
.SetItemPosition(lvIndex
, &apt
[i
]);
2870 /**********************************************************
2871 * IShellView2 implementation
2874 HRESULT STDMETHODCALLTYPE
CDefView::GetView(SHELLVIEWID
*view_guid
, ULONG view_type
)
2876 FIXME("(%p)->(%p, %lu) stub\n", this, view_guid
, view_type
);
2880 HRESULT STDMETHODCALLTYPE
CDefView::CreateViewWindow2(LPSV2CVW2_PARAMS view_params
)
2882 return CreateViewWindow3(view_params
->psbOwner
, view_params
->psvPrev
,
2883 SV3CVW3_DEFAULT
, (FOLDERFLAGS
)view_params
->pfs
->fFlags
, (FOLDERFLAGS
)view_params
->pfs
->fFlags
,
2884 (FOLDERVIEWMODE
)view_params
->pfs
->ViewMode
, view_params
->pvid
, view_params
->prcView
, &view_params
->hwndView
);
2887 HRESULT STDMETHODCALLTYPE
CDefView::CreateViewWindow3(IShellBrowser
*psb
, IShellView
*psvPrevious
, SV3CVW3_FLAGS view_flags
, FOLDERFLAGS mask
, FOLDERFLAGS flags
, FOLDERVIEWMODE mode
, const SHELLVIEWID
*view_id
, RECT
*prcView
, HWND
*hwnd
)
2889 OLEMENUGROUPWIDTHS omw
= { { 0, 0, 0, 0, 0, 0 } };
2893 TRACE("(%p)->(shlview=%p shlbrs=%p rec=%p hwnd=%p vmode=%x flags=%x)\n", this, psvPrevious
, psb
, prcView
, hwnd
, mode
, flags
);
2894 if (prcView
!= NULL
)
2895 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView
->left
, prcView
->top
, prcView
->right
, prcView
->bottom
);
2897 /* Validate the Shell Browser */
2898 if (psb
== NULL
|| m_hWnd
)
2899 return E_UNEXPECTED
;
2901 if (view_flags
!= SV3CVW3_DEFAULT
)
2902 FIXME("unsupported view flags 0x%08x\n", view_flags
);
2904 /* Set up the member variables */
2905 m_pShellBrowser
= psb
;
2906 m_FolderSettings
.ViewMode
= mode
;
2907 m_FolderSettings
.fFlags
= mask
& flags
;
2911 if (IsEqualIID(*view_id
, VID_LargeIcons
))
2912 m_FolderSettings
.ViewMode
= FVM_ICON
;
2913 else if (IsEqualIID(*view_id
, VID_SmallIcons
))
2914 m_FolderSettings
.ViewMode
= FVM_SMALLICON
;
2915 else if (IsEqualIID(*view_id
, VID_List
))
2916 m_FolderSettings
.ViewMode
= FVM_LIST
;
2917 else if (IsEqualIID(*view_id
, VID_Details
))
2918 m_FolderSettings
.ViewMode
= FVM_DETAILS
;
2919 else if (IsEqualIID(*view_id
, VID_Thumbnails
))
2920 m_FolderSettings
.ViewMode
= FVM_THUMBNAIL
;
2921 else if (IsEqualIID(*view_id
, VID_Tile
))
2922 m_FolderSettings
.ViewMode
= FVM_TILE
;
2923 else if (IsEqualIID(*view_id
, VID_ThumbStrip
))
2924 m_FolderSettings
.ViewMode
= FVM_THUMBSTRIP
;
2926 FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_id
));
2929 /* Get our parent window */
2930 m_pShellBrowser
->GetWindow(&m_hWndParent
);
2932 /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
2933 m_pCommDlgBrowser
= NULL
;
2934 if (SUCCEEDED(m_pShellBrowser
->QueryInterface(IID_PPV_ARG(ICommDlgBrowser
, &m_pCommDlgBrowser
))))
2936 TRACE("-- CommDlgBrowser\n");
2939 Create(m_hWndParent
, prcView
, NULL
, WS_CHILD
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_TABSTOP
, 0, 0U);
2950 _DoFolderViewCB(SFVM_WINDOWCREATED
, (WPARAM
)m_hWnd
, 0);
2952 SetWindowPos(HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_SHOWWINDOW
);
2957 m_hMenu
= CreateMenu();
2958 m_pShellBrowser
->InsertMenusSB(m_hMenu
, &omw
);
2959 TRACE("-- after fnInsertMenusSB\n");
2967 HRESULT STDMETHODCALLTYPE
CDefView::HandleRename(LPCITEMIDLIST new_pidl
)
2969 FIXME("(%p)->(%p) stub\n", this, new_pidl
);
2973 HRESULT STDMETHODCALLTYPE
CDefView::SelectAndPositionItem(LPCITEMIDLIST item
, UINT flags
, POINT
*point
)
2975 FIXME("(%p)->(%p, %u, %p) stub\n", this, item
, flags
, point
);
2979 /**********************************************************
2980 * IShellFolderView implementation
2982 HRESULT STDMETHODCALLTYPE
CDefView::Rearrange(LPARAM sort
)
2984 FIXME("(%p)->(%ld) stub\n", this, sort
);
2988 HRESULT STDMETHODCALLTYPE
CDefView::GetArrangeParam(LPARAM
*sort
)
2990 FIXME("(%p)->(%p) stub\n", this, sort
);
2994 HRESULT STDMETHODCALLTYPE
CDefView::ArrangeGrid()
2996 m_ListView
.SetExtendedListViewStyle(LVS_EX_SNAPTOGRID
, LVS_EX_SNAPTOGRID
);
3000 HRESULT STDMETHODCALLTYPE
CDefView::AutoArrange()
3002 m_ListView
.ModifyStyle(0, LVS_AUTOARRANGE
);
3003 m_ListView
.Arrange(LVA_DEFAULT
);
3007 HRESULT STDMETHODCALLTYPE
CDefView::AddObject(PITEMID_CHILD pidl
, UINT
*item
)
3009 TRACE("(%p)->(%p %p)\n", this, pidl
, item
);
3010 *item
= LV_AddItem(pidl
);
3011 return (int)*item
>= 0 ? S_OK
: E_OUTOFMEMORY
;
3014 HRESULT STDMETHODCALLTYPE
CDefView::GetObject(PITEMID_CHILD
*pidl
, UINT item
)
3016 TRACE("(%p)->(%p %d)\n", this, pidl
, item
);
3017 return Item(item
, pidl
);
3020 HRESULT STDMETHODCALLTYPE
CDefView::RemoveObject(PITEMID_CHILD pidl
, UINT
*item
)
3023 TRACE("(%p)->(%p %p)\n", this, pidl
, item
);
3027 *item
= LV_FindItemByPidl(ILFindLastID(pidl
));
3028 m_ListView
.DeleteItem(*item
);
3033 m_ListView
.DeleteAllItems();
3039 HRESULT STDMETHODCALLTYPE
CDefView::GetObjectCount(UINT
*count
)
3041 TRACE("(%p)->(%p)\n", this, count
);
3042 *count
= m_ListView
.GetItemCount();
3046 HRESULT STDMETHODCALLTYPE
CDefView::SetObjectCount(UINT count
, UINT flags
)
3048 FIXME("(%p)->(%d %x) stub\n", this, count
, flags
);
3052 HRESULT STDMETHODCALLTYPE
CDefView::UpdateObject(PITEMID_CHILD pidl_old
, PITEMID_CHILD pidl_new
, UINT
*item
)
3054 FIXME("(%p)->(%p %p %p) stub\n", this, pidl_old
, pidl_new
, item
);
3058 HRESULT STDMETHODCALLTYPE
CDefView::RefreshObject(PITEMID_CHILD pidl
, UINT
*item
)
3060 FIXME("(%p)->(%p %p) stub\n", this, pidl
, item
);
3064 HRESULT STDMETHODCALLTYPE
CDefView::SetRedraw(BOOL redraw
)
3066 TRACE("(%p)->(%d)\n", this, redraw
);
3067 m_ListView
.SetRedraw(redraw
);
3071 HRESULT STDMETHODCALLTYPE
CDefView::GetSelectedCount(UINT
*count
)
3073 FIXME("(%p)->(%p) stub\n", this, count
);
3077 HRESULT STDMETHODCALLTYPE
CDefView::GetSelectedObjects(PCUITEMID_CHILD
**pidl
, UINT
*items
)
3079 TRACE("(%p)->(%p %p)\n", this, pidl
, items
);
3081 *items
= GetSelections();
3085 *pidl
= static_cast<PCUITEMID_CHILD
*>(LocalAlloc(0, *items
* sizeof(PCUITEMID_CHILD
)));
3088 return E_OUTOFMEMORY
;
3091 /* it's documented that caller shouldn't PIDLs, only array itself */
3092 memcpy(*pidl
, m_apidl
, *items
* sizeof(PCUITEMID_CHILD
));
3098 HRESULT STDMETHODCALLTYPE
CDefView::IsDropOnSource(IDropTarget
*drop_target
)
3100 if ((m_iDragOverItem
== -1 || m_pCurDropTarget
== NULL
) &&
3101 (m_pSourceDataObject
.p
))
3109 HRESULT STDMETHODCALLTYPE
CDefView::GetDragPoint(POINT
*pt
)
3112 return E_INVALIDARG
;
3114 *pt
= m_ptFirstMousePos
;
3118 HRESULT STDMETHODCALLTYPE
CDefView::GetDropPoint(POINT
*pt
)
3120 FIXME("(%p)->(%p) stub\n", this, pt
);
3124 HRESULT STDMETHODCALLTYPE
CDefView::MoveIcons(IDataObject
*obj
)
3126 TRACE("(%p)->(%p)\n", this, obj
);
3130 HRESULT STDMETHODCALLTYPE
CDefView::SetItemPos(PCUITEMID_CHILD pidl
, POINT
*pt
)
3132 FIXME("(%p)->(%p %p) stub\n", this, pidl
, pt
);
3136 HRESULT STDMETHODCALLTYPE
CDefView::IsBkDropTarget(IDropTarget
*drop_target
)
3138 FIXME("(%p)->(%p) stub\n", this, drop_target
);
3142 HRESULT STDMETHODCALLTYPE
CDefView::SetClipboard(BOOL move
)
3144 FIXME("(%p)->(%d) stub\n", this, move
);
3148 HRESULT STDMETHODCALLTYPE
CDefView::SetPoints(IDataObject
*obj
)
3150 FIXME("(%p)->(%p) stub\n", this, obj
);
3154 HRESULT STDMETHODCALLTYPE
CDefView::GetItemSpacing(ITEMSPACING
*spacing
)
3156 FIXME("(%p)->(%p) stub\n", this, spacing
);
3160 HRESULT STDMETHODCALLTYPE
CDefView::SetCallback(IShellFolderViewCB
*new_cb
, IShellFolderViewCB
**old_cb
)
3163 *old_cb
= m_pShellFolderViewCB
.Detach();
3165 m_pShellFolderViewCB
= new_cb
;
3169 HRESULT STDMETHODCALLTYPE
CDefView::Select(UINT flags
)
3171 FIXME("(%p)->(%d) stub\n", this, flags
);
3175 HRESULT STDMETHODCALLTYPE
CDefView::QuerySupport(UINT
*support
)
3177 TRACE("(%p)->(%p)\n", this, support
);
3181 HRESULT STDMETHODCALLTYPE
CDefView::SetAutomationObject(IDispatch
*disp
)
3183 FIXME("(%p)->(%p) stub\n", this, disp
);
3187 /**********************************************************
3188 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
3190 HRESULT WINAPI
CDefView::QueryStatus(const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD
*prgCmds
, OLECMDTEXT
*pCmdText
)
3192 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
3193 this, pguidCmdGroup
, debugstr_guid(pguidCmdGroup
), cCmds
, prgCmds
, pCmdText
);
3196 return E_INVALIDARG
;
3198 for (UINT i
= 0; i
< cCmds
; i
++)
3200 FIXME("\tprgCmds[%d].cmdID = %d\n", i
, prgCmds
[i
].cmdID
);
3201 prgCmds
[i
].cmdf
= 0;
3204 return OLECMDERR_E_UNKNOWNGROUP
;
3207 /**********************************************************
3208 * ISVOleCmdTarget_Exec (IOleCommandTarget)
3210 * nCmdID is the OLECMDID_* enumeration
3212 HRESULT WINAPI
CDefView::Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
3214 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
3215 this, debugstr_guid(pguidCmdGroup
), nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
3218 return OLECMDERR_E_UNKNOWNGROUP
;
3220 if (IsEqualCLSID(*pguidCmdGroup
, m_Category
))
3222 if (nCmdID
== FCIDM_SHVIEW_AUTOARRANGE
)
3224 if (V_VT(pvaIn
) != VT_INT_PTR
)
3225 return OLECMDERR_E_NOTSUPPORTED
;
3228 params
.cbSize
= sizeof(params
);
3229 params
.rcExclude
= *(RECT
*) V_INTREF(pvaIn
);
3231 if (m_hMenuViewModes
)
3233 /* Duplicate all but the last two items of the view modes menu */
3234 HMENU hmenuViewPopup
= CreatePopupMenu();
3235 Shell_MergeMenus(hmenuViewPopup
, m_hMenuViewModes
, 0, 0, 0xFFFF, 0);
3236 DeleteMenu(hmenuViewPopup
, GetMenuItemCount(hmenuViewPopup
) - 1, MF_BYPOSITION
);
3237 DeleteMenu(hmenuViewPopup
, GetMenuItemCount(hmenuViewPopup
) - 1, MF_BYPOSITION
);
3238 CheckViewMode(hmenuViewPopup
);
3239 TrackPopupMenuEx(hmenuViewPopup
, TPM_LEFTALIGN
| TPM_TOPALIGN
, params
.rcExclude
.left
, params
.rcExclude
.bottom
, m_hWndParent
, ¶ms
);
3240 ::DestroyMenu(hmenuViewPopup
);
3243 // pvaOut is VT_I4 with value 0x403 (cmd id of the new mode maybe?)
3244 V_VT(pvaOut
) = VT_I4
;
3245 V_I4(pvaOut
) = 0x403;
3249 if (IsEqualIID(*pguidCmdGroup
, CGID_Explorer
) &&
3251 (nCmdexecopt
== 4) && pvaOut
)
3254 if (IsEqualIID(*pguidCmdGroup
, CGID_ShellDocView
) &&
3259 return OLECMDERR_E_UNKNOWNGROUP
;
3262 /**********************************************************
3263 * ISVDropTarget implementation
3266 /******************************************************************************
3267 * drag_notify_subitem [Internal]
3269 * Figure out the shellfolder object, which is currently under the mouse cursor
3270 * and notify it via the IDropTarget interface.
3273 #define SCROLLAREAWIDTH 20
3275 HRESULT
CDefView::drag_notify_subitem(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
3281 /* The key state on drop doesn't have MK_LBUTTON or MK_RBUTTON because it
3282 reflects the key state after the user released the button, so we need
3283 to remember the last key state when the button was pressed */
3284 m_grfKeyState
= grfKeyState
;
3286 /* Map from global to client coordinates and query the index of the listview-item, which is
3287 * currently under the mouse cursor. */
3288 LVHITTESTINFO htinfo
= {{pt
.x
, pt
.y
}, LVHT_ONITEM
};
3289 ScreenToClient(&htinfo
.pt
);
3290 lResult
= m_ListView
.HitTest(&htinfo
);
3292 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
3293 ::GetClientRect(m_ListView
, &clientRect
);
3294 if (htinfo
.pt
.x
== m_ptLastMousePos
.x
&& htinfo
.pt
.y
== m_ptLastMousePos
.y
&&
3295 (htinfo
.pt
.x
< SCROLLAREAWIDTH
|| htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
||
3296 htinfo
.pt
.y
< SCROLLAREAWIDTH
|| htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
))
3298 m_cScrollDelay
= (m_cScrollDelay
+ 1) % 5; /* DragOver is called every 50 ms */
3299 if (m_cScrollDelay
== 0)
3301 /* Mouse did hover another 250 ms over the scroll-area */
3302 if (htinfo
.pt
.x
< SCROLLAREAWIDTH
)
3303 m_ListView
.SendMessageW(WM_HSCROLL
, SB_LINEUP
, 0);
3305 if (htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
)
3306 m_ListView
.SendMessageW(WM_HSCROLL
, SB_LINEDOWN
, 0);
3308 if (htinfo
.pt
.y
< SCROLLAREAWIDTH
)
3309 m_ListView
.SendMessageW(WM_VSCROLL
, SB_LINEUP
, 0);
3311 if (htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
)
3312 m_ListView
.SendMessageW(WM_VSCROLL
, SB_LINEDOWN
, 0);
3317 m_cScrollDelay
= 0; /* Reset, if the cursor is not over the listview's scroll-area */
3320 m_ptLastMousePos
= htinfo
.pt
;
3321 ::ClientToListView(m_ListView
, &m_ptLastMousePos
);
3323 /* We need to check if we drag the selection over itself */
3324 if (lResult
!= -1 && m_pSourceDataObject
.p
!= NULL
)
3326 PCUITEMID_CHILD pidl
= _PidlByItem(lResult
);
3328 for (UINT i
= 0; i
< m_cidl
; i
++)
3330 if (pidl
== m_apidl
[i
])
3332 /* The item that is being draged is hovering itself. */
3339 /* If we are still over the previous sub-item, notify it via DragOver and return. */
3340 if (m_pCurDropTarget
&& lResult
== m_iDragOverItem
)
3341 return m_pCurDropTarget
->DragOver(grfKeyState
, pt
, pdwEffect
);
3343 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
3344 if (m_pCurDropTarget
)
3346 PCUITEMID_CHILD pidl
= _PidlByItem(m_iDragOverItem
);
3348 SelectItem(pidl
, 0);
3350 m_pCurDropTarget
->DragLeave();
3351 m_pCurDropTarget
.Release();
3354 m_iDragOverItem
= lResult
;
3358 /* We are not above one of the listview's subitems. Bind to the parent folder's
3359 * DropTarget interface. */
3360 hr
= m_pSFParent
->CreateViewObject(NULL
, IID_PPV_ARG(IDropTarget
,&m_pCurDropTarget
));
3364 /* Query the relative PIDL of the shellfolder object represented by the currently
3365 * dragged over listview-item ... */
3366 PCUITEMID_CHILD pidl
= _PidlByItem(lResult
);
3368 /* ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object */
3369 hr
= m_pSFParent
->GetUIObjectOf(m_ListView
, 1, &pidl
, IID_NULL_PPV_ARG(IDropTarget
, &m_pCurDropTarget
));
3372 IUnknown_SetSite(m_pCurDropTarget
, (IShellView
*)this);
3374 /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */
3377 *pdwEffect
= DROPEFFECT_NONE
;
3381 if (m_iDragOverItem
!= -1)
3383 SelectItem(m_iDragOverItem
, SVSI_SELECT
);
3386 /* Notify the item just entered via DragEnter. */
3387 return m_pCurDropTarget
->DragEnter(m_pCurDataObject
, grfKeyState
, pt
, pdwEffect
);
3390 HRESULT WINAPI
CDefView::DragEnter(IDataObject
*pDataObject
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
3392 if (*pdwEffect
== DROPEFFECT_NONE
)
3395 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
3396 m_pCurDataObject
= pDataObject
;
3398 HRESULT hr
= drag_notify_subitem(grfKeyState
, pt
, pdwEffect
);
3401 POINT ptClient
= {pt
.x
, pt
.y
};
3402 ScreenToClient(&ptClient
);
3403 ImageList_DragEnter(m_hWnd
, ptClient
.x
, ptClient
.y
);
3409 HRESULT WINAPI
CDefView::DragOver(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
3411 POINT ptClient
= {pt
.x
, pt
.y
};
3412 ScreenToClient(&ptClient
);
3413 ImageList_DragMove(ptClient
.x
, ptClient
.y
);
3414 return drag_notify_subitem(grfKeyState
, pt
, pdwEffect
);
3417 HRESULT WINAPI
CDefView::DragLeave()
3419 ImageList_DragLeave(m_hWnd
);
3421 if (m_pCurDropTarget
)
3423 m_pCurDropTarget
->DragLeave();
3424 m_pCurDropTarget
.Release();
3427 if (m_pCurDataObject
!= NULL
)
3429 m_pCurDataObject
.Release();
3432 m_iDragOverItem
= 0;
3437 INT
CDefView::_FindInsertableIndexFromPoint(POINT pt
)
3440 INT i
, nCount
= m_ListView
.GetItemCount();
3443 BOOL bSmall
= ((m_ListView
.GetStyle() & LVS_TYPEMASK
) != LVS_ICON
);
3445 /* FIXME: LVM_GETORIGIN is broken. See CORE-17266 */
3446 pt
.x
+= m_ListView
.GetScrollPos(SB_HORZ
);
3447 pt
.y
+= m_ListView
.GetScrollPos(SB_VERT
);
3449 if (m_ListView
.GetStyle() & LVS_ALIGNLEFT
)
3452 for (i
= 0; i
< nCount
; ++i
)
3454 dwSpacing
= ListView_GetItemSpacing(m_ListView
, bSmall
);
3455 dx
= LOWORD(dwSpacing
);
3456 dy
= HIWORD(dwSpacing
);
3457 ListView_GetItemRect(m_ListView
, i
, &rcBound
, LVIR_SELECTBOUNDS
);
3458 rcBound
.right
= rcBound
.left
+ dx
;
3459 rcBound
.bottom
= rcBound
.top
+ dy
;
3460 if (pt
.x
< rcBound
.right
&& pt
.y
< (rcBound
.top
+ rcBound
.bottom
) / 2)
3465 for (i
= nCount
- 1; i
>= 0; --i
)
3467 ListView_GetItemRect(m_ListView
, i
, &rcBound
, LVIR_SELECTBOUNDS
);
3468 if (rcBound
.left
< pt
.x
&& rcBound
.top
< pt
.y
)
3477 for (i
= 0; i
< nCount
; ++i
)
3479 dwSpacing
= ListView_GetItemSpacing(m_ListView
, bSmall
);
3480 dx
= LOWORD(dwSpacing
);
3481 dy
= HIWORD(dwSpacing
);
3482 ListView_GetItemRect(m_ListView
, i
, &rcBound
, LVIR_SELECTBOUNDS
);
3483 rcBound
.right
= rcBound
.left
+ dx
;
3484 rcBound
.bottom
= rcBound
.top
+ dy
;
3485 if (pt
.y
< rcBound
.bottom
&& pt
.x
< rcBound
.left
)
3489 if (pt
.y
< rcBound
.bottom
&& pt
.x
< rcBound
.right
)
3494 for (i
= nCount
- 1; i
>= 0; --i
)
3496 ListView_GetItemRect(m_ListView
, i
, &rcBound
, LVIR_SELECTBOUNDS
);
3497 if (rcBound
.left
< pt
.x
&& rcBound
.top
< pt
.y
)
3507 typedef CSimpleMap
<LPARAM
, INT
> CLParamIndexMap
;
3510 SelectionMoveCompareFunc(LPARAM lParam1
, LPARAM lParam2
, LPARAM lParamSort
)
3512 CLParamIndexMap
*pmap
= (CLParamIndexMap
*)lParamSort
;
3513 INT i1
= pmap
->Lookup(lParam1
), i2
= pmap
->Lookup(lParam2
);
3521 void CDefView::_MoveSelectionOnAutoArrange(POINT pt
)
3523 // get insertable index from position
3524 INT iPosition
= _FindInsertableIndexFromPoint(pt
);
3526 // create identity mapping of indexes
3527 CSimpleArray
<INT
> array
;
3528 INT nCount
= m_ListView
.GetItemCount();
3529 for (INT i
= 0; i
< nCount
; ++i
)
3534 // re-ordering mapping
3536 while ((iItem
= m_ListView
.GetNextItem(iItem
, LVNI_SELECTED
)) >= 0)
3538 INT iFrom
= iItem
, iTo
= iPosition
;
3541 if (iFrom
>= nCount
)
3546 // shift indexes by swapping (like a bucket relay)
3549 for (INT i
= iFrom
; i
< iTo
; ++i
)
3551 // swap array[i] and array[i + 1]
3553 array
[i
] = array
[i
+ 1];
3559 for (INT i
= iFrom
; i
> iTo
; --i
)
3561 // swap array[i] and array[i - 1]
3563 array
[i
] = array
[i
- 1];
3569 // create mapping (ListView's lParam to index) from array
3570 CLParamIndexMap map
;
3571 for (INT i
= 0; i
< nCount
; ++i
)
3573 LPARAM lParam
= m_ListView
.GetItemData(array
[i
]);
3578 m_ListView
.SortItems(SelectionMoveCompareFunc
, &map
);
3581 HRESULT WINAPI
CDefView::Drop(IDataObject
* pDataObject
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
3583 ImageList_DragLeave(m_hWnd
);
3584 ImageList_EndDrag();
3586 if ((IsDropOnSource(NULL
) == S_OK
) &&
3587 (*pdwEffect
& DROPEFFECT_MOVE
) &&
3588 (m_grfKeyState
& MK_LBUTTON
))
3590 if (m_pCurDropTarget
)
3592 m_pCurDropTarget
->DragLeave();
3593 m_pCurDropTarget
.Release();
3596 POINT ptDrop
= { pt
.x
, pt
.y
};
3597 ::ScreenToClient(m_ListView
, &ptDrop
);
3598 ::ClientToListView(m_ListView
, &ptDrop
);
3599 m_ptLastMousePos
= ptDrop
;
3601 m_ListView
.SetRedraw(FALSE
);
3602 if (m_ListView
.GetStyle() & LVS_AUTOARRANGE
)
3604 _MoveSelectionOnAutoArrange(m_ptLastMousePos
);
3610 while ((iItem
= m_ListView
.GetNextItem(iItem
, LVNI_SELECTED
)) >= 0)
3612 if (m_ListView
.GetItemPosition(iItem
, &ptItem
))
3614 ptItem
.x
+= m_ptLastMousePos
.x
- m_ptFirstMousePos
.x
;
3615 ptItem
.y
+= m_ptLastMousePos
.y
- m_ptFirstMousePos
.y
;
3616 m_ListView
.SetItemPosition(iItem
, &ptItem
);
3620 m_ListView
.SetRedraw(TRUE
);
3622 else if (m_pCurDropTarget
)
3624 m_pCurDropTarget
->Drop(pDataObject
, grfKeyState
, pt
, pdwEffect
);
3625 m_pCurDropTarget
.Release();
3628 m_pCurDataObject
.Release();
3629 m_iDragOverItem
= 0;
3633 /**********************************************************
3634 * ISVDropSource implementation
3637 HRESULT WINAPI
CDefView::QueryContinueDrag(BOOL fEscapePressed
, DWORD grfKeyState
)
3639 TRACE("(%p)\n", this);
3642 return DRAGDROP_S_CANCEL
;
3643 else if (!(grfKeyState
& MK_LBUTTON
) && !(grfKeyState
& MK_RBUTTON
))
3644 return DRAGDROP_S_DROP
;
3649 HRESULT WINAPI
CDefView::GiveFeedback(DWORD dwEffect
)
3651 TRACE("(%p)\n", this);
3653 return DRAGDROP_S_USEDEFAULTCURSORS
;
3656 /**********************************************************
3657 * ISVViewObject implementation
3660 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
)
3662 FIXME("Stub: this=%p\n", this);
3667 HRESULT WINAPI
CDefView::GetColorSet(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DVTARGETDEVICE
*ptd
, HDC hicTargetDevice
, LOGPALETTE
**ppColorSet
)
3669 FIXME("Stub: this=%p\n", this);
3674 HRESULT WINAPI
CDefView::Freeze(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DWORD
*pdwFreeze
)
3676 FIXME("Stub: this=%p\n", this);
3681 HRESULT WINAPI
CDefView::Unfreeze(DWORD dwFreeze
)
3683 FIXME("Stub: this=%p\n", this);
3688 HRESULT WINAPI
CDefView::SetAdvise(DWORD aspects
, DWORD advf
, IAdviseSink
*pAdvSink
)
3690 FIXME("partial stub: %p 0x%08x 0x%08x %p\n", this, aspects
, advf
, pAdvSink
);
3692 /* FIXME: we set the AdviseSink, but never use it to send any advice */
3693 m_pAdvSink
= pAdvSink
;
3694 m_dwAspects
= aspects
;
3700 HRESULT WINAPI
CDefView::GetAdvise(DWORD
*pAspects
, DWORD
*pAdvf
, IAdviseSink
**ppAdvSink
)
3702 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects
, pAdvf
, ppAdvSink
);
3706 *ppAdvSink
= m_pAdvSink
;
3707 m_pAdvSink
.p
->AddRef();
3711 *pAspects
= m_dwAspects
;
3719 HRESULT STDMETHODCALLTYPE
CDefView::QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
)
3721 if (IsEqualIID(guidService
, SID_IShellBrowser
))
3722 return m_pShellBrowser
->QueryInterface(riid
, ppvObject
);
3723 else if(IsEqualIID(guidService
, SID_IFolderView
))
3724 return QueryInterface(riid
, ppvObject
);
3726 return E_NOINTERFACE
;
3729 HRESULT
CDefView::_MergeToolbar()
3731 CComPtr
<IExplorerToolbar
> ptb
;
3734 hr
= IUnknown_QueryService(m_pShellBrowser
, IID_IExplorerToolbar
, IID_PPV_ARG(IExplorerToolbar
, &ptb
));
3738 m_Category
= CGID_DefViewFrame
;
3740 hr
= ptb
->SetCommandTarget(static_cast<IOleCommandTarget
*>(this), &m_Category
, 0);
3748 hr
= ptb
->AddButtons(&m_Category
, buttonsCount
, buttons
);
3756 HRESULT
CDefView::_DoFolderViewCB(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3758 HRESULT hr
= E_NOTIMPL
;
3760 if (m_pShellFolderViewCB
)
3762 hr
= m_pShellFolderViewCB
->MessageSFVCB(uMsg
, wParam
, lParam
);
3768 HRESULT
CDefView_CreateInstance(IShellFolder
*pFolder
, REFIID riid
, LPVOID
* ppvOut
)
3770 return ShellObjectCreatorInit
<CDefView
>(pFolder
, riid
, ppvOut
);
3773 HRESULT WINAPI
SHCreateShellFolderViewEx(
3774 LPCSFV psvcbi
, /* [in] shelltemplate struct */
3775 IShellView
**ppsv
) /* [out] IShellView pointer */
3777 CComPtr
<IShellView
> psv
;
3780 TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n",
3781 psvcbi
->pshf
, psvcbi
->pidl
, psvcbi
->pfnCallback
,
3782 psvcbi
->fvm
, psvcbi
->psvOuter
);
3785 hRes
= CDefView_CreateInstance(psvcbi
->pshf
, IID_PPV_ARG(IShellView
, &psv
));
3786 if (FAILED_UNEXPECTEDLY(hRes
))
3789 *ppsv
= psv
.Detach();
3793 HRESULT WINAPI
SHCreateShellFolderView(const SFV_CREATE
*pcsfv
,
3796 CComPtr
<IShellView
> psv
;
3800 return E_INVALIDARG
;
3804 if (!pcsfv
|| pcsfv
->cbSize
!= sizeof(*pcsfv
))
3805 return E_INVALIDARG
;
3807 TRACE("sf=%p outer=%p callback=%p\n",
3808 pcsfv
->pshf
, pcsfv
->psvOuter
, pcsfv
->psfvcb
);
3810 hRes
= CDefView_CreateInstance(pcsfv
->pshf
, IID_PPV_ARG(IShellView
, &psv
));
3816 CComPtr
<IShellFolderView
> sfv
;
3817 if (SUCCEEDED(psv
->QueryInterface(IID_PPV_ARG(IShellFolderView
, &sfv
))))
3819 sfv
->SetCallback(pcsfv
->psfvcb
, NULL
);
3823 *ppsv
= psv
.Detach();