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 hResult
= GetItemObject( bUseSelection
? SVGIO_SELECTION
: SVGIO_BACKGROUND
, IID_PPV_ARG(IContextMenu
, &m_pCM
));
1579 if (FAILED_UNEXPECTEDLY( hResult
))
1581 if ((uCommand
!= FCIDM_SHVIEW_DELETE
) && (uCommand
!= FCIDM_SHVIEW_RENAME
))
1583 hMenu
= CreatePopupMenu();
1587 hResult
= m_pCM
->QueryContextMenu(hMenu
, 0, FCIDM_SHVIEWFIRST
, FCIDM_SHVIEWLAST
, CMF_NORMAL
);
1588 if (FAILED_UNEXPECTEDLY(hResult
))
1594 // FIXME: we should cache this....
1595 SFGAOF rfg
= SFGAO_BROWSABLE
| SFGAO_CANCOPY
| SFGAO_CANLINK
| SFGAO_CANMOVE
| SFGAO_CANDELETE
| SFGAO_CANRENAME
| SFGAO_HASPROPSHEET
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
;
1596 hResult
= m_pSFParent
->GetAttributesOf(m_cidl
, m_apidl
, &rfg
);
1597 if (FAILED_UNEXPECTEDLY(hResult
))
1600 if (!(rfg
& SFGAO_CANMOVE
) && uCommand
== FCIDM_SHVIEW_CUT
)
1602 if (!(rfg
& SFGAO_CANCOPY
) && uCommand
== FCIDM_SHVIEW_COPY
)
1604 if (!(rfg
& SFGAO_CANDELETE
) && uCommand
== FCIDM_SHVIEW_DELETE
)
1606 if (!(rfg
& SFGAO_CANRENAME
) && uCommand
== FCIDM_SHVIEW_RENAME
)
1608 if (!(rfg
& SFGAO_HASPROPSHEET
) && uCommand
== FCIDM_SHVIEW_PROPERTIES
)
1612 InvokeContextMenuCommand(uCommand
);
1617 IUnknown_SetSite(m_pCM
, NULL
);
1627 /**********************************************************
1628 * ##### message handling #####
1631 /**********************************************************
1632 * ShellView_OnSize()
1634 LRESULT
CDefView::OnSize(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1636 WORD wWidth
, wHeight
;
1638 wWidth
= LOWORD(lParam
);
1639 wHeight
= HIWORD(lParam
);
1641 TRACE("%p width=%u height=%u\n", this, wWidth
, wHeight
);
1643 /* Resize the ListView to fit our window */
1646 ::MoveWindow(m_ListView
, 0, 0, wWidth
, wHeight
, TRUE
);
1649 _DoFolderViewCB(SFVM_SIZE
, 0, 0);
1654 /**********************************************************
1655 * ShellView_OnDeactivate()
1660 void CDefView::OnDeactivate()
1662 TRACE("%p\n", this);
1664 if (m_uState
!= SVUIA_DEACTIVATE
)
1666 // TODO: cleanup menu after deactivation
1668 m_uState
= SVUIA_DEACTIVATE
;
1672 void CDefView::DoActivate(UINT uState
)
1674 TRACE("%p uState=%x\n", this, uState
);
1676 /*don't do anything if the state isn't really changing */
1677 if (m_uState
== uState
)
1682 if (uState
== SVUIA_DEACTIVATE
)
1688 if(m_hMenu
&& !m_bmenuBarInitialized
)
1692 m_pShellBrowser
->SetMenuSB(m_hMenu
, 0, m_hWnd
);
1693 m_bmenuBarInitialized
= TRUE
;
1696 if (SVUIA_ACTIVATE_FOCUS
== uState
)
1698 m_ListView
.SetFocus();
1706 /**********************************************************
1707 * ShellView_OnActivate()
1709 LRESULT
CDefView::OnActivate(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1711 DoActivate(SVUIA_ACTIVATE_FOCUS
);
1715 /**********************************************************
1716 * ShellView_OnSetFocus()
1719 LRESULT
CDefView::OnSetFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1721 TRACE("%p\n", this);
1723 /* Tell the browser one of our windows has received the focus. This
1724 should always be done before merging menus (OnActivate merges the
1725 menus) if one of our windows has the focus.*/
1727 m_pShellBrowser
->OnViewWindowActive(this);
1728 DoActivate(SVUIA_ACTIVATE_FOCUS
);
1730 /* Set the focus to the listview */
1731 m_ListView
.SetFocus();
1733 /* Notify the ICommDlgBrowser interface */
1734 OnStateChange(CDBOSC_SETFOCUS
);
1739 /**********************************************************
1740 * ShellView_OnKillFocus()
1742 LRESULT
CDefView::OnKillFocus(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1744 TRACE("(%p) stub\n", this);
1746 DoActivate(SVUIA_ACTIVATE_NOFOCUS
);
1747 /* Notify the ICommDlgBrowser */
1748 OnStateChange(CDBOSC_KILLFOCUS
);
1753 /**********************************************************
1754 * ShellView_OnCommand()
1757 * the CmdID's are the ones from the context menu
1759 LRESULT
CDefView::OnCommand(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1766 dwCmdID
= GET_WM_COMMAND_ID(wParam
, lParam
);
1767 dwCmd
= GET_WM_COMMAND_CMD(wParam
, lParam
);
1768 hwndCmd
= GET_WM_COMMAND_HWND(wParam
, lParam
);
1770 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n", this, dwCmdID
, dwCmd
, hwndCmd
);
1774 case FCIDM_SHVIEW_SMALLICON
:
1775 m_FolderSettings
.ViewMode
= FVM_SMALLICON
;
1776 m_ListView
.ModifyStyle(LVS_TYPEMASK
, LVS_SMALLICON
);
1780 case FCIDM_SHVIEW_BIGICON
:
1781 m_FolderSettings
.ViewMode
= FVM_ICON
;
1782 m_ListView
.ModifyStyle(LVS_TYPEMASK
, LVS_ICON
);
1786 case FCIDM_SHVIEW_LISTVIEW
:
1787 m_FolderSettings
.ViewMode
= FVM_LIST
;
1788 m_ListView
.ModifyStyle(LVS_TYPEMASK
, LVS_LIST
);
1792 case FCIDM_SHVIEW_REPORTVIEW
:
1793 m_FolderSettings
.ViewMode
= FVM_DETAILS
;
1794 m_ListView
.ModifyStyle(LVS_TYPEMASK
, LVS_REPORT
);
1798 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1803 m_sortInfo
.nHeaderID
= dwCmdID
- 0x30;
1804 m_sortInfo
.bIsAscending
= TRUE
;
1808 case FCIDM_SHVIEW_SNAPTOGRID
:
1809 m_ListView
.Arrange(LVA_SNAPTOGRID
);
1811 case FCIDM_SHVIEW_ALIGNTOGRID
:
1812 if (_GetSnapToGrid() == S_OK
)
1813 m_ListView
.SetExtendedListViewStyle(0, LVS_EX_SNAPTOGRID
);
1817 case FCIDM_SHVIEW_AUTOARRANGE
:
1818 if (GetAutoArrange() == S_OK
)
1819 m_ListView
.ModifyStyle(LVS_AUTOARRANGE
, 0);
1823 case FCIDM_SHVIEW_SELECTALL
:
1824 m_ListView
.SetItemState(-1, LVIS_SELECTED
, LVIS_SELECTED
);
1827 case FCIDM_SHVIEW_INVERTSELECTION
:
1828 nCount
= m_ListView
.GetItemCount();
1829 for (int i
=0; i
< nCount
; i
++)
1830 m_ListView
.SetItemState(i
, m_ListView
.GetItemState(i
, LVIS_SELECTED
) ? 0 : LVIS_SELECTED
, LVIS_SELECTED
);
1833 case FCIDM_SHVIEW_REFRESH
:
1837 case FCIDM_SHVIEW_DELETE
:
1838 case FCIDM_SHVIEW_CUT
:
1839 case FCIDM_SHVIEW_COPY
:
1840 case FCIDM_SHVIEW_RENAME
:
1841 case FCIDM_SHVIEW_PROPERTIES
:
1842 case FCIDM_SHVIEW_COPYTO
:
1843 case FCIDM_SHVIEW_MOVETO
:
1844 if (SHRestricted(REST_NOVIEWCONTEXTMENU
))
1847 return OnExplorerCommand(dwCmdID
, TRUE
);
1849 case FCIDM_SHVIEW_INSERT
:
1850 case FCIDM_SHVIEW_UNDO
:
1851 case FCIDM_SHVIEW_INSERTLINK
:
1852 case FCIDM_SHVIEW_NEWFOLDER
:
1853 return OnExplorerCommand(dwCmdID
, FALSE
);
1855 /* WM_COMMAND messages from the file menu are routed to the CDefView so as to let m_pCM handle the command */
1856 if (m_pCM
&& dwCmd
== 0)
1858 InvokeContextMenuCommand(dwCmdID
);
1866 SelectExtOnRename(void)
1870 DWORD dwValue
= FALSE
, cbValue
;
1872 error
= RegOpenKeyExW(HKEY_CURRENT_USER
,
1873 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer",
1874 0, KEY_READ
, &hKey
);
1878 cbValue
= sizeof(dwValue
);
1879 RegQueryValueExW(hKey
, L
"SelectExtOnRename", NULL
, NULL
, (LPBYTE
)&dwValue
, &cbValue
);
1885 /**********************************************************
1886 * ShellView_OnNotify()
1889 LRESULT
CDefView::OnNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
1893 LPNMLISTVIEW lpnmlv
;
1894 NMLVDISPINFOW
*lpdi
;
1895 PCUITEMID_CHILD pidl
;
1899 lpnmh
= (LPNMHDR
)lParam
;
1900 lpnmlv
= (LPNMLISTVIEW
)lpnmh
;
1901 lpdi
= (NMLVDISPINFOW
*)lpnmh
;
1903 TRACE("%p CtlID=%u lpnmh->code=%x\n", this, CtlID
, lpnmh
->code
);
1905 switch (lpnmh
->code
)
1908 TRACE("-- NM_SETFOCUS %p\n", this);
1909 OnSetFocus(0, 0, 0, unused
);
1913 TRACE("-- NM_KILLFOCUS %p\n", this);
1915 /* Notify the ICommDlgBrowser interface */
1916 OnStateChange(CDBOSC_KILLFOCUS
);
1920 TRACE("-- NM_CUSTOMDRAW %p\n", this);
1921 return CDRF_DODEFAULT
;
1923 case NM_RELEASEDCAPTURE
:
1924 TRACE("-- NM_RELEASEDCAPTURE %p\n", this);
1928 TRACE("-- NM_CLICK %p\n", this);
1932 TRACE("-- NM_RCLICK %p\n", this);
1936 TRACE("-- NM_DBLCLK %p\n", this);
1937 OpenSelectedItems();
1941 TRACE("-- NM_RETURN %p\n", this);
1942 OpenSelectedItems();
1946 TRACE("-- HDN_ENDTRACKW %p\n", this);
1947 /*nColumn1 = m_ListView.GetColumnWidth(0);
1948 nColumn2 = m_ListView.GetColumnWidth(1);*/
1951 case LVN_DELETEITEM
:
1952 TRACE("-- LVN_DELETEITEM %p\n", this);
1954 /*delete the pidl because we made a copy of it*/
1955 SHFree(reinterpret_cast<LPVOID
>(lpnmlv
->lParam
));
1959 case LVN_DELETEALLITEMS
:
1960 TRACE("-- LVN_DELETEALLITEMS %p\n", this);
1963 case LVN_INSERTITEM
:
1964 TRACE("-- LVN_INSERTITEM (STUB)%p\n", this);
1967 case LVN_ITEMACTIVATE
:
1968 TRACE("-- LVN_ITEMACTIVATE %p\n", this);
1969 OnStateChange(CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
1972 case LVN_COLUMNCLICK
:
1973 m_sortInfo
.nHeaderID
= lpnmlv
->iSubItem
;
1974 if (m_sortInfo
.nLastHeaderID
== m_sortInfo
.nHeaderID
)
1975 m_sortInfo
.bIsAscending
= !m_sortInfo
.bIsAscending
;
1977 m_sortInfo
.bIsAscending
= TRUE
;
1981 case LVN_GETDISPINFOA
:
1982 case LVN_GETDISPINFOW
:
1983 TRACE("-- LVN_GETDISPINFO %p\n", this);
1984 pidl
= _PidlByItem(lpdi
->item
);
1986 if (lpdi
->item
.mask
& LVIF_TEXT
) /* text requested */
1991 if (FAILED_UNEXPECTEDLY(m_pSF2Parent
->GetDetailsOf(pidl
, lpdi
->item
.iSubItem
, &sd
)))
1994 if (lpnmh
->code
== LVN_GETDISPINFOA
)
1996 /* shouldn't happen */
1997 NMLVDISPINFOA
*lpdiA
= (NMLVDISPINFOA
*)lpnmh
;
1998 StrRetToStrNA( lpdiA
->item
.pszText
, lpdiA
->item
.cchTextMax
, &sd
.str
, NULL
);
1999 TRACE("-- text=%s\n", lpdiA
->item
.pszText
);
2001 else /* LVN_GETDISPINFOW */
2003 StrRetToStrNW( lpdi
->item
.pszText
, lpdi
->item
.cchTextMax
, &sd
.str
, NULL
);
2004 TRACE("-- text=%s\n", debugstr_w(lpdi
->item
.pszText
));
2009 FIXME("no m_pSF2Parent\n");
2012 if(lpdi
->item
.mask
& LVIF_IMAGE
) /* image requested */
2014 lpdi
->item
.iImage
= SHMapPIDLToSystemImageListIndex(m_pSFParent
, pidl
, 0);
2016 if(lpdi
->item
.mask
& LVIF_STATE
)
2018 ULONG attributes
= SFGAO_HIDDEN
;
2019 if (SUCCEEDED(m_pSFParent
->GetAttributesOf(1, &pidl
, &attributes
)))
2021 if (attributes
& SFGAO_HIDDEN
)
2023 lpdi
->item
.state
|= LVIS_CUT
;
2027 lpdi
->item
.mask
|= LVIF_DI_SETITEM
;
2030 case LVN_ITEMCHANGED
:
2031 TRACE("-- LVN_ITEMCHANGED %p\n", this);
2032 OnStateChange(CDBOSC_SELCHANGE
); /* the browser will get the IDataObject now */
2034 _DoFolderViewCB(SFVM_SELECTIONCHANGED
, NULL
/* FIXME */, NULL
/* FIXME */);
2038 case LVN_BEGINRDRAG
:
2039 TRACE("-- LVN_BEGINDRAG\n");
2041 if (GetSelections())
2043 CComPtr
<IDataObject
> pda
;
2044 DWORD dwAttributes
= SFGAO_CANCOPY
| SFGAO_CANLINK
;
2045 DWORD dwEffect
= DROPEFFECT_MOVE
;
2047 if (SUCCEEDED(m_pSFParent
->GetUIObjectOf(m_hWnd
, m_cidl
, m_apidl
, IID_NULL_PPV_ARG(IDataObject
, &pda
))))
2049 LPNMLISTVIEW params
= (LPNMLISTVIEW
)lParam
;
2051 if (SUCCEEDED(m_pSFParent
->GetAttributesOf(m_cidl
, m_apidl
, &dwAttributes
)))
2053 dwEffect
|= dwAttributes
& (SFGAO_CANCOPY
| SFGAO_CANLINK
);
2056 CComPtr
<IAsyncOperation
> piaso
;
2057 if (SUCCEEDED(pda
->QueryInterface(IID_PPV_ARG(IAsyncOperation
, &piaso
))))
2059 piaso
->SetAsyncMode(TRUE
);
2064 m_pSourceDataObject
= pda
;
2065 m_ptFirstMousePos
= params
->ptAction
;
2066 ClientToScreen(&m_ptFirstMousePos
);
2067 ::ClientToListView(m_ListView
, &m_ptFirstMousePos
);
2069 HIMAGELIST big_icons
, small_icons
;
2070 Shell_GetImageLists(&big_icons
, &small_icons
);
2071 PCUITEMID_CHILD pidl
= _PidlByItem(params
->iItem
);
2072 int iIcon
= SHMapPIDLToSystemImageListIndex(m_pSFParent
, pidl
, 0);
2074 m_ListView
.GetItemPosition(params
->iItem
, &ptItem
);
2076 ImageList_BeginDrag(big_icons
, iIcon
, params
->ptAction
.x
- ptItem
.x
, params
->ptAction
.y
- ptItem
.y
);
2078 DoDragDrop(pda
, this, dwEffect
, &dwEffect2
);
2080 m_pSourceDataObject
.Release();
2085 case LVN_BEGINLABELEDITW
:
2087 DWORD dwAttr
= SFGAO_CANRENAME
;
2088 pidl
= _PidlByItem(lpdi
->item
);
2090 TRACE("-- LVN_BEGINLABELEDITW %p\n", this);
2092 m_pSFParent
->GetAttributesOf(1, &pidl
, &dwAttr
);
2093 if (SFGAO_CANRENAME
& dwAttr
)
2095 HWND hEdit
= reinterpret_cast<HWND
>(m_ListView
.SendMessage(LVM_GETEDITCONTROL
));
2096 SHLimitInputEdit(hEdit
, m_pSFParent
);
2098 /* smartass-renaming: See CORE-15242 */
2099 if (!(dwAttr
& SFGAO_FOLDER
) && (dwAttr
& SFGAO_FILESYSTEM
) &&
2100 (lpdi
->item
.mask
& LVIF_TEXT
) && !SelectExtOnRename())
2102 WCHAR szFullPath
[MAX_PATH
];
2103 PIDLIST_ABSOLUTE pidlFull
= ILCombine(m_pidlParent
, pidl
);
2104 SHGetPathFromIDListW(pidlFull
, szFullPath
);
2106 if (!SHELL_FS_HideExtension(szFullPath
))
2108 LPWSTR pszText
= lpdi
->item
.pszText
;
2109 LPWSTR pchDotExt
= PathFindExtensionW(pszText
);
2110 ::PostMessageW(hEdit
, EM_SETSEL
, 0, pchDotExt
- pszText
);
2111 ::PostMessageW(hEdit
, EM_SCROLLCARET
, 0, 0);
2124 case LVN_ENDLABELEDITW
:
2126 TRACE("-- LVN_ENDLABELEDITW %p\n", this);
2128 m_isEditing
= FALSE
;
2130 if (lpdi
->item
.pszText
)
2135 pidl
= _PidlByItem(lpdi
->item
);
2136 PITEMID_CHILD pidlNew
= NULL
;
2137 hr
= m_pSFParent
->SetNameOf(0, pidl
, lpdi
->item
.pszText
, SHGDN_INFOLDER
, &pidlNew
);
2139 if (SUCCEEDED(hr
) && pidlNew
)
2141 lvItem
.mask
= LVIF_PARAM
|LVIF_IMAGE
;
2142 lvItem
.iItem
= lpdi
->item
.iItem
;
2143 lvItem
.iSubItem
= 0;
2144 lvItem
.lParam
= reinterpret_cast<LPARAM
>(pidlNew
);
2145 lvItem
.iImage
= SHMapPIDLToSystemImageListIndex(m_pSFParent
, pidlNew
, 0);
2146 m_ListView
.SetItem(&lvItem
);
2147 m_ListView
.Update(lpdi
->item
.iItem
);
2156 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh
->code
);
2164 * This is just a quick hack to make the desktop work correctly.
2165 * ITranslateShellChangeNotify's IsChildID is undocumented, but most likely the way that
2166 * a folder should know if it should update upon a change notification.
2167 * It is exported by merged folders at a minimum.
2169 static BOOL
ILIsParentOrSpecialParent(PCIDLIST_ABSOLUTE pidl1
, PCIDLIST_ABSOLUTE pidl2
)
2171 if (!pidl1
|| !pidl2
)
2173 if (ILIsParent(pidl1
, pidl2
, TRUE
))
2176 if (_ILIsDesktop(pidl1
))
2178 PIDLIST_ABSOLUTE deskpidl
;
2179 SHGetFolderLocation(NULL
, CSIDL_DESKTOPDIRECTORY
, NULL
, 0, &deskpidl
);
2180 if (ILIsParent(deskpidl
, pidl2
, TRUE
))
2186 SHGetFolderLocation(NULL
, CSIDL_COMMON_DESKTOPDIRECTORY
, NULL
, 0, &deskpidl
);
2187 if (ILIsParent(deskpidl
, pidl2
, TRUE
))
2195 WCHAR szPath1
[MAX_PATH
], szPath2
[MAX_PATH
];
2196 LPITEMIDLIST pidl2Clone
= ILClone(pidl2
);
2197 ILRemoveLastID(pidl2Clone
);
2198 if (SHGetPathFromIDListW(pidl1
, szPath1
) &&
2199 SHGetPathFromIDListW(pidl2Clone
, szPath2
))
2201 if (lstrcmpiW(szPath1
, szPath2
) == 0)
2212 /**********************************************************
2213 * ShellView_OnChange()
2215 LRESULT
CDefView::OnChangeNotify(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2217 HANDLE hChange
= (HANDLE
)wParam
;
2218 DWORD dwProcID
= (DWORD
)lParam
;
2219 PIDLIST_ABSOLUTE
*Pidls
;
2221 HANDLE hLock
= SHChangeNotification_Lock(hChange
, dwProcID
, &Pidls
, &lEvent
);
2224 ERR("hLock == NULL\n");
2228 BOOL bParent0
= ILIsParentOrSpecialParent(m_pidlParent
, Pidls
[0]);
2229 BOOL bParent1
= ILIsParentOrSpecialParent(m_pidlParent
, Pidls
[1]);
2231 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls
[0], Pidls
[1], lParam
);
2233 lEvent
&= ~SHCNE_INTERRUPT
;
2240 if (LV_FindItemByPidl(ILFindLastID(Pidls
[0])) == -1)
2242 LV_AddItem(ILFindLastID(Pidls
[0]));
2246 LV_ProdItem(ILFindLastID(Pidls
[0]));
2254 LV_DeleteItem(ILFindLastID(Pidls
[0]));
2257 case SHCNE_RENAMEFOLDER
:
2258 case SHCNE_RENAMEITEM
:
2259 if (bParent0
&& bParent1
)
2260 LV_RenameItem(ILFindLastID(Pidls
[0]), ILFindLastID(Pidls
[1]));
2262 LV_DeleteItem(ILFindLastID(Pidls
[0]));
2264 LV_AddItem(ILFindLastID(Pidls
[1]));
2267 case SHCNE_UPDATEITEM
:
2269 LV_RenameItem(ILFindLastID(Pidls
[0]), ILFindLastID(Pidls
[0]));
2272 case SHCNE_UPDATEDIR
:
2277 SHChangeNotification_Unlock(hLock
);
2281 HRESULT
SHGetMenuIdFromMenuMsg(UINT uMsg
, LPARAM lParam
, UINT
*CmdId
);
2282 HRESULT
SHSetMenuIdInMenuMsg(UINT uMsg
, LPARAM lParam
, UINT CmdId
);
2284 /**********************************************************
2285 * CDefView::OnCustomItem
2287 LRESULT
CDefView::OnCustomItem(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2292 ERR("no menu!!!\n");
2296 /* The lParam of WM_DRAWITEM WM_MEASUREITEM contain a menu id and this also needs to
2297 be changed to a menu identifier offset */
2299 HRESULT hres
= SHGetMenuIdFromMenuMsg(uMsg
, lParam
, &CmdID
);
2300 if (SUCCEEDED(hres
))
2301 SHSetMenuIdInMenuMsg(uMsg
, lParam
, CmdID
- CONTEXT_MENU_BASE_ID
);
2303 /* Forward the message to the IContextMenu2 */
2305 hres
= SHForwardContextMenuMsg(m_pCM
, uMsg
, wParam
, lParam
, &result
, TRUE
);
2307 return (SUCCEEDED(hres
));
2310 LRESULT
CDefView::OnSettingChange(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2312 /* Wallpaper setting affects drop shadows effect */
2313 if (wParam
== SPI_SETDESKWALLPAPER
|| wParam
== 0)
2319 /**********************************************************
2320 * CDefView::OnInitMenuPopup
2322 LRESULT
CDefView::OnInitMenuPopup(UINT uMsg
, WPARAM wParam
, LPARAM lParam
, BOOL
&bHandled
)
2324 HMENU hmenu
= (HMENU
) wParam
;
2325 int nPos
= LOWORD(lParam
);
2328 OnCustomItem(uMsg
, wParam
, lParam
, bHandled
);
2330 HMENU hViewMenu
= GetSubmenuByID(m_hMenu
, FCIDM_MENU_VIEW
);
2332 if (GetSelections() == 0)
2334 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_CUT
, MF_GRAYED
);
2335 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_COPY
, MF_GRAYED
);
2336 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_RENAME
, MF_GRAYED
);
2337 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_COPYTO
, MF_GRAYED
);
2338 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_MOVETO
, MF_GRAYED
);
2339 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_DELETE
, MF_GRAYED
);
2343 // FIXME: Check copyable
2344 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_CUT
, MF_ENABLED
);
2345 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_COPY
, MF_ENABLED
);
2346 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_RENAME
, MF_ENABLED
);
2347 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_COPYTO
, MF_ENABLED
);
2348 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_MOVETO
, MF_ENABLED
);
2349 ::EnableMenuItem(hmenu
, FCIDM_SHVIEW_DELETE
, MF_ENABLED
);
2352 /* Lets try to find out what the hell wParam is */
2353 if (hmenu
== GetSubMenu(m_hMenu
, nPos
))
2354 menuItemId
= ReallyGetMenuItemID(m_hMenu
, nPos
);
2355 else if (hViewMenu
&& hmenu
== GetSubMenu(hViewMenu
, nPos
))
2356 menuItemId
= ReallyGetMenuItemID(hViewMenu
, nPos
);
2357 else if (m_hContextMenu
&& hmenu
== GetSubMenu(m_hContextMenu
, nPos
))
2358 menuItemId
= ReallyGetMenuItemID(m_hContextMenu
, nPos
);
2364 case FCIDM_MENU_FILE
:
2367 case FCIDM_MENU_VIEW
:
2368 case FCIDM_SHVIEW_VIEW
:
2369 CheckViewMode(hmenu
);
2371 case FCIDM_SHVIEW_ARRANGE
:
2372 FillArrangeAsMenu(hmenu
);
2379 /**********************************************************
2382 * The INTERFACE of the IShellView object
2385 **********************************************************
2388 /**********************************************************
2389 * ShellView_GetWindow
2391 HRESULT WINAPI
CDefView::GetWindow(HWND
*phWnd
)
2393 TRACE("(%p)\n", this);
2400 HRESULT WINAPI
CDefView::ContextSensitiveHelp(BOOL fEnterMode
)
2402 FIXME("(%p) stub\n", this);
2407 /**********************************************************
2408 * IShellView_TranslateAccelerator
2411 * use the accel functions
2413 HRESULT WINAPI
CDefView::TranslateAccelerator(LPMSG lpmsg
)
2418 if (lpmsg
->message
>= WM_KEYFIRST
&& lpmsg
->message
<= WM_KEYLAST
)
2420 if (::TranslateAcceleratorW(m_hWnd
, m_hAccel
, lpmsg
) != 0)
2423 TRACE("-- key=0x%04lx\n", lpmsg
->wParam
) ;
2426 return m_pShellBrowser
->TranslateAcceleratorSB(lpmsg
, 0);
2429 HRESULT WINAPI
CDefView::EnableModeless(BOOL fEnable
)
2431 FIXME("(%p) stub\n", this);
2436 HRESULT WINAPI
CDefView::UIActivate(UINT uState
)
2438 // CHAR szName[MAX_PATH];
2440 int nPartArray
[1] = { -1};
2442 TRACE("(%p)->(state=%x) stub\n", this, uState
);
2444 /* don't do anything if the state isn't really changing */
2445 if (m_uState
== uState
)
2450 /* OnActivate handles the menu merging and internal state */
2453 /* only do This if we are active */
2454 if (uState
!= SVUIA_DEACTIVATE
)
2458 GetFolderPath is not a method of IShellFolder
2459 IShellFolder_GetFolderPath( m_pSFParent, szName, sizeof(szName) );
2461 /* set the number of parts */
2462 m_pShellBrowser
->SendControlMsg(FCW_STATUS
, SB_SETPARTS
, 1, (LPARAM
)nPartArray
, &lResult
);
2464 /* set the text for the parts */
2466 m_pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult);
2473 HRESULT WINAPI
CDefView::Refresh()
2475 TRACE("(%p)\n", this);
2477 _DoFolderViewCB(SFVM_LISTREFRESHED
, TRUE
, 0);
2479 m_ListView
.DeleteAllItems();
2485 HRESULT WINAPI
CDefView::CreateViewWindow(IShellView
*lpPrevView
, LPCFOLDERSETTINGS lpfs
, IShellBrowser
*psb
, RECT
*prcView
, HWND
*phWnd
)
2487 return CreateViewWindow3(psb
, lpPrevView
, SV3CVW3_DEFAULT
,
2488 (FOLDERFLAGS
)lpfs
->fFlags
, (FOLDERFLAGS
)lpfs
->fFlags
, (FOLDERVIEWMODE
)lpfs
->ViewMode
, NULL
, prcView
, phWnd
);
2491 HRESULT WINAPI
CDefView::DestroyViewWindow()
2493 TRACE("(%p)\n", this);
2495 /* Make absolutely sure all our UI is cleaned up */
2496 UIActivate(SVUIA_DEACTIVATE
);
2500 // "Accelerator tables loaded from resources are freed automatically when the application terminates." -- MSDN
2504 if (m_hMenuArrangeModes
)
2506 DestroyMenu(m_hMenuArrangeModes
);
2507 m_hMenuArrangeModes
= NULL
;
2510 if (m_hMenuViewModes
)
2512 DestroyMenu(m_hMenuViewModes
);
2513 m_hMenuViewModes
= NULL
;
2518 DestroyMenu(m_hMenu
);
2524 m_ListView
.DestroyWindow();
2529 _DoFolderViewCB(SFVM_WINDOWCLOSING
, (WPARAM
)m_hWnd
, 0);
2533 m_pShellBrowser
.Release();
2534 m_pCommDlgBrowser
.Release();
2539 HRESULT WINAPI
CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs
)
2541 TRACE("(%p)->(%p) vmode=%x flags=%x\n", this, lpfs
,
2542 m_FolderSettings
.ViewMode
, m_FolderSettings
.fFlags
);
2545 return E_INVALIDARG
;
2547 *lpfs
= m_FolderSettings
;
2551 HRESULT WINAPI
CDefView::AddPropertySheetPages(DWORD dwReserved
, LPFNADDPROPSHEETPAGE lpfn
, LPARAM lparam
)
2553 FIXME("(%p) stub\n", this);
2558 HRESULT WINAPI
CDefView::SaveViewState()
2560 FIXME("(%p) stub\n", this);
2565 HRESULT WINAPI
CDefView::SelectItem(PCUITEMID_CHILD pidl
, UINT uFlags
)
2569 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n", this, pidl
, uFlags
);
2571 i
= LV_FindItemByPidl(pidl
);
2575 LVITEMW lvItem
= {0};
2576 lvItem
.mask
= LVIF_STATE
;
2577 lvItem
.stateMask
= LVIS_SELECTED
| LVIS_FOCUSED
;
2579 while (m_ListView
.GetItem(&lvItem
))
2581 if (lvItem
.iItem
== i
)
2583 if (uFlags
& SVSI_SELECT
)
2584 lvItem
.state
|= LVIS_SELECTED
;
2586 lvItem
.state
&= ~LVIS_SELECTED
;
2588 if (uFlags
& SVSI_FOCUSED
)
2589 lvItem
.state
|= LVIS_FOCUSED
;
2591 lvItem
.state
&= ~LVIS_FOCUSED
;
2595 if (uFlags
& SVSI_DESELECTOTHERS
)
2597 lvItem
.state
&= ~LVIS_SELECTED
;
2599 lvItem
.state
&= ~LVIS_FOCUSED
;
2602 m_ListView
.SetItem(&lvItem
);
2606 if (uFlags
& SVSI_ENSUREVISIBLE
)
2607 m_ListView
.EnsureVisible(i
, FALSE
);
2609 if((uFlags
& SVSI_EDIT
) == SVSI_EDIT
)
2610 m_ListView
.EditLabel(i
);
2615 HRESULT WINAPI
CDefView::GetItemObject(UINT uItem
, REFIID riid
, LPVOID
*ppvOut
)
2617 HRESULT hr
= E_NOINTERFACE
;
2619 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n", this, uItem
, debugstr_guid(&riid
), ppvOut
);
2622 return E_INVALIDARG
;
2628 case SVGIO_BACKGROUND
:
2629 if (IsEqualIID(riid
, IID_IContextMenu
))
2631 hr
= CDefViewBckgrndMenu_CreateInstance(m_pSF2Parent
, riid
, ppvOut
);
2632 if (FAILED_UNEXPECTEDLY(hr
))
2635 IUnknown_SetSite(*((IUnknown
**)ppvOut
), (IShellView
*)this);
2637 else if (IsEqualIID(riid
, IID_IDispatch
))
2639 if (m_pShellFolderViewDual
== NULL
)
2641 hr
= CDefViewDual_Constructor(riid
, (LPVOID
*)&m_pShellFolderViewDual
);
2642 if (FAILED_UNEXPECTEDLY(hr
))
2645 hr
= m_pShellFolderViewDual
->QueryInterface(riid
, ppvOut
);
2649 case SVGIO_SELECTION
:
2651 hr
= m_pSFParent
->GetUIObjectOf(m_hWnd
, m_cidl
, m_apidl
, riid
, 0, ppvOut
);
2652 if (FAILED_UNEXPECTEDLY(hr
))
2655 if (IsEqualIID(riid
, IID_IContextMenu
))
2656 IUnknown_SetSite(*((IUnknown
**)ppvOut
), (IShellView
*)this);
2661 TRACE("-- (%p)->(interface=%p)\n", this, *ppvOut
);
2666 HRESULT STDMETHODCALLTYPE
CDefView::GetCurrentViewMode(UINT
*pViewMode
)
2668 TRACE("(%p)->(%p), stub\n", this, pViewMode
);
2671 return E_INVALIDARG
;
2673 *pViewMode
= m_FolderSettings
.ViewMode
;
2677 HRESULT STDMETHODCALLTYPE
CDefView::SetCurrentViewMode(UINT ViewMode
)
2680 TRACE("(%p)->(%u), stub\n", this, ViewMode
);
2682 /* It's not redundant to check FVM_AUTO because it's a (UINT)-1 */
2683 if (((INT
)ViewMode
< FVM_FIRST
|| (INT
)ViewMode
> FVM_LAST
) && ((INT
)ViewMode
!= FVM_AUTO
))
2684 return E_INVALIDARG
;
2686 /* Windows before Vista uses LVM_SETVIEW and possibly
2687 LVM_SETEXTENDEDLISTVIEWSTYLE to set the style of the listview,
2688 while later versions seem to accomplish this through other
2696 dwStyle
= LVS_REPORT
;
2699 dwStyle
= LVS_SMALLICON
;
2706 FIXME("ViewMode %d not implemented\n", ViewMode
);
2712 m_ListView
.ModifyStyle(LVS_TYPEMASK
, dwStyle
);
2714 /* This will not necessarily be the actual mode set above.
2715 This mimics the behavior of Windows XP. */
2716 m_FolderSettings
.ViewMode
= ViewMode
;
2721 HRESULT STDMETHODCALLTYPE
CDefView::GetFolder(REFIID riid
, void **ppv
)
2723 if (m_pSFParent
== NULL
)
2726 return m_pSFParent
->QueryInterface(riid
, ppv
);
2729 HRESULT STDMETHODCALLTYPE
CDefView::Item(int iItemIndex
, PITEMID_CHILD
*ppidl
)
2731 PCUITEMID_CHILD pidl
= _PidlByItem(iItemIndex
);
2734 *ppidl
= ILClone(pidl
);
2739 return E_INVALIDARG
;
2742 HRESULT STDMETHODCALLTYPE
CDefView::ItemCount(UINT uFlags
, int *pcItems
)
2744 TRACE("(%p)->(%u %p)\n", this, uFlags
, pcItems
);
2746 if (uFlags
!= SVGIO_ALLVIEW
)
2747 FIXME("some flags unsupported, %x\n", uFlags
& ~SVGIO_ALLVIEW
);
2749 *pcItems
= m_ListView
.GetItemCount();
2754 HRESULT STDMETHODCALLTYPE
CDefView::Items(UINT uFlags
, REFIID riid
, void **ppv
)
2759 HRESULT STDMETHODCALLTYPE
CDefView::GetSelectionMarkedItem(int *piItem
)
2761 TRACE("(%p)->(%p)\n", this, piItem
);
2763 *piItem
= m_ListView
.GetSelectionMark();
2768 HRESULT STDMETHODCALLTYPE
CDefView::GetFocusedItem(int *piItem
)
2770 TRACE("(%p)->(%p)\n", this, piItem
);
2772 *piItem
= m_ListView
.GetNextItem(-1, LVNI_FOCUSED
);
2777 HRESULT STDMETHODCALLTYPE
CDefView::GetItemPosition(PCUITEMID_CHILD pidl
, POINT
*ppt
)
2779 int lvIndex
= LV_FindItemByPidl(pidl
);
2780 if (lvIndex
== -1 || ppt
== NULL
)
2781 return E_INVALIDARG
;
2783 m_ListView
.GetItemPosition(lvIndex
, ppt
);
2787 HRESULT STDMETHODCALLTYPE
CDefView::GetSpacing(POINT
*ppt
)
2789 TRACE("(%p)->(%p)\n", this, ppt
);
2797 m_ListView
.GetItemSpacing(spacing
);
2799 ppt
->x
= spacing
.cx
;
2800 ppt
->y
= spacing
.cy
;
2806 HRESULT STDMETHODCALLTYPE
CDefView::GetDefaultSpacing(POINT
*ppt
)
2811 HRESULT STDMETHODCALLTYPE
CDefView::GetAutoArrange()
2813 return ((m_ListView
.GetStyle() & LVS_AUTOARRANGE
) ? S_OK
: S_FALSE
);
2816 HRESULT
CDefView::_GetSnapToGrid()
2818 DWORD dwExStyle
= (DWORD
)m_ListView
.SendMessage(LVM_GETEXTENDEDLISTVIEWSTYLE
, 0, 0);
2819 return ((dwExStyle
& LVS_EX_SNAPTOGRID
) ? S_OK
: S_FALSE
);
2822 HRESULT STDMETHODCALLTYPE
CDefView::SelectItem(int iItem
, DWORD dwFlags
)
2826 TRACE("(%p)->(%d, %x)\n", this, iItem
, dwFlags
);
2829 lvItem
.stateMask
= LVIS_SELECTED
;
2831 if (dwFlags
& SVSI_ENSUREVISIBLE
)
2832 m_ListView
.EnsureVisible(iItem
, 0);
2835 if (dwFlags
& SVSI_DESELECTOTHERS
)
2836 m_ListView
.SetItemState(-1, 0, LVIS_SELECTED
);
2839 if (dwFlags
& SVSI_SELECT
)
2840 lvItem
.state
|= LVIS_SELECTED
;
2842 if (dwFlags
& SVSI_FOCUSED
)
2843 lvItem
.stateMask
|= LVIS_FOCUSED
;
2845 m_ListView
.SetItemState(iItem
, lvItem
.state
, lvItem
.stateMask
);
2847 if ((dwFlags
& SVSI_EDIT
) == SVSI_EDIT
)
2848 m_ListView
.EditLabel(iItem
);
2853 HRESULT STDMETHODCALLTYPE
CDefView::SelectAndPositionItems(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, POINT
*apt
, DWORD dwFlags
)
2855 /* Reset the selection */
2856 m_ListView
.SetItemState(-1, 0, LVIS_SELECTED
);
2859 for (UINT i
= 0 ; i
< m_cidl
; i
++)
2861 lvIndex
= LV_FindItemByPidl(apidl
[i
]);
2864 SelectItem(lvIndex
, dwFlags
);
2865 m_ListView
.SetItemPosition(lvIndex
, &apt
[i
]);
2872 /**********************************************************
2873 * IShellView2 implementation
2876 HRESULT STDMETHODCALLTYPE
CDefView::GetView(SHELLVIEWID
*view_guid
, ULONG view_type
)
2878 FIXME("(%p)->(%p, %lu) stub\n", this, view_guid
, view_type
);
2882 HRESULT STDMETHODCALLTYPE
CDefView::CreateViewWindow2(LPSV2CVW2_PARAMS view_params
)
2884 return CreateViewWindow3(view_params
->psbOwner
, view_params
->psvPrev
,
2885 SV3CVW3_DEFAULT
, (FOLDERFLAGS
)view_params
->pfs
->fFlags
, (FOLDERFLAGS
)view_params
->pfs
->fFlags
,
2886 (FOLDERVIEWMODE
)view_params
->pfs
->ViewMode
, view_params
->pvid
, view_params
->prcView
, &view_params
->hwndView
);
2889 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
)
2891 OLEMENUGROUPWIDTHS omw
= { { 0, 0, 0, 0, 0, 0 } };
2895 TRACE("(%p)->(shlview=%p shlbrs=%p rec=%p hwnd=%p vmode=%x flags=%x)\n", this, psvPrevious
, psb
, prcView
, hwnd
, mode
, flags
);
2896 if (prcView
!= NULL
)
2897 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView
->left
, prcView
->top
, prcView
->right
, prcView
->bottom
);
2899 /* Validate the Shell Browser */
2900 if (psb
== NULL
|| m_hWnd
)
2901 return E_UNEXPECTED
;
2903 if (view_flags
!= SV3CVW3_DEFAULT
)
2904 FIXME("unsupported view flags 0x%08x\n", view_flags
);
2906 /* Set up the member variables */
2907 m_pShellBrowser
= psb
;
2908 m_FolderSettings
.ViewMode
= mode
;
2909 m_FolderSettings
.fFlags
= mask
& flags
;
2913 if (IsEqualIID(*view_id
, VID_LargeIcons
))
2914 m_FolderSettings
.ViewMode
= FVM_ICON
;
2915 else if (IsEqualIID(*view_id
, VID_SmallIcons
))
2916 m_FolderSettings
.ViewMode
= FVM_SMALLICON
;
2917 else if (IsEqualIID(*view_id
, VID_List
))
2918 m_FolderSettings
.ViewMode
= FVM_LIST
;
2919 else if (IsEqualIID(*view_id
, VID_Details
))
2920 m_FolderSettings
.ViewMode
= FVM_DETAILS
;
2921 else if (IsEqualIID(*view_id
, VID_Thumbnails
))
2922 m_FolderSettings
.ViewMode
= FVM_THUMBNAIL
;
2923 else if (IsEqualIID(*view_id
, VID_Tile
))
2924 m_FolderSettings
.ViewMode
= FVM_TILE
;
2925 else if (IsEqualIID(*view_id
, VID_ThumbStrip
))
2926 m_FolderSettings
.ViewMode
= FVM_THUMBSTRIP
;
2928 FIXME("Ignoring unrecognized VID %s\n", debugstr_guid(view_id
));
2931 /* Get our parent window */
2932 m_pShellBrowser
->GetWindow(&m_hWndParent
);
2934 /* Try to get the ICommDlgBrowserInterface, adds a reference !!! */
2935 m_pCommDlgBrowser
= NULL
;
2936 if (SUCCEEDED(m_pShellBrowser
->QueryInterface(IID_PPV_ARG(ICommDlgBrowser
, &m_pCommDlgBrowser
))))
2938 TRACE("-- CommDlgBrowser\n");
2941 Create(m_hWndParent
, prcView
, NULL
, WS_CHILD
| WS_CLIPSIBLINGS
| WS_CLIPCHILDREN
| WS_TABSTOP
, 0, 0U);
2952 _DoFolderViewCB(SFVM_WINDOWCREATED
, (WPARAM
)m_hWnd
, 0);
2954 SetWindowPos(HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
| SWP_SHOWWINDOW
);
2959 m_hMenu
= CreateMenu();
2960 m_pShellBrowser
->InsertMenusSB(m_hMenu
, &omw
);
2961 TRACE("-- after fnInsertMenusSB\n");
2969 HRESULT STDMETHODCALLTYPE
CDefView::HandleRename(LPCITEMIDLIST new_pidl
)
2971 FIXME("(%p)->(%p) stub\n", this, new_pidl
);
2975 HRESULT STDMETHODCALLTYPE
CDefView::SelectAndPositionItem(LPCITEMIDLIST item
, UINT flags
, POINT
*point
)
2977 FIXME("(%p)->(%p, %u, %p) stub\n", this, item
, flags
, point
);
2981 /**********************************************************
2982 * IShellFolderView implementation
2984 HRESULT STDMETHODCALLTYPE
CDefView::Rearrange(LPARAM sort
)
2986 FIXME("(%p)->(%ld) stub\n", this, sort
);
2990 HRESULT STDMETHODCALLTYPE
CDefView::GetArrangeParam(LPARAM
*sort
)
2992 FIXME("(%p)->(%p) stub\n", this, sort
);
2996 HRESULT STDMETHODCALLTYPE
CDefView::ArrangeGrid()
2998 m_ListView
.SetExtendedListViewStyle(LVS_EX_SNAPTOGRID
, LVS_EX_SNAPTOGRID
);
3002 HRESULT STDMETHODCALLTYPE
CDefView::AutoArrange()
3004 m_ListView
.ModifyStyle(0, LVS_AUTOARRANGE
);
3005 m_ListView
.Arrange(LVA_DEFAULT
);
3009 HRESULT STDMETHODCALLTYPE
CDefView::AddObject(PITEMID_CHILD pidl
, UINT
*item
)
3011 TRACE("(%p)->(%p %p)\n", this, pidl
, item
);
3012 *item
= LV_AddItem(pidl
);
3013 return (int)*item
>= 0 ? S_OK
: E_OUTOFMEMORY
;
3016 HRESULT STDMETHODCALLTYPE
CDefView::GetObject(PITEMID_CHILD
*pidl
, UINT item
)
3018 TRACE("(%p)->(%p %d)\n", this, pidl
, item
);
3019 return Item(item
, pidl
);
3022 HRESULT STDMETHODCALLTYPE
CDefView::RemoveObject(PITEMID_CHILD pidl
, UINT
*item
)
3025 TRACE("(%p)->(%p %p)\n", this, pidl
, item
);
3029 *item
= LV_FindItemByPidl(ILFindLastID(pidl
));
3030 m_ListView
.DeleteItem(*item
);
3035 m_ListView
.DeleteAllItems();
3041 HRESULT STDMETHODCALLTYPE
CDefView::GetObjectCount(UINT
*count
)
3043 TRACE("(%p)->(%p)\n", this, count
);
3044 *count
= m_ListView
.GetItemCount();
3048 HRESULT STDMETHODCALLTYPE
CDefView::SetObjectCount(UINT count
, UINT flags
)
3050 FIXME("(%p)->(%d %x) stub\n", this, count
, flags
);
3054 HRESULT STDMETHODCALLTYPE
CDefView::UpdateObject(PITEMID_CHILD pidl_old
, PITEMID_CHILD pidl_new
, UINT
*item
)
3056 FIXME("(%p)->(%p %p %p) stub\n", this, pidl_old
, pidl_new
, item
);
3060 HRESULT STDMETHODCALLTYPE
CDefView::RefreshObject(PITEMID_CHILD pidl
, UINT
*item
)
3062 FIXME("(%p)->(%p %p) stub\n", this, pidl
, item
);
3066 HRESULT STDMETHODCALLTYPE
CDefView::SetRedraw(BOOL redraw
)
3068 TRACE("(%p)->(%d)\n", this, redraw
);
3069 m_ListView
.SetRedraw(redraw
);
3073 HRESULT STDMETHODCALLTYPE
CDefView::GetSelectedCount(UINT
*count
)
3075 FIXME("(%p)->(%p) stub\n", this, count
);
3079 HRESULT STDMETHODCALLTYPE
CDefView::GetSelectedObjects(PCUITEMID_CHILD
**pidl
, UINT
*items
)
3081 TRACE("(%p)->(%p %p)\n", this, pidl
, items
);
3083 *items
= GetSelections();
3087 *pidl
= static_cast<PCUITEMID_CHILD
*>(LocalAlloc(0, *items
* sizeof(PCUITEMID_CHILD
)));
3090 return E_OUTOFMEMORY
;
3093 /* it's documented that caller shouldn't PIDLs, only array itself */
3094 memcpy(*pidl
, m_apidl
, *items
* sizeof(PCUITEMID_CHILD
));
3100 HRESULT STDMETHODCALLTYPE
CDefView::IsDropOnSource(IDropTarget
*drop_target
)
3102 if ((m_iDragOverItem
== -1 || m_pCurDropTarget
== NULL
) &&
3103 (m_pSourceDataObject
.p
))
3111 HRESULT STDMETHODCALLTYPE
CDefView::GetDragPoint(POINT
*pt
)
3114 return E_INVALIDARG
;
3116 *pt
= m_ptFirstMousePos
;
3120 HRESULT STDMETHODCALLTYPE
CDefView::GetDropPoint(POINT
*pt
)
3122 FIXME("(%p)->(%p) stub\n", this, pt
);
3126 HRESULT STDMETHODCALLTYPE
CDefView::MoveIcons(IDataObject
*obj
)
3128 TRACE("(%p)->(%p)\n", this, obj
);
3132 HRESULT STDMETHODCALLTYPE
CDefView::SetItemPos(PCUITEMID_CHILD pidl
, POINT
*pt
)
3134 FIXME("(%p)->(%p %p) stub\n", this, pidl
, pt
);
3138 HRESULT STDMETHODCALLTYPE
CDefView::IsBkDropTarget(IDropTarget
*drop_target
)
3140 FIXME("(%p)->(%p) stub\n", this, drop_target
);
3144 HRESULT STDMETHODCALLTYPE
CDefView::SetClipboard(BOOL move
)
3146 FIXME("(%p)->(%d) stub\n", this, move
);
3150 HRESULT STDMETHODCALLTYPE
CDefView::SetPoints(IDataObject
*obj
)
3152 FIXME("(%p)->(%p) stub\n", this, obj
);
3156 HRESULT STDMETHODCALLTYPE
CDefView::GetItemSpacing(ITEMSPACING
*spacing
)
3158 FIXME("(%p)->(%p) stub\n", this, spacing
);
3162 HRESULT STDMETHODCALLTYPE
CDefView::SetCallback(IShellFolderViewCB
*new_cb
, IShellFolderViewCB
**old_cb
)
3165 *old_cb
= m_pShellFolderViewCB
.Detach();
3167 m_pShellFolderViewCB
= new_cb
;
3171 HRESULT STDMETHODCALLTYPE
CDefView::Select(UINT flags
)
3173 FIXME("(%p)->(%d) stub\n", this, flags
);
3177 HRESULT STDMETHODCALLTYPE
CDefView::QuerySupport(UINT
*support
)
3179 TRACE("(%p)->(%p)\n", this, support
);
3183 HRESULT STDMETHODCALLTYPE
CDefView::SetAutomationObject(IDispatch
*disp
)
3185 FIXME("(%p)->(%p) stub\n", this, disp
);
3189 /**********************************************************
3190 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
3192 HRESULT WINAPI
CDefView::QueryStatus(const GUID
*pguidCmdGroup
, ULONG cCmds
, OLECMD
*prgCmds
, OLECMDTEXT
*pCmdText
)
3194 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
3195 this, pguidCmdGroup
, debugstr_guid(pguidCmdGroup
), cCmds
, prgCmds
, pCmdText
);
3198 return E_INVALIDARG
;
3200 for (UINT i
= 0; i
< cCmds
; i
++)
3202 FIXME("\tprgCmds[%d].cmdID = %d\n", i
, prgCmds
[i
].cmdID
);
3203 prgCmds
[i
].cmdf
= 0;
3206 return OLECMDERR_E_UNKNOWNGROUP
;
3209 /**********************************************************
3210 * ISVOleCmdTarget_Exec (IOleCommandTarget)
3212 * nCmdID is the OLECMDID_* enumeration
3214 HRESULT WINAPI
CDefView::Exec(const GUID
*pguidCmdGroup
, DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
*pvaIn
, VARIANT
*pvaOut
)
3216 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
3217 this, debugstr_guid(pguidCmdGroup
), nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
3220 return OLECMDERR_E_UNKNOWNGROUP
;
3222 if (IsEqualCLSID(*pguidCmdGroup
, m_Category
))
3224 if (nCmdID
== FCIDM_SHVIEW_AUTOARRANGE
)
3226 if (V_VT(pvaIn
) != VT_INT_PTR
)
3227 return OLECMDERR_E_NOTSUPPORTED
;
3230 params
.cbSize
= sizeof(params
);
3231 params
.rcExclude
= *(RECT
*) V_INTREF(pvaIn
);
3233 if (m_hMenuViewModes
)
3235 /* Duplicate all but the last two items of the view modes menu */
3236 HMENU hmenuViewPopup
= CreatePopupMenu();
3237 Shell_MergeMenus(hmenuViewPopup
, m_hMenuViewModes
, 0, 0, 0xFFFF, 0);
3238 DeleteMenu(hmenuViewPopup
, GetMenuItemCount(hmenuViewPopup
) - 1, MF_BYPOSITION
);
3239 DeleteMenu(hmenuViewPopup
, GetMenuItemCount(hmenuViewPopup
) - 1, MF_BYPOSITION
);
3240 CheckViewMode(hmenuViewPopup
);
3241 TrackPopupMenuEx(hmenuViewPopup
, TPM_LEFTALIGN
| TPM_TOPALIGN
, params
.rcExclude
.left
, params
.rcExclude
.bottom
, m_hWndParent
, ¶ms
);
3242 ::DestroyMenu(hmenuViewPopup
);
3245 // pvaOut is VT_I4 with value 0x403 (cmd id of the new mode maybe?)
3246 V_VT(pvaOut
) = VT_I4
;
3247 V_I4(pvaOut
) = 0x403;
3251 if (IsEqualIID(*pguidCmdGroup
, CGID_Explorer
) &&
3253 (nCmdexecopt
== 4) && pvaOut
)
3256 if (IsEqualIID(*pguidCmdGroup
, CGID_ShellDocView
) &&
3261 return OLECMDERR_E_UNKNOWNGROUP
;
3264 /**********************************************************
3265 * ISVDropTarget implementation
3268 /******************************************************************************
3269 * drag_notify_subitem [Internal]
3271 * Figure out the shellfolder object, which is currently under the mouse cursor
3272 * and notify it via the IDropTarget interface.
3275 #define SCROLLAREAWIDTH 20
3277 HRESULT
CDefView::drag_notify_subitem(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
3283 /* The key state on drop doesn't have MK_LBUTTON or MK_RBUTTON because it
3284 reflects the key state after the user released the button, so we need
3285 to remember the last key state when the button was pressed */
3286 m_grfKeyState
= grfKeyState
;
3288 /* Map from global to client coordinates and query the index of the listview-item, which is
3289 * currently under the mouse cursor. */
3290 LVHITTESTINFO htinfo
= {{pt
.x
, pt
.y
}, LVHT_ONITEM
};
3291 ScreenToClient(&htinfo
.pt
);
3292 lResult
= m_ListView
.HitTest(&htinfo
);
3294 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
3295 ::GetClientRect(m_ListView
, &clientRect
);
3296 if (htinfo
.pt
.x
== m_ptLastMousePos
.x
&& htinfo
.pt
.y
== m_ptLastMousePos
.y
&&
3297 (htinfo
.pt
.x
< SCROLLAREAWIDTH
|| htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
||
3298 htinfo
.pt
.y
< SCROLLAREAWIDTH
|| htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
))
3300 m_cScrollDelay
= (m_cScrollDelay
+ 1) % 5; /* DragOver is called every 50 ms */
3301 if (m_cScrollDelay
== 0)
3303 /* Mouse did hover another 250 ms over the scroll-area */
3304 if (htinfo
.pt
.x
< SCROLLAREAWIDTH
)
3305 m_ListView
.SendMessageW(WM_HSCROLL
, SB_LINEUP
, 0);
3307 if (htinfo
.pt
.x
> clientRect
.right
- SCROLLAREAWIDTH
)
3308 m_ListView
.SendMessageW(WM_HSCROLL
, SB_LINEDOWN
, 0);
3310 if (htinfo
.pt
.y
< SCROLLAREAWIDTH
)
3311 m_ListView
.SendMessageW(WM_VSCROLL
, SB_LINEUP
, 0);
3313 if (htinfo
.pt
.y
> clientRect
.bottom
- SCROLLAREAWIDTH
)
3314 m_ListView
.SendMessageW(WM_VSCROLL
, SB_LINEDOWN
, 0);
3319 m_cScrollDelay
= 0; /* Reset, if the cursor is not over the listview's scroll-area */
3322 m_ptLastMousePos
= htinfo
.pt
;
3323 ::ClientToListView(m_ListView
, &m_ptLastMousePos
);
3325 /* We need to check if we drag the selection over itself */
3326 if (lResult
!= -1 && m_pSourceDataObject
.p
!= NULL
)
3328 PCUITEMID_CHILD pidl
= _PidlByItem(lResult
);
3330 for (UINT i
= 0; i
< m_cidl
; i
++)
3332 if (pidl
== m_apidl
[i
])
3334 /* The item that is being draged is hovering itself. */
3341 /* If we are still over the previous sub-item, notify it via DragOver and return. */
3342 if (m_pCurDropTarget
&& lResult
== m_iDragOverItem
)
3343 return m_pCurDropTarget
->DragOver(grfKeyState
, pt
, pdwEffect
);
3345 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
3346 if (m_pCurDropTarget
)
3348 PCUITEMID_CHILD pidl
= _PidlByItem(m_iDragOverItem
);
3350 SelectItem(pidl
, 0);
3352 m_pCurDropTarget
->DragLeave();
3353 m_pCurDropTarget
.Release();
3356 m_iDragOverItem
= lResult
;
3360 /* We are not above one of the listview's subitems. Bind to the parent folder's
3361 * DropTarget interface. */
3362 hr
= m_pSFParent
->CreateViewObject(NULL
, IID_PPV_ARG(IDropTarget
,&m_pCurDropTarget
));
3366 /* Query the relative PIDL of the shellfolder object represented by the currently
3367 * dragged over listview-item ... */
3368 PCUITEMID_CHILD pidl
= _PidlByItem(lResult
);
3370 /* ... and bind m_pCurDropTarget to the IDropTarget interface of an UIObject of this object */
3371 hr
= m_pSFParent
->GetUIObjectOf(m_ListView
, 1, &pidl
, IID_NULL_PPV_ARG(IDropTarget
, &m_pCurDropTarget
));
3374 IUnknown_SetSite(m_pCurDropTarget
, (IShellView
*)this);
3376 /* If anything failed, m_pCurDropTarget should be NULL now, which ought to be a save state. */
3379 *pdwEffect
= DROPEFFECT_NONE
;
3383 if (m_iDragOverItem
!= -1)
3385 SelectItem(m_iDragOverItem
, SVSI_SELECT
);
3388 /* Notify the item just entered via DragEnter. */
3389 return m_pCurDropTarget
->DragEnter(m_pCurDataObject
, grfKeyState
, pt
, pdwEffect
);
3392 HRESULT WINAPI
CDefView::DragEnter(IDataObject
*pDataObject
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
3394 if (*pdwEffect
== DROPEFFECT_NONE
)
3397 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
3398 m_pCurDataObject
= pDataObject
;
3400 HRESULT hr
= drag_notify_subitem(grfKeyState
, pt
, pdwEffect
);
3403 POINT ptClient
= {pt
.x
, pt
.y
};
3404 ScreenToClient(&ptClient
);
3405 ImageList_DragEnter(m_hWnd
, ptClient
.x
, ptClient
.y
);
3411 HRESULT WINAPI
CDefView::DragOver(DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
3413 POINT ptClient
= {pt
.x
, pt
.y
};
3414 ScreenToClient(&ptClient
);
3415 ImageList_DragMove(ptClient
.x
, ptClient
.y
);
3416 return drag_notify_subitem(grfKeyState
, pt
, pdwEffect
);
3419 HRESULT WINAPI
CDefView::DragLeave()
3421 ImageList_DragLeave(m_hWnd
);
3423 if (m_pCurDropTarget
)
3425 m_pCurDropTarget
->DragLeave();
3426 m_pCurDropTarget
.Release();
3429 if (m_pCurDataObject
!= NULL
)
3431 m_pCurDataObject
.Release();
3434 m_iDragOverItem
= 0;
3439 INT
CDefView::_FindInsertableIndexFromPoint(POINT pt
)
3442 INT i
, nCount
= m_ListView
.GetItemCount();
3445 BOOL bSmall
= ((m_ListView
.GetStyle() & LVS_TYPEMASK
) != LVS_ICON
);
3447 /* FIXME: LVM_GETORIGIN is broken. See CORE-17266 */
3448 pt
.x
+= m_ListView
.GetScrollPos(SB_HORZ
);
3449 pt
.y
+= m_ListView
.GetScrollPos(SB_VERT
);
3451 if (m_ListView
.GetStyle() & LVS_ALIGNLEFT
)
3454 for (i
= 0; i
< nCount
; ++i
)
3456 dwSpacing
= ListView_GetItemSpacing(m_ListView
, bSmall
);
3457 dx
= LOWORD(dwSpacing
);
3458 dy
= HIWORD(dwSpacing
);
3459 ListView_GetItemRect(m_ListView
, i
, &rcBound
, LVIR_SELECTBOUNDS
);
3460 rcBound
.right
= rcBound
.left
+ dx
;
3461 rcBound
.bottom
= rcBound
.top
+ dy
;
3462 if (pt
.x
< rcBound
.right
&& pt
.y
< (rcBound
.top
+ rcBound
.bottom
) / 2)
3467 for (i
= nCount
- 1; i
>= 0; --i
)
3469 ListView_GetItemRect(m_ListView
, i
, &rcBound
, LVIR_SELECTBOUNDS
);
3470 if (rcBound
.left
< pt
.x
&& rcBound
.top
< pt
.y
)
3479 for (i
= 0; i
< nCount
; ++i
)
3481 dwSpacing
= ListView_GetItemSpacing(m_ListView
, bSmall
);
3482 dx
= LOWORD(dwSpacing
);
3483 dy
= HIWORD(dwSpacing
);
3484 ListView_GetItemRect(m_ListView
, i
, &rcBound
, LVIR_SELECTBOUNDS
);
3485 rcBound
.right
= rcBound
.left
+ dx
;
3486 rcBound
.bottom
= rcBound
.top
+ dy
;
3487 if (pt
.y
< rcBound
.bottom
&& pt
.x
< rcBound
.left
)
3491 if (pt
.y
< rcBound
.bottom
&& pt
.x
< rcBound
.right
)
3496 for (i
= nCount
- 1; i
>= 0; --i
)
3498 ListView_GetItemRect(m_ListView
, i
, &rcBound
, LVIR_SELECTBOUNDS
);
3499 if (rcBound
.left
< pt
.x
&& rcBound
.top
< pt
.y
)
3509 typedef CSimpleMap
<LPARAM
, INT
> CLParamIndexMap
;
3512 SelectionMoveCompareFunc(LPARAM lParam1
, LPARAM lParam2
, LPARAM lParamSort
)
3514 CLParamIndexMap
*pmap
= (CLParamIndexMap
*)lParamSort
;
3515 INT i1
= pmap
->Lookup(lParam1
), i2
= pmap
->Lookup(lParam2
);
3523 void CDefView::_MoveSelectionOnAutoArrange(POINT pt
)
3525 // get insertable index from position
3526 INT iPosition
= _FindInsertableIndexFromPoint(pt
);
3528 // create identity mapping of indexes
3529 CSimpleArray
<INT
> array
;
3530 INT nCount
= m_ListView
.GetItemCount();
3531 for (INT i
= 0; i
< nCount
; ++i
)
3536 // re-ordering mapping
3538 while ((iItem
= m_ListView
.GetNextItem(iItem
, LVNI_SELECTED
)) >= 0)
3540 INT iFrom
= iItem
, iTo
= iPosition
;
3543 if (iFrom
>= nCount
)
3548 // shift indexes by swapping (like a bucket relay)
3551 for (INT i
= iFrom
; i
< iTo
; ++i
)
3553 // swap array[i] and array[i + 1]
3555 array
[i
] = array
[i
+ 1];
3561 for (INT i
= iFrom
; i
> iTo
; --i
)
3563 // swap array[i] and array[i - 1]
3565 array
[i
] = array
[i
- 1];
3571 // create mapping (ListView's lParam to index) from array
3572 CLParamIndexMap map
;
3573 for (INT i
= 0; i
< nCount
; ++i
)
3575 LPARAM lParam
= m_ListView
.GetItemData(array
[i
]);
3580 m_ListView
.SortItems(SelectionMoveCompareFunc
, &map
);
3583 HRESULT WINAPI
CDefView::Drop(IDataObject
* pDataObject
, DWORD grfKeyState
, POINTL pt
, DWORD
*pdwEffect
)
3585 ImageList_DragLeave(m_hWnd
);
3586 ImageList_EndDrag();
3588 if ((IsDropOnSource(NULL
) == S_OK
) &&
3589 (*pdwEffect
& DROPEFFECT_MOVE
) &&
3590 (m_grfKeyState
& MK_LBUTTON
))
3592 if (m_pCurDropTarget
)
3594 m_pCurDropTarget
->DragLeave();
3595 m_pCurDropTarget
.Release();
3598 POINT ptDrop
= { pt
.x
, pt
.y
};
3599 ::ScreenToClient(m_ListView
, &ptDrop
);
3600 ::ClientToListView(m_ListView
, &ptDrop
);
3601 m_ptLastMousePos
= ptDrop
;
3603 m_ListView
.SetRedraw(FALSE
);
3604 if (m_ListView
.GetStyle() & LVS_AUTOARRANGE
)
3606 _MoveSelectionOnAutoArrange(m_ptLastMousePos
);
3612 while ((iItem
= m_ListView
.GetNextItem(iItem
, LVNI_SELECTED
)) >= 0)
3614 if (m_ListView
.GetItemPosition(iItem
, &ptItem
))
3616 ptItem
.x
+= m_ptLastMousePos
.x
- m_ptFirstMousePos
.x
;
3617 ptItem
.y
+= m_ptLastMousePos
.y
- m_ptFirstMousePos
.y
;
3618 m_ListView
.SetItemPosition(iItem
, &ptItem
);
3622 m_ListView
.SetRedraw(TRUE
);
3624 else if (m_pCurDropTarget
)
3626 m_pCurDropTarget
->Drop(pDataObject
, grfKeyState
, pt
, pdwEffect
);
3627 m_pCurDropTarget
.Release();
3630 m_pCurDataObject
.Release();
3631 m_iDragOverItem
= 0;
3635 /**********************************************************
3636 * ISVDropSource implementation
3639 HRESULT WINAPI
CDefView::QueryContinueDrag(BOOL fEscapePressed
, DWORD grfKeyState
)
3641 TRACE("(%p)\n", this);
3644 return DRAGDROP_S_CANCEL
;
3645 else if (!(grfKeyState
& MK_LBUTTON
) && !(grfKeyState
& MK_RBUTTON
))
3646 return DRAGDROP_S_DROP
;
3651 HRESULT WINAPI
CDefView::GiveFeedback(DWORD dwEffect
)
3653 TRACE("(%p)\n", this);
3655 return DRAGDROP_S_USEDEFAULTCURSORS
;
3658 /**********************************************************
3659 * ISVViewObject implementation
3662 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
)
3664 FIXME("Stub: this=%p\n", this);
3669 HRESULT WINAPI
CDefView::GetColorSet(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DVTARGETDEVICE
*ptd
, HDC hicTargetDevice
, LOGPALETTE
**ppColorSet
)
3671 FIXME("Stub: this=%p\n", this);
3676 HRESULT WINAPI
CDefView::Freeze(DWORD dwDrawAspect
, LONG lindex
, void *pvAspect
, DWORD
*pdwFreeze
)
3678 FIXME("Stub: this=%p\n", this);
3683 HRESULT WINAPI
CDefView::Unfreeze(DWORD dwFreeze
)
3685 FIXME("Stub: this=%p\n", this);
3690 HRESULT WINAPI
CDefView::SetAdvise(DWORD aspects
, DWORD advf
, IAdviseSink
*pAdvSink
)
3692 FIXME("partial stub: %p 0x%08x 0x%08x %p\n", this, aspects
, advf
, pAdvSink
);
3694 /* FIXME: we set the AdviseSink, but never use it to send any advice */
3695 m_pAdvSink
= pAdvSink
;
3696 m_dwAspects
= aspects
;
3702 HRESULT WINAPI
CDefView::GetAdvise(DWORD
*pAspects
, DWORD
*pAdvf
, IAdviseSink
**ppAdvSink
)
3704 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects
, pAdvf
, ppAdvSink
);
3708 *ppAdvSink
= m_pAdvSink
;
3709 m_pAdvSink
.p
->AddRef();
3713 *pAspects
= m_dwAspects
;
3721 HRESULT STDMETHODCALLTYPE
CDefView::QueryService(REFGUID guidService
, REFIID riid
, void **ppvObject
)
3723 if (IsEqualIID(guidService
, SID_IShellBrowser
))
3724 return m_pShellBrowser
->QueryInterface(riid
, ppvObject
);
3725 else if(IsEqualIID(guidService
, SID_IFolderView
))
3726 return QueryInterface(riid
, ppvObject
);
3728 return E_NOINTERFACE
;
3731 HRESULT
CDefView::_MergeToolbar()
3733 CComPtr
<IExplorerToolbar
> ptb
;
3736 hr
= IUnknown_QueryService(m_pShellBrowser
, IID_IExplorerToolbar
, IID_PPV_ARG(IExplorerToolbar
, &ptb
));
3740 m_Category
= CGID_DefViewFrame
;
3742 hr
= ptb
->SetCommandTarget(static_cast<IOleCommandTarget
*>(this), &m_Category
, 0);
3750 hr
= ptb
->AddButtons(&m_Category
, buttonsCount
, buttons
);
3758 HRESULT
CDefView::_DoFolderViewCB(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3760 HRESULT hr
= E_NOTIMPL
;
3762 if (m_pShellFolderViewCB
)
3764 hr
= m_pShellFolderViewCB
->MessageSFVCB(uMsg
, wParam
, lParam
);
3770 HRESULT
CDefView_CreateInstance(IShellFolder
*pFolder
, REFIID riid
, LPVOID
* ppvOut
)
3772 return ShellObjectCreatorInit
<CDefView
>(pFolder
, riid
, ppvOut
);
3775 HRESULT WINAPI
SHCreateShellFolderViewEx(
3776 LPCSFV psvcbi
, /* [in] shelltemplate struct */
3777 IShellView
**ppsv
) /* [out] IShellView pointer */
3779 CComPtr
<IShellView
> psv
;
3782 TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n",
3783 psvcbi
->pshf
, psvcbi
->pidl
, psvcbi
->pfnCallback
,
3784 psvcbi
->fvm
, psvcbi
->psvOuter
);
3787 hRes
= CDefView_CreateInstance(psvcbi
->pshf
, IID_PPV_ARG(IShellView
, &psv
));
3788 if (FAILED_UNEXPECTEDLY(hRes
))
3791 *ppsv
= psv
.Detach();
3795 HRESULT WINAPI
SHCreateShellFolderView(const SFV_CREATE
*pcsfv
,
3798 CComPtr
<IShellView
> psv
;
3802 return E_INVALIDARG
;
3806 if (!pcsfv
|| pcsfv
->cbSize
!= sizeof(*pcsfv
))
3807 return E_INVALIDARG
;
3809 TRACE("sf=%p outer=%p callback=%p\n",
3810 pcsfv
->pshf
, pcsfv
->psvOuter
, pcsfv
->psfvcb
);
3812 hRes
= CDefView_CreateInstance(pcsfv
->pshf
, IID_PPV_ARG(IShellView
, &psv
));
3818 CComPtr
<IShellFolderView
> sfv
;
3819 if (SUCCEEDED(psv
->QueryInterface(IID_PPV_ARG(IShellFolderView
, &sfv
))))
3821 sfv
->SetCallback(pcsfv
->psfvcb
, NULL
);
3825 *ppsv
= psv
.Detach();