[shell32.dll]
[reactos.git] / dll / win32 / shell32 / shlview.cpp
1 /*
2 * ShellView
3 *
4 * Copyright 1998,1999 <juergen.schmied@debitel.net>
5 *
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.
8 *
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.
13 *
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.
18 *
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
22 *
23 * FIXME: The order by part of the background context menu should be
24 * built according to the columns shown.
25 *
26 * FIXME: CheckToolbar: handle the "new folder" and "folder up" button
27 *
28 * FIXME: ShellView_FillList: consider sort orders
29 */
30
31 /*
32 TODO:
33 1. Load/Save the view state from/into the stream provided by the ShellBrowser.
34 2. Let the shell folder sort items.
35 3. Code to merge menus in the shellbrowser is incorrect.
36 4. Move the background context menu creation into shell view. It should store the
37 shell view HWND to send commands.
38 5. Send init, measure, and draw messages to context menu during tracking.
39 6. Shell view should do SetCommandTarget on internet toolbar.
40 7. When editing starts on item, set edit text to for editing value.
41 8. When shell view is called back for item info, let listview save the value.
42 9. Shell view should update status bar.
43 10. Fix shell view to handle view mode popup exec.
44 11. The background context menu should have a pidl just like foreground menus. This
45 causes crashes when dynamic handlers try to use the NULL pidl.
46 12. The SHELLDLL_DefView should not be filled with blue unconditionally. This causes
47 annoying flashing of blue even on XP, and is not correct.
48 13. Reorder of columns doesn't work - might be bug in comctl32
49 */
50
51 #include <precomp.h>
52
53 WINE_DEFAULT_DEBUG_CHANNEL(shell);
54
55 #undef SV_CLASS_NAME
56
57 static const WCHAR SV_CLASS_NAME[] = {'S','H','E','L','L','D','L','L','_','D','e','f','V','i','e','w',0};
58
59 typedef struct
60 { BOOL bIsAscending;
61 INT nHeaderID;
62 INT nLastHeaderID;
63 }LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;
64
65 #define SHV_CHANGE_NOTIFY WM_USER + 0x1111
66
67 class CDefView :
68 public CWindowImpl<CDefView, CWindow, CControlWinTraits>,
69 public CComObjectRootEx<CComMultiThreadModelNoCS>,
70 public IShellView,
71 public IFolderView,
72 public IOleCommandTarget,
73 public IDropTarget,
74 public IDropSource,
75 public IViewObject,
76 public IServiceProvider
77 {
78 private:
79 CComPtr<IShellFolder> pSFParent;
80 CComPtr<IShellFolder2> pSF2Parent;
81 CComPtr<IShellBrowser> pShellBrowser;
82 CComPtr<ICommDlgBrowser> pCommDlgBrowser;
83 HWND hWndList; /* ListView control */
84 HWND hWndParent;
85 FOLDERSETTINGS FolderSettings;
86 HMENU hMenu;
87 UINT uState;
88 UINT cidl;
89 LPITEMIDLIST *apidl;
90 LISTVIEW_SORT_INFO ListViewSortInfo;
91 ULONG hNotify; /* change notification handle */
92 HANDLE hAccel;
93 DWORD dwAspects;
94 DWORD dwAdvf;
95 CComPtr<IAdviseSink> pAdvSink;
96 // for drag and drop
97 CComPtr<IDropTarget> pCurDropTarget; /* The sub-item, which is currently dragged over */
98 CComPtr<IDataObject> pCurDataObject; /* The dragged data-object */
99 LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */
100 UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
101 POINT ptLastMousePos; /* Mouse position at last DragOver call */
102 //
103 CComPtr<IContextMenu2> pCM;
104 public:
105 CDefView();
106 ~CDefView();
107 HRESULT WINAPI Initialize(IShellFolder *shellFolder);
108 HRESULT IncludeObject(LPCITEMIDLIST pidl);
109 HRESULT OnDefaultCommand();
110 HRESULT OnStateChange(UINT uFlags);
111 void CheckToolbar();
112 void SetStyle(DWORD dwAdd, DWORD dwRemove);
113 BOOL CreateList();
114 BOOL InitList();
115 static INT CALLBACK CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData);
116 static INT CALLBACK ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData);
117 int LV_FindItemByPidl(LPCITEMIDLIST pidl);
118 BOOLEAN LV_AddItem(LPCITEMIDLIST pidl);
119 BOOLEAN LV_DeleteItem(LPCITEMIDLIST pidl);
120 BOOLEAN LV_RenameItem(LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew);
121 static INT CALLBACK fill_list(LPVOID ptr, LPVOID arg);
122 HRESULT FillList();
123 HMENU BuildFileMenu();
124 void MergeFileMenu(HMENU hSubMenu);
125 void MergeViewMenu(HMENU hSubMenu);
126 UINT GetSelections();
127 HRESULT OpenSelectedItems();
128 void OnDeactivate();
129 void DoActivate(UINT uState);
130 HRESULT drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
131
132 // *** IOleWindow methods ***
133 virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd);
134 virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
135
136 // *** IShellView methods ***
137 virtual HRESULT STDMETHODCALLTYPE TranslateAccelerator(MSG *pmsg);
138 virtual HRESULT STDMETHODCALLTYPE EnableModeless(BOOL fEnable);
139 virtual HRESULT STDMETHODCALLTYPE UIActivate(UINT uState);
140 virtual HRESULT STDMETHODCALLTYPE Refresh();
141 virtual HRESULT STDMETHODCALLTYPE CreateViewWindow(IShellView *psvPrevious, LPCFOLDERSETTINGS pfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd);
142 virtual HRESULT STDMETHODCALLTYPE DestroyViewWindow();
143 virtual HRESULT STDMETHODCALLTYPE GetCurrentInfo(LPFOLDERSETTINGS pfs);
144 virtual HRESULT STDMETHODCALLTYPE AddPropertySheetPages(DWORD dwReserved, LPFNSVADDPROPSHEETPAGE pfn, LPARAM lparam);
145 virtual HRESULT STDMETHODCALLTYPE SaveViewState();
146 virtual HRESULT STDMETHODCALLTYPE SelectItem(LPCITEMIDLIST pidlItem, SVSIF uFlags);
147 virtual HRESULT STDMETHODCALLTYPE GetItemObject(UINT uItem, REFIID riid, void **ppv);
148
149 // *** IFolderView methods ***
150 virtual HRESULT STDMETHODCALLTYPE GetCurrentViewMode(UINT *pViewMode);
151 virtual HRESULT STDMETHODCALLTYPE SetCurrentViewMode(UINT ViewMode);
152 virtual HRESULT STDMETHODCALLTYPE GetFolder(REFIID riid, void **ppv);
153 virtual HRESULT STDMETHODCALLTYPE Item(int iItemIndex, LPITEMIDLIST *ppidl);
154 virtual HRESULT STDMETHODCALLTYPE ItemCount(UINT uFlags, int *pcItems);
155 virtual HRESULT STDMETHODCALLTYPE Items(UINT uFlags, REFIID riid, void **ppv);
156 virtual HRESULT STDMETHODCALLTYPE GetSelectionMarkedItem(int *piItem);
157 virtual HRESULT STDMETHODCALLTYPE GetFocusedItem(int *piItem);
158 virtual HRESULT STDMETHODCALLTYPE GetItemPosition(LPCITEMIDLIST pidl, POINT *ppt);
159 virtual HRESULT STDMETHODCALLTYPE GetSpacing(POINT *ppt);
160 virtual HRESULT STDMETHODCALLTYPE GetDefaultSpacing(POINT *ppt);
161 virtual HRESULT STDMETHODCALLTYPE GetAutoArrange();
162 virtual HRESULT STDMETHODCALLTYPE SelectItem(int iItem, DWORD dwFlags);
163 virtual HRESULT STDMETHODCALLTYPE SelectAndPositionItems(UINT cidl, LPCITEMIDLIST *apidl, POINT *apt, DWORD dwFlags);
164
165 // *** IOleCommandTarget methods ***
166 virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[ ], OLECMDTEXT *pCmdText);
167 virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
168
169 // *** IDropTarget methods ***
170 virtual HRESULT STDMETHODCALLTYPE DragEnter(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
171 virtual HRESULT STDMETHODCALLTYPE DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
172 virtual HRESULT STDMETHODCALLTYPE DragLeave();
173 virtual HRESULT STDMETHODCALLTYPE Drop(IDataObject *pDataObj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect);
174
175 // *** IDropSource methods ***
176 virtual HRESULT STDMETHODCALLTYPE QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState);
177 virtual HRESULT STDMETHODCALLTYPE GiveFeedback(DWORD dwEffect);
178
179 // *** IViewObject methods ***
180 virtual HRESULT STDMETHODCALLTYPE Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd,
181 HDC hdcTargetDev, HDC hdcDraw, LPCRECTL lprcBounds, LPCRECTL lprcWBounds,
182 BOOL ( STDMETHODCALLTYPE *pfnContinue )(ULONG_PTR dwContinue), ULONG_PTR dwContinue);
183 virtual HRESULT STDMETHODCALLTYPE GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect,
184 DVTARGETDEVICE *ptd, HDC hicTargetDev, LOGPALETTE **ppColorSet);
185 virtual HRESULT STDMETHODCALLTYPE Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze);
186 virtual HRESULT STDMETHODCALLTYPE Unfreeze(DWORD dwFreeze);
187 virtual HRESULT STDMETHODCALLTYPE SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink);
188 virtual HRESULT STDMETHODCALLTYPE GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink);
189
190 // *** IServiceProvider methods ***
191 virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
192
193 // message handlers
194 LRESULT OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
195 LRESULT OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
196 LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
197 LRESULT OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
198 LRESULT OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
199 LRESULT OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
200 LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
201 LRESULT OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
202 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
203 LRESULT OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
204 LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
205 LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
206 LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
207 LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
208 LRESULT OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
209 LRESULT OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
210
211 static ATL::CWndClassInfo& GetWndClassInfo()
212 {
213 static ATL::CWndClassInfo wc =
214 {
215 { sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, StartWindowProc,
216 0, 0, NULL, NULL,
217 LoadCursor(NULL, IDC_ARROW), (HBRUSH)(COLOR_BACKGROUND + 1), NULL, SV_CLASS_NAME, NULL },
218 NULL, NULL, IDC_ARROW, TRUE, 0, _T("")
219 };
220 return wc;
221 }
222
223 virtual WNDPROC GetWindowProc()
224 {
225 return WindowProc;
226 }
227
228 static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
229 {
230 CDefView *pThis;
231 LRESULT result;
232
233 // must hold a reference during message handling
234 pThis = reinterpret_cast<CDefView *>(hWnd);
235 pThis->AddRef();
236 result = CWindowImpl<CDefView, CWindow, CControlWinTraits>::WindowProc(hWnd, uMsg, wParam, lParam);
237 pThis->Release();
238 return result;
239 }
240
241 BEGIN_MSG_MAP(CDefView)
242 MESSAGE_HANDLER(WM_SIZE, OnSize)
243 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
244 MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
245 MESSAGE_HANDLER(WM_CREATE, OnCreate)
246 MESSAGE_HANDLER(WM_ACTIVATE, OnActivate)
247 MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
248 MESSAGE_HANDLER(WM_COMMAND, OnCommand)
249 MESSAGE_HANDLER(SHV_CHANGE_NOTIFY, OnChangeNotify)
250 MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
251 MESSAGE_HANDLER(WM_DRAWITEM, OnCustomItem)
252 MESSAGE_HANDLER(WM_MEASUREITEM, OnCustomItem)
253 MESSAGE_HANDLER(WM_SHOWWINDOW, OnShowWindow)
254 MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode)
255 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
256 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
257 MESSAGE_HANDLER(WM_SYSCOLORCHANGE, OnSysColorChange)
258 MESSAGE_HANDLER(CWM_GETISHELLBROWSER, OnGetShellBrowser)
259 END_MSG_MAP()
260
261 BEGIN_COM_MAP(CDefView)
262 COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
263 COM_INTERFACE_ENTRY_IID(IID_IShellView, IShellView)
264 COM_INTERFACE_ENTRY_IID(IID_IFolderView, IFolderView)
265 COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
266 COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget)
267 COM_INTERFACE_ENTRY_IID(IID_IDropSource, IDropSource)
268 COM_INTERFACE_ENTRY_IID(IID_IViewObject, IViewObject)
269 COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
270 END_COM_MAP()
271 };
272
273 /* ListView Header ID's */
274 #define LISTVIEW_COLUMN_NAME 0
275 #define LISTVIEW_COLUMN_SIZE 1
276 #define LISTVIEW_COLUMN_TYPE 2
277 #define LISTVIEW_COLUMN_TIME 3
278 #define LISTVIEW_COLUMN_ATTRIB 4
279
280 /*menu items */
281 #define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
282 #define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
283 #define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
284
285 #define ID_LISTVIEW 1
286
287 /*windowsx.h */
288 #define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
289 #define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
290 #define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
291
292 /*
293 Items merged into the toolbar and the filemenu
294 */
295 typedef struct
296 { int idCommand;
297 int iImage;
298 int idButtonString;
299 int idMenuString;
300 BYTE bState;
301 BYTE bStyle;
302 } MYTOOLINFO, *LPMYTOOLINFO;
303
304 static const MYTOOLINFO Tools[] =
305 {
306 { FCIDM_SHVIEW_BIGICON, 0, 0, IDS_VIEW_LARGE, TBSTATE_ENABLED, BTNS_BUTTON },
307 { FCIDM_SHVIEW_SMALLICON, 0, 0, IDS_VIEW_SMALL, TBSTATE_ENABLED, BTNS_BUTTON },
308 { FCIDM_SHVIEW_LISTVIEW, 0, 0, IDS_VIEW_LIST, TBSTATE_ENABLED, BTNS_BUTTON },
309 { FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON },
310 { -1, 0, 0, 0, 0, 0}
311 };
312
313 typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
314
315 CDefView::CDefView()
316 {
317 hWndList = NULL;
318 hWndParent = NULL;
319 FolderSettings.fFlags = 0;
320 FolderSettings.ViewMode = 0;
321 hMenu = NULL;
322 uState = 0;
323 cidl = 0;
324 apidl = NULL;
325 ListViewSortInfo.bIsAscending = FALSE;
326 ListViewSortInfo.nHeaderID = 0;
327 ListViewSortInfo.nLastHeaderID = 0;
328 hNotify = 0;
329 hAccel = NULL;
330 dwAspects = 0;
331 dwAdvf = 0;
332 iDragOverItem = 0;
333 cScrollDelay = 0;
334 ptLastMousePos.x = 0;
335 ptLastMousePos.y = 0;
336 }
337
338 CDefView::~CDefView()
339 {
340 TRACE(" destroying IShellView(%p)\n", this);
341
342 SHFree(apidl);
343 }
344
345 HRESULT WINAPI CDefView::Initialize(IShellFolder *shellFolder)
346 {
347 pSFParent = shellFolder;
348 shellFolder->QueryInterface(IID_IShellFolder2, (LPVOID *)&pSF2Parent);
349
350 return S_OK;
351 }
352
353 /**********************************************************
354 *
355 * ##### helperfunctions for communication with ICommDlgBrowser #####
356 */
357 HRESULT CDefView::IncludeObject(LPCITEMIDLIST pidl)
358 {
359 HRESULT ret = S_OK;
360
361 if (pCommDlgBrowser.p != NULL)
362 {
363 TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
364 ret = pCommDlgBrowser->IncludeObject((IShellView *)this, pidl);
365 TRACE("--0x%08x\n", ret);
366 }
367
368 return ret;
369 }
370
371 HRESULT CDefView::OnDefaultCommand()
372 {
373 HRESULT ret = S_FALSE;
374
375 if (pCommDlgBrowser.p != NULL)
376 {
377 TRACE("ICommDlgBrowser::OnDefaultCommand\n");
378 ret = pCommDlgBrowser->OnDefaultCommand((IShellView *)this);
379 TRACE("-- returns %08x\n", ret);
380 }
381
382 return ret;
383 }
384
385 HRESULT CDefView::OnStateChange(UINT uFlags)
386 {
387 HRESULT ret = S_FALSE;
388
389 if (pCommDlgBrowser.p != NULL)
390 {
391 TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
392 ret = pCommDlgBrowser->OnStateChange((IShellView *)this, uFlags);
393 TRACE("--\n");
394 }
395
396 return ret;
397 }
398 /**********************************************************
399 * set the toolbar of the filedialog buttons
400 *
401 * - activates the buttons from the shellbrowser according to
402 * the view state
403 */
404 void CDefView::CheckToolbar()
405 {
406 LRESULT result;
407
408 TRACE("\n");
409
410 if (pCommDlgBrowser != NULL)
411 {
412 pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_CHECKBUTTON,
413 FCIDM_TB_SMALLICON, (FolderSettings.ViewMode==FVM_LIST)? TRUE : FALSE, &result);
414 pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_CHECKBUTTON,
415 FCIDM_TB_REPORTVIEW, (FolderSettings.ViewMode==FVM_DETAILS)? TRUE : FALSE, &result);
416 pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON,
417 FCIDM_TB_SMALLICON, TRUE, &result);
418 pShellBrowser->SendControlMsg(FCW_TOOLBAR, TB_ENABLEBUTTON,
419 FCIDM_TB_REPORTVIEW, TRUE, &result);
420 }
421 }
422
423 /**********************************************************
424 *
425 * ##### helperfunctions for initializing the view #####
426 */
427 /**********************************************************
428 * change the style of the listview control
429 */
430 void CDefView::SetStyle(DWORD dwAdd, DWORD dwRemove)
431 {
432 DWORD tmpstyle;
433
434 TRACE("(%p)\n", this);
435
436 tmpstyle = ::GetWindowLongPtrW(hWndList, GWL_STYLE);
437 ::SetWindowLongPtrW(hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
438 }
439
440 /**********************************************************
441 * ShellView_CreateList()
442 *
443 * - creates the list view window
444 */
445 BOOL CDefView::CreateList()
446 { DWORD dwStyle, dwExStyle;
447
448 TRACE("%p\n",this);
449
450 dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
451 LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_AUTOARRANGE;
452 dwExStyle = WS_EX_CLIENTEDGE;
453
454 if (FolderSettings.fFlags & FWF_DESKTOP)
455 dwStyle |= LVS_ALIGNLEFT;
456 else
457 dwStyle |= LVS_ALIGNTOP;
458
459 switch (FolderSettings.ViewMode)
460 {
461 case FVM_ICON:
462 dwStyle |= LVS_ICON;
463 break;
464
465 case FVM_DETAILS:
466 dwStyle |= LVS_REPORT;
467 break;
468
469 case FVM_SMALLICON:
470 dwStyle |= LVS_SMALLICON;
471 break;
472
473 case FVM_LIST:
474 dwStyle |= LVS_LIST;
475 break;
476
477 default:
478 dwStyle |= LVS_LIST;
479 break;
480 }
481
482 if (FolderSettings.fFlags & FWF_AUTOARRANGE)
483 dwStyle |= LVS_AUTOARRANGE;
484
485 if (FolderSettings.fFlags & FWF_DESKTOP)
486 FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
487
488 if (FolderSettings.fFlags & FWF_SINGLESEL)
489 dwStyle |= LVS_SINGLESEL;
490
491 if (FolderSettings.fFlags & FWF_NOCLIENTEDGE)
492 dwExStyle &= ~WS_EX_CLIENTEDGE;
493
494 hWndList=CreateWindowExW( dwExStyle,
495 WC_LISTVIEWW,
496 NULL,
497 dwStyle,
498 0,0,0,0,
499 m_hWnd,
500 (HMENU)ID_LISTVIEW,
501 shell32_hInstance,
502 NULL);
503
504 if (!hWndList)
505 return FALSE;
506
507 ListViewSortInfo.bIsAscending = TRUE;
508 ListViewSortInfo.nHeaderID = -1;
509 ListViewSortInfo.nLastHeaderID = -1;
510
511 if (FolderSettings.fFlags & FWF_DESKTOP)
512 {
513 /*
514 * FIXME: look at the registry value
515 * HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
516 * and activate drop shadows if necessary
517 */
518 if (1)
519 {
520 SendMessageW(hWndList, LVM_SETTEXTBKCOLOR, 0, CLR_NONE);
521 SendMessageW(hWndList, LVM_SETBKCOLOR, 0, CLR_NONE);
522 }
523 else
524 {
525 SendMessageW(hWndList, LVM_SETTEXTBKCOLOR, 0, GetSysColor(COLOR_DESKTOP));
526 SendMessageW(hWndList, LVM_SETBKCOLOR, 0, GetSysColor(COLOR_DESKTOP));
527 }
528
529 SendMessageW(hWndList, LVM_SETTEXTCOLOR, 0, RGB(255,255,255));
530 }
531
532 /* UpdateShellSettings(); */
533 return TRUE;
534 }
535
536 /**********************************************************
537 * ShellView_InitList()
538 *
539 * - adds all needed columns to the shellview
540 */
541 BOOL CDefView::InitList()
542 {
543 LVCOLUMNW lvColumn;
544 SHELLDETAILS sd;
545 WCHAR szTemp[50];
546
547 TRACE("%p\n",this);
548
549 SendMessageW(hWndList, LVM_DELETEALLITEMS, 0, 0);
550
551 lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
552 lvColumn.pszText = szTemp;
553
554 if (pSF2Parent)
555 {
556 for (int i=0; 1; i++)
557 {
558 if (FAILED(pSF2Parent->GetDetailsOf(NULL, i, &sd)))
559 break;
560
561 lvColumn.fmt = sd.fmt;
562 lvColumn.cx = sd.cxChar*8; /* chars->pixel */
563 StrRetToStrNW( szTemp, 50, &sd.str, NULL);
564 SendMessageW(hWndList, LVM_INSERTCOLUMNW, i, (LPARAM) &lvColumn);
565 }
566 }
567 else
568 {
569 FIXME("no SF2\n");
570 }
571
572 SendMessageW(hWndList, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ShellSmallIconList);
573 SendMessageW(hWndList, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)ShellBigIconList);
574
575 return TRUE;
576 }
577
578 /**********************************************************
579 * ShellView_CompareItems()
580 *
581 * NOTES
582 * internal, CALLBACK for DSA_Sort
583 */
584 INT CALLBACK CDefView::CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
585 {
586 int ret;
587 TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
588
589 if (!lpData)
590 return 0;
591
592 ret = (SHORT)SCODE_CODE(((IShellFolder *)lpData)->CompareIDs(0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2));
593 TRACE("ret=%i\n",ret);
594
595 return ret;
596 }
597
598 /*************************************************************************
599 * ShellView_ListViewCompareItems
600 *
601 * Compare Function for the Listview (FileOpen Dialog)
602 *
603 * PARAMS
604 * lParam1 [I] the first ItemIdList to compare with
605 * lParam2 [I] the second ItemIdList to compare with
606 * lpData [I] The column ID for the header Ctrl to process
607 *
608 * RETURNS
609 * A negative value if the first item should precede the second,
610 * a positive value if the first item should follow the second,
611 * or zero if the two items are equivalent
612 *
613 * NOTES
614 * FIXME: function does what ShellView_CompareItems is supposed to do.
615 * unify it and figure out how to use the undocumented first parameter
616 * of IShellFolder_CompareIDs to do the job this function does and
617 * move this code to IShellFolder.
618 * make LISTVIEW_SORT_INFO obsolete
619 * the way this function works is only usable if we had only
620 * filesystemfolders (25/10/99 jsch)
621 */
622 INT CALLBACK CDefView::ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
623 {
624 INT nDiff=0;
625 FILETIME fd1, fd2;
626 char strName1[MAX_PATH], strName2[MAX_PATH];
627 BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
628 LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1;
629 LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2;
630 LISTVIEW_SORT_INFO *pSortInfo = (LPLISTVIEW_SORT_INFO) lpData;
631
632
633 bIsFolder1 = _ILIsFolder(pItemIdList1);
634 bIsFolder2 = _ILIsFolder(pItemIdList2);
635 bIsBothFolder = bIsFolder1 && bIsFolder2;
636
637 /* When sorting between a File and a Folder, the Folder gets sorted first */
638 if ( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
639 {
640 nDiff = bIsFolder1 ? -1 : 1;
641 }
642 else
643 {
644 /* Sort by Time: Folders or Files can be sorted */
645
646 if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_TIME)
647 {
648 _ILGetFileDateTime(pItemIdList1, &fd1);
649 _ILGetFileDateTime(pItemIdList2, &fd2);
650 nDiff = CompareFileTime(&fd2, &fd1);
651 }
652 /* Sort by Attribute: Folder or Files can be sorted */
653 else if(pSortInfo->nHeaderID == LISTVIEW_COLUMN_ATTRIB)
654 {
655 _ILGetFileAttributes(pItemIdList1, strName1, MAX_PATH);
656 _ILGetFileAttributes(pItemIdList2, strName2, MAX_PATH);
657 nDiff = lstrcmpiA(strName1, strName2);
658 }
659 /* Sort by FileName: Folder or Files can be sorted */
660 else if (pSortInfo->nHeaderID == LISTVIEW_COLUMN_NAME || bIsBothFolder)
661 {
662 /* Sort by Text */
663 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
664 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
665 nDiff = lstrcmpiA(strName1, strName2);
666 }
667 /* Sort by File Size, Only valid for Files */
668 else if (pSortInfo->nHeaderID == LISTVIEW_COLUMN_SIZE)
669 {
670 nDiff = (INT)(_ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0));
671 }
672 /* Sort by File Type, Only valid for Files */
673 else if (pSortInfo->nHeaderID == LISTVIEW_COLUMN_TYPE)
674 {
675 /* Sort by Type */
676 _ILGetFileType(pItemIdList1, strName1, MAX_PATH);
677 _ILGetFileType(pItemIdList2, strName2, MAX_PATH);
678 nDiff = lstrcmpiA(strName1, strName2);
679 }
680 }
681 /* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
682
683 if (nDiff == 0)
684 {
685 _ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
686 _ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
687 nDiff = lstrcmpiA(strName1, strName2);
688 }
689
690 if (!pSortInfo->bIsAscending)
691 {
692 nDiff = -nDiff;
693 }
694
695 return nDiff;
696 }
697
698 /**********************************************************
699 * LV_FindItemByPidl()
700 */
701 int CDefView::LV_FindItemByPidl(LPCITEMIDLIST pidl)
702 {
703 LVITEMW lvItem;
704 lvItem.iSubItem = 0;
705 lvItem.mask = LVIF_PARAM;
706
707 for (lvItem.iItem = 0;
708 SendMessageW(hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
709 lvItem.iItem++)
710 {
711 LPITEMIDLIST currentpidl = (LPITEMIDLIST) lvItem.lParam;
712 HRESULT hr = pSFParent->CompareIDs(0, pidl, currentpidl);
713
714 if (SUCCEEDED(hr) && !HRESULT_CODE(hr))
715 {
716 return lvItem.iItem;
717 }
718 }
719 return -1;
720 }
721
722 /**********************************************************
723 * LV_AddItem()
724 */
725 BOOLEAN CDefView::LV_AddItem(LPCITEMIDLIST pidl)
726 {
727 LVITEMW lvItem;
728
729 TRACE("(%p)(pidl=%p)\n", this, pidl);
730
731 lvItem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; /*set the mask*/
732 lvItem.iItem = ListView_GetItemCount(hWndList); /*add the item to the end of the list*/
733 lvItem.iSubItem = 0;
734 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidl)); /*set the item's data*/
735 lvItem.pszText = LPSTR_TEXTCALLBACKW; /*get text on a callback basis*/
736 lvItem.iImage = I_IMAGECALLBACK; /*get the image on a callback basis*/
737
738 if (SendMessageW(hWndList, LVM_INSERTITEMW, 0, (LPARAM)&lvItem) == -1)
739 return FALSE;
740 else
741 return TRUE;
742 }
743
744 /**********************************************************
745 * LV_DeleteItem()
746 */
747 BOOLEAN CDefView::LV_DeleteItem(LPCITEMIDLIST pidl)
748 {
749 int nIndex;
750
751 TRACE("(%p)(pidl=%p)\n", this, pidl);
752
753 nIndex = LV_FindItemByPidl(ILFindLastID(pidl));
754
755 return (-1 == ListView_DeleteItem(hWndList, nIndex)) ? FALSE : TRUE;
756 }
757
758 /**********************************************************
759 * LV_RenameItem()
760 */
761 BOOLEAN CDefView::LV_RenameItem(LPCITEMIDLIST pidlOld, LPCITEMIDLIST pidlNew)
762 {
763 int nItem;
764 LVITEMW lvItem;
765
766 TRACE("(%p)(pidlold=%p pidlnew=%p)\n", this, pidlOld, pidlNew);
767
768 nItem = LV_FindItemByPidl(ILFindLastID(pidlOld));
769
770 if ( -1 != nItem )
771 {
772 lvItem.mask = LVIF_PARAM; /* only the pidl */
773 lvItem.iItem = nItem;
774 SendMessageW(hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
775
776 SHFree((LPITEMIDLIST)lvItem.lParam);
777 lvItem.mask = LVIF_PARAM;
778 lvItem.iItem = nItem;
779 lvItem.lParam = (LPARAM) ILClone(ILFindLastID(pidlNew)); /* set the item's data */
780 SendMessageW(hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
781 SendMessageW(hWndList, LVM_UPDATE, nItem, 0);
782 return TRUE; /* FIXME: better handling */
783 }
784
785 return FALSE;
786 }
787
788 /**********************************************************
789 * ShellView_FillList()
790 *
791 * - gets the objectlist from the shellfolder
792 * - sorts the list
793 * - fills the list into the view
794 */
795 INT CALLBACK CDefView::fill_list( LPVOID ptr, LPVOID arg )
796 {
797 LPITEMIDLIST pidl = (LPITEMIDLIST)ptr;
798 CDefView *pThis = (CDefView *)arg;
799 /* in a commdlg This works as a filemask*/
800 if (pThis->IncludeObject(pidl) == S_OK)
801 pThis->LV_AddItem(pidl);
802
803 SHFree(pidl);
804 return TRUE;
805 }
806
807 HRESULT CDefView::FillList()
808 {
809 LPENUMIDLIST pEnumIDList;
810 LPITEMIDLIST pidl;
811 DWORD dwFetched;
812 HRESULT hRes;
813 HDPA hdpa;
814
815 TRACE("%p\n",this);
816
817 /* get the itemlist from the shfolder*/
818 hRes = pSFParent->EnumObjects(m_hWnd, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, &pEnumIDList);
819 if (hRes != S_OK)
820 {
821 if (hRes==S_FALSE)
822 return(NOERROR);
823 return(hRes);
824 }
825
826 /* create a pointer array */
827 hdpa = DPA_Create(16);
828 if (!hdpa)
829 {
830 return(E_OUTOFMEMORY);
831 }
832
833 /* copy the items into the array*/
834 while((S_OK == pEnumIDList->Next(1, &pidl, &dwFetched)) && dwFetched)
835 {
836 if (DPA_InsertPtr(hdpa, 0x7fff, pidl) == -1)
837 {
838 SHFree(pidl);
839 }
840 }
841
842 /* sort the array */
843 DPA_Sort(hdpa, CompareItems, (LPARAM)pSFParent.p);
844
845 /*turn the listview's redrawing off*/
846 SendMessageA(hWndList, WM_SETREDRAW, FALSE, 0);
847
848 DPA_DestroyCallback( hdpa, fill_list, (void *)this);
849
850 /*turn the listview's redrawing back on and force it to draw*/
851 SendMessageA(hWndList, WM_SETREDRAW, TRUE, 0);
852
853 pEnumIDList->Release(); /* destroy the list*/
854
855 return S_OK;
856 }
857
858 LRESULT CDefView::OnShowWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
859 {
860 ::UpdateWindow(hWndList);
861 bHandled = FALSE;
862 return 0;
863 }
864
865 LRESULT CDefView::OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
866 {
867 return SendMessageW(hWndList, uMsg, 0, 0);
868 }
869
870 LRESULT CDefView::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
871 {
872 RevokeDragDrop(m_hWnd);
873 SHChangeNotifyDeregister(hNotify);
874 bHandled = FALSE;
875 return 0;
876 }
877
878 LRESULT CDefView::OnEraseBackground(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
879 {
880 if (FolderSettings.fFlags & (FWF_DESKTOP | FWF_TRANSPARENT))
881 return SendMessageW(GetParent(), WM_ERASEBKGND, wParam, lParam); /* redirect to parent */
882
883 bHandled = FALSE;
884 return 0;
885 }
886
887 LRESULT CDefView::OnSysColorChange(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
888 {
889 /* Forward WM_SYSCOLORCHANGE to common controls */
890 return SendMessageW(hWndList, uMsg, 0, 0);
891 }
892
893 LRESULT CDefView::OnGetShellBrowser(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
894 {
895 return (LRESULT)pShellBrowser.p;
896 }
897
898 /**********************************************************
899 * ShellView_OnCreate()
900 */
901 LRESULT CDefView::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
902 {
903 CComPtr<IDropTarget> pdt;
904 SHChangeNotifyEntry ntreg;
905 CComPtr<IPersistFolder2> ppf2;
906
907 TRACE("%p\n",this);
908
909 DbgPrint("[shell32, CDefView::OnCreate] Called\n");
910
911 if(CreateList())
912 {
913 if(InitList())
914 {
915 FillList();
916 }
917 }
918
919 if (SUCCEEDED(this->QueryInterface(IID_IDropTarget, (LPVOID*)&pdt)))
920 RegisterDragDrop(m_hWnd, pdt);
921
922 /* register for receiving notifications */
923 pSFParent->QueryInterface(IID_IPersistFolder2, (LPVOID*)&ppf2);
924 if (ppf2)
925 {
926 ppf2->GetCurFolder((LPITEMIDLIST*)&ntreg.pidl);
927 ntreg.fRecursive = TRUE;
928 hNotify = SHChangeNotifyRegister(m_hWnd, SHCNF_IDLIST, SHCNE_ALLEVENTS, SHV_CHANGE_NOTIFY, 1, &ntreg);
929 SHFree((LPITEMIDLIST)ntreg.pidl);
930 }
931
932 hAccel = LoadAcceleratorsA(shell32_hInstance, "shv_accel");
933
934 return S_OK;
935 }
936
937 /**********************************************************
938 * #### Handling of the menus ####
939 */
940
941 /**********************************************************
942 * ShellView_BuildFileMenu()
943 */
944 HMENU CDefView::BuildFileMenu()
945 { WCHAR szText[MAX_PATH];
946 MENUITEMINFOW mii;
947 int nTools,i;
948 HMENU hSubMenu;
949
950 TRACE("(%p)\n",this);
951
952 hSubMenu = CreatePopupMenu();
953 if (hSubMenu)
954 {
955 /*get the number of items in our global array*/
956 for(nTools = 0; Tools[nTools].idCommand != -1; nTools++){}
957
958 /*add the menu items*/
959 for(i = 0; i < nTools; i++)
960 {
961 LoadStringW(shell32_hInstance, Tools[i].idMenuString, szText, MAX_PATH);
962
963 ZeroMemory(&mii, sizeof(mii));
964 mii.cbSize = sizeof(mii);
965 mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
966
967 if(BTNS_SEP != Tools[i].bStyle) /* no separator*/
968 {
969 mii.fType = MFT_STRING;
970 mii.fState = MFS_ENABLED;
971 mii.dwTypeData = szText;
972 mii.wID = Tools[i].idCommand;
973 }
974 else
975 {
976 mii.fType = MFT_SEPARATOR;
977 }
978 /* tack This item onto the end of the menu */
979 InsertMenuItemW(hSubMenu, (UINT)-1, TRUE, &mii);
980 }
981 }
982
983 TRACE("-- return (menu=%p)\n",hSubMenu);
984 return hSubMenu;
985 }
986
987 /**********************************************************
988 * ShellView_MergeFileMenu()
989 */
990 void CDefView::MergeFileMenu(HMENU hSubMenu)
991 {
992 TRACE("(%p)->(submenu=%p) stub\n",this,hSubMenu);
993
994 if (hSubMenu)
995 { /*insert This item at the beginning of the menu */
996 _InsertMenuItemW(hSubMenu, 0, TRUE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
997 _InsertMenuItemW(hSubMenu, 0, TRUE, IDM_MYFILEITEM, MFT_STRING, L"dummy45", MFS_ENABLED);
998 }
999
1000 TRACE("--\n");
1001 }
1002
1003 /**********************************************************
1004 * ShellView_MergeViewMenu()
1005 */
1006 void CDefView::MergeViewMenu(HMENU hSubMenu)
1007 {
1008 TRACE("(%p)->(submenu=%p)\n",this,hSubMenu);
1009
1010 if (hSubMenu)
1011 {
1012 /*add a separator at the correct position in the menu*/
1013 MENUITEMINFOW mii;
1014 static WCHAR view[] = L"View";
1015
1016 _InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, 0, MFT_SEPARATOR, NULL, MFS_ENABLED);
1017
1018 ZeroMemory(&mii, sizeof(mii));
1019 mii.cbSize = sizeof(mii);
1020 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_DATA;
1021 mii.fType = MFT_STRING;
1022 mii.dwTypeData = view;
1023 mii.hSubMenu = LoadMenuW(shell32_hInstance, L"MENU_001");
1024 InsertMenuItemW(hSubMenu, FCIDM_MENU_VIEW_SEP_OPTIONS, FALSE, &mii);
1025 }
1026 }
1027
1028 /**********************************************************
1029 * ShellView_GetSelections()
1030 *
1031 * - fills the this->apidl list with the selected objects
1032 *
1033 * RETURNS
1034 * number of selected items
1035 */
1036 UINT CDefView::GetSelections()
1037 {
1038 LVITEMW lvItem;
1039 UINT i = 0;
1040
1041 SHFree(apidl);
1042
1043 cidl = ListView_GetSelectedCount(hWndList);
1044 apidl = (LPITEMIDLIST*)SHAlloc(cidl * sizeof(LPITEMIDLIST));
1045
1046 TRACE("selected=%i\n", cidl);
1047
1048 if (apidl)
1049 {
1050 TRACE("-- Items selected =%u\n", cidl);
1051
1052 lvItem.mask = LVIF_STATE | LVIF_PARAM;
1053 lvItem.stateMask = LVIS_SELECTED;
1054 lvItem.iItem = 0;
1055 lvItem.iSubItem = 0;
1056 lvItem.state = 0;
1057
1058 while(SendMessageW(hWndList, LVM_GETITEMW, 0, (LPARAM)&lvItem) && (i < cidl))
1059 {
1060 if(lvItem.state & LVIS_SELECTED)
1061 {
1062 apidl[i] = (LPITEMIDLIST)lvItem.lParam;
1063 i++;
1064 if (i == cidl)
1065 break;
1066 TRACE("-- selected Item found\n");
1067 }
1068 lvItem.iItem++;
1069 }
1070 }
1071
1072 return cidl;
1073 }
1074
1075 /**********************************************************
1076 * ShellView_OpenSelectedItems()
1077 */
1078 HRESULT CDefView::OpenSelectedItems()
1079 {
1080 static UINT CF_IDLIST = 0;
1081 HRESULT hr;
1082 CComPtr<IDataObject> selection;
1083 CComPtr<IContextMenu> cm;
1084 HMENU hmenu;
1085 FORMATETC fetc;
1086 STGMEDIUM stgm;
1087 LPIDA pIDList;
1088 LPCITEMIDLIST parent_pidl;
1089 WCHAR parent_path[MAX_PATH];
1090 LPCWSTR parent_dir = NULL;
1091 SFGAOF attribs;
1092 int i;
1093 CMINVOKECOMMANDINFOEX ici;
1094 MENUITEMINFOW info;
1095
1096 if (0 == GetSelections())
1097 {
1098 return S_OK;
1099 }
1100
1101 hr = pSFParent->GetUIObjectOf(m_hWnd, cidl,
1102 (LPCITEMIDLIST*)apidl, IID_IContextMenu,
1103 0, (LPVOID *)&cm);
1104
1105 if (SUCCEEDED(hr))
1106 {
1107 hmenu = CreatePopupMenu();
1108 if (hmenu)
1109 {
1110 hr = IUnknown_SetSite(cm, (IShellView *)this);
1111 if (SUCCEEDED(cm->QueryContextMenu(hmenu, 0, 0x20, 0x7fff, CMF_DEFAULTONLY)))
1112 {
1113 INT def = -1, n = GetMenuItemCount(hmenu);
1114
1115 for ( i = 0; i < n; i++ )
1116 {
1117 memset( &info, 0, sizeof info );
1118 info.cbSize = sizeof info;
1119 info.fMask = MIIM_FTYPE | MIIM_STATE | MIIM_ID;
1120 if (GetMenuItemInfoW( hmenu, i, TRUE, &info))
1121 {
1122 if (info.fState & MFS_DEFAULT)
1123 {
1124 def = info.wID;
1125 break;
1126 }
1127 }
1128 }
1129 if (def != -1)
1130 {
1131 memset( &ici, 0, sizeof ici );
1132 ici.cbSize = sizeof ici;
1133 ici.lpVerb = MAKEINTRESOURCEA( def );
1134 ici.hwnd = m_hWnd;
1135
1136 if (cm->InvokeCommand((LPCMINVOKECOMMANDINFO) &ici ) == S_OK)
1137 {
1138 DestroyMenu( hmenu );
1139 hr = IUnknown_SetSite(cm, NULL);
1140 return S_OK;
1141 }
1142 }
1143
1144 }
1145 DestroyMenu( hmenu );
1146 hr = IUnknown_SetSite(cm, NULL);
1147 }
1148 cm->Release();
1149 }
1150
1151
1152
1153 hr = pSFParent->GetUIObjectOf(m_hWnd, cidl,
1154 (LPCITEMIDLIST*)apidl, IID_IDataObject,
1155 0, (LPVOID *)&selection);
1156
1157
1158
1159 if (FAILED(hr))
1160 return hr;
1161
1162 if (0 == CF_IDLIST)
1163 {
1164 CF_IDLIST = RegisterClipboardFormatW(CFSTR_SHELLIDLIST);
1165 }
1166
1167 fetc.cfFormat = CF_IDLIST;
1168 fetc.ptd = NULL;
1169 fetc.dwAspect = DVASPECT_CONTENT;
1170 fetc.lindex = -1;
1171 fetc.tymed = TYMED_HGLOBAL;
1172
1173 hr = selection->QueryGetData(&fetc);
1174 if (FAILED(hr))
1175 return hr;
1176
1177 hr = selection->GetData(&fetc, &stgm);
1178 if (FAILED(hr))
1179 return hr;
1180
1181 pIDList = (LPIDA)GlobalLock(stgm.hGlobal);
1182
1183 parent_pidl = (LPCITEMIDLIST) ((LPBYTE)pIDList+pIDList->aoffset[0]);
1184 hr = pSFParent->GetAttributesOf(1, &parent_pidl, &attribs);
1185 if (SUCCEEDED(hr) && (attribs & SFGAO_FILESYSTEM) &&
1186 SHGetPathFromIDListW(parent_pidl, parent_path))
1187 {
1188 parent_dir = parent_path;
1189 }
1190
1191 for (i = pIDList->cidl; i > 0; --i)
1192 {
1193 LPCITEMIDLIST pidl;
1194
1195 pidl = (LPCITEMIDLIST)((LPBYTE)pIDList+pIDList->aoffset[i]);
1196
1197 attribs = SFGAO_FOLDER;
1198 hr = pSFParent->GetAttributesOf(1, &pidl, &attribs);
1199
1200 if (SUCCEEDED(hr) && ! (attribs & SFGAO_FOLDER))
1201 {
1202 SHELLEXECUTEINFOW shexinfo;
1203
1204 shexinfo.cbSize = sizeof(SHELLEXECUTEINFOW);
1205 shexinfo.fMask = SEE_MASK_INVOKEIDLIST; /* SEE_MASK_IDLIST is also possible. */
1206 shexinfo.hwnd = NULL;
1207 shexinfo.lpVerb = NULL;
1208 shexinfo.lpFile = NULL;
1209 shexinfo.lpParameters = NULL;
1210 shexinfo.lpDirectory = parent_dir;
1211 shexinfo.nShow = SW_NORMAL;
1212 shexinfo.lpIDList = ILCombine(parent_pidl, pidl);
1213
1214 ShellExecuteExW(&shexinfo); /* Discard error/success info */
1215
1216 ILFree((LPITEMIDLIST)shexinfo.lpIDList);
1217 }
1218 }
1219
1220 GlobalUnlock(stgm.hGlobal);
1221 ReleaseStgMedium(&stgm);
1222
1223 return S_OK;
1224 }
1225
1226 /**********************************************************
1227 * ShellView_DoContextMenu()
1228 */
1229 LRESULT CDefView::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1230 {
1231 WORD x;
1232 WORD y;
1233 BOOL bDefault;
1234 UINT uCommand;
1235 DWORD wFlags;
1236 HMENU hMenu;
1237 BOOL fExplore;
1238 HWND hwndTree;
1239 CMINVOKECOMMANDINFO cmi;
1240 HRESULT hResult;
1241
1242 // for some reason I haven't figured out, we sometimes recurse into this method
1243 if (pCM != NULL)
1244 return 0;
1245
1246 x = LOWORD(lParam);
1247 y = HIWORD(lParam);
1248 bDefault = FALSE;
1249
1250 TRACE("(%p)->(0x%08x 0x%08x 0x%08x) stub\n",this, x, y, bDefault);
1251
1252 fExplore = FALSE;
1253 hwndTree = NULL;
1254
1255 /* look, what's selected and create a context menu object of it*/
1256 if (GetSelections())
1257 {
1258 pSFParent->GetUIObjectOf(hWndParent, cidl, (LPCITEMIDLIST*)apidl, IID_IContextMenu, NULL, (LPVOID *)&pCM);
1259
1260 if (pCM)
1261 {
1262 TRACE("-- pContextMenu\n");
1263 hMenu = CreatePopupMenu();
1264
1265 if (hMenu)
1266 {
1267 hResult = IUnknown_SetSite(pCM, (IShellView *)this);
1268
1269 /* See if we are in Explore or Open mode. If the browser's tree is present, we are in Explore mode.*/
1270 if (SUCCEEDED(pShellBrowser->GetControlWindow(FCW_TREE, &hwndTree)) && hwndTree)
1271 {
1272 TRACE("-- explore mode\n");
1273 fExplore = TRUE;
1274 }
1275
1276 /* build the flags depending on what we can do with the selected item */
1277 wFlags = CMF_NORMAL | (cidl != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0);
1278
1279 /* let the ContextMenu merge its items in */
1280 if (SUCCEEDED(pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, wFlags )))
1281 {
1282 if (FolderSettings.fFlags & FWF_DESKTOP)
1283 SetMenuDefaultItem(hMenu, FCIDM_SHVIEW_OPEN, MF_BYCOMMAND);
1284
1285 if (bDefault)
1286 {
1287 TRACE("-- get menu default command\n");
1288 uCommand = GetMenuDefaultItem(hMenu, FALSE, GMDI_GOINTOPOPUPS);
1289 }
1290 else
1291 {
1292 TRACE("-- track popup\n");
1293 uCommand = TrackPopupMenu( hMenu,TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,m_hWnd,NULL);
1294 }
1295
1296 if (uCommand > 0)
1297 {
1298 TRACE("-- uCommand=%u\n", uCommand);
1299
1300 if (uCommand==FCIDM_SHVIEW_OPEN && pCommDlgBrowser.p != NULL)
1301 {
1302 TRACE("-- dlg: OnDefaultCommand\n");
1303 if (OnDefaultCommand() != S_OK)
1304 {
1305 OpenSelectedItems();
1306 }
1307 }
1308 else
1309 {
1310 TRACE("-- explore -- invoke command\n");
1311 ZeroMemory(&cmi, sizeof(cmi));
1312 cmi.cbSize = sizeof(cmi);
1313 cmi.hwnd = hWndParent; /* this window has to answer CWM_GETISHELLBROWSER */
1314 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1315 pCM->InvokeCommand(&cmi);
1316 }
1317 }
1318
1319 hResult = IUnknown_SetSite(pCM, NULL);
1320 DestroyMenu(hMenu);
1321 }
1322 }
1323 pCM.Release();
1324 }
1325 }
1326 else /* background context menu */
1327 {
1328 hMenu = CreatePopupMenu();
1329
1330 CDefFolderMenu_Create2(NULL, NULL, cidl, (LPCITEMIDLIST*)apidl, pSFParent, NULL, 0, NULL, (IContextMenu**)&pCM);
1331 pCM->QueryContextMenu(hMenu, 0, FCIDM_SHVIEWFIRST, FCIDM_SHVIEWLAST, 0);
1332
1333 uCommand = TrackPopupMenu( hMenu, TPM_LEFTALIGN | TPM_RETURNCMD,x,y,0,m_hWnd,NULL);
1334 DestroyMenu(hMenu);
1335
1336 TRACE("-- (%p)->(uCommand=0x%08x )\n",this, uCommand);
1337
1338 ZeroMemory(&cmi, sizeof(cmi));
1339 cmi.cbSize = sizeof(cmi);
1340 cmi.lpVerb = (LPCSTR)MAKEINTRESOURCEA(uCommand);
1341 cmi.hwnd = hWndParent;
1342 pCM->InvokeCommand(&cmi);
1343
1344 pCM.Release();
1345 }
1346
1347 return 0;
1348 }
1349
1350 /**********************************************************
1351 * ##### message handling #####
1352 */
1353
1354 /**********************************************************
1355 * ShellView_OnSize()
1356 */
1357 LRESULT CDefView::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1358 {
1359 WORD wWidth;
1360 WORD wHeight;
1361
1362 wWidth = LOWORD(lParam);
1363 wHeight = HIWORD(lParam);
1364
1365 TRACE("%p width=%u height=%u\n", this, wWidth, wHeight);
1366
1367 /*resize the ListView to fit our window*/
1368 if (hWndList)
1369 {
1370 ::MoveWindow(hWndList, 0, 0, wWidth, wHeight, TRUE);
1371 }
1372
1373 return 0;
1374 }
1375
1376 /**********************************************************
1377 * ShellView_OnDeactivate()
1378 *
1379 * NOTES
1380 * internal
1381 */
1382 void CDefView::OnDeactivate()
1383 {
1384 TRACE("%p\n",this);
1385
1386 if (uState != SVUIA_DEACTIVATE)
1387 {
1388 if (hMenu)
1389 {
1390 pShellBrowser->SetMenuSB(0, 0, 0);
1391 pShellBrowser->RemoveMenusSB(hMenu);
1392 DestroyMenu(hMenu);
1393 hMenu = 0;
1394 }
1395
1396 uState = SVUIA_DEACTIVATE;
1397 }
1398 }
1399
1400 void CDefView::DoActivate(UINT uState)
1401 {
1402 OLEMENUGROUPWIDTHS omw = { {0, 0, 0, 0, 0, 0} };
1403 MENUITEMINFOA mii;
1404 CHAR szText[MAX_PATH];
1405
1406 TRACE("%p uState=%x\n", this, uState);
1407
1408 /*don't do anything if the state isn't really changing */
1409 if (uState == uState)
1410 {
1411 return;
1412 }
1413
1414 OnDeactivate();
1415
1416 /*only do This if we are active */
1417 if(uState != SVUIA_DEACTIVATE)
1418 {
1419 /*merge the menus */
1420 hMenu = CreateMenu();
1421
1422 if(hMenu)
1423 {
1424 pShellBrowser->InsertMenusSB(hMenu, &omw);
1425 TRACE("-- after fnInsertMenusSB\n");
1426
1427 /*build the top level menu get the menu item's text*/
1428 strcpy(szText,"dummy 31");
1429
1430 ZeroMemory(&mii, sizeof(mii));
1431 mii.cbSize = sizeof(mii);
1432 mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
1433 mii.fType = MFT_STRING;
1434 mii.fState = MFS_ENABLED;
1435 mii.dwTypeData = szText;
1436 mii.hSubMenu = BuildFileMenu();
1437
1438 /*insert our menu into the menu bar*/
1439 if (mii.hSubMenu)
1440 {
1441 InsertMenuItemA(hMenu, FCIDM_MENU_HELP, FALSE, &mii);
1442 }
1443
1444 /*get the view menu so we can merge with it*/
1445 ZeroMemory(&mii, sizeof(mii));
1446 mii.cbSize = sizeof(mii);
1447 mii.fMask = MIIM_SUBMENU;
1448
1449 if (GetMenuItemInfoA(hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
1450 {
1451 MergeViewMenu(mii.hSubMenu);
1452 }
1453
1454 /*add the items that should only be added if we have the focus*/
1455 if (SVUIA_ACTIVATE_FOCUS == uState)
1456 {
1457 /*get the file menu so we can merge with it */
1458 ZeroMemory(&mii, sizeof(mii));
1459 mii.cbSize = sizeof(mii);
1460 mii.fMask = MIIM_SUBMENU;
1461
1462 if (GetMenuItemInfoA(hMenu, FCIDM_MENU_FILE, FALSE, &mii))
1463 {
1464 MergeFileMenu(mii.hSubMenu);
1465 }
1466 }
1467
1468 TRACE("-- before fnSetMenuSB\n");
1469 pShellBrowser->SetMenuSB(hMenu, 0, m_hWnd);
1470 }
1471 }
1472 uState = uState;
1473 TRACE("--\n");
1474 }
1475
1476 /**********************************************************
1477 * ShellView_OnActivate()
1478 */
1479 LRESULT CDefView::OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1480 {
1481 DoActivate(SVUIA_ACTIVATE_FOCUS);
1482 return 0;
1483 }
1484
1485 /**********************************************************
1486 * ShellView_OnSetFocus()
1487 *
1488 */
1489 LRESULT CDefView::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1490 {
1491 TRACE("%p\n", this);
1492
1493 /* Tell the browser one of our windows has received the focus. This
1494 should always be done before merging menus (OnActivate merges the
1495 menus) if one of our windows has the focus.*/
1496
1497 pShellBrowser->OnViewWindowActive((IShellView *)this);
1498 DoActivate(SVUIA_ACTIVATE_FOCUS);
1499
1500 /* Set the focus to the listview */
1501 ::SetFocus(hWndList);
1502
1503 /* Notify the ICommDlgBrowser interface */
1504 OnStateChange(CDBOSC_SETFOCUS);
1505
1506 return 0;
1507 }
1508
1509 /**********************************************************
1510 * ShellView_OnKillFocus()
1511 */
1512 LRESULT CDefView::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1513 {
1514 TRACE("(%p) stub\n", this);
1515
1516 DoActivate(SVUIA_ACTIVATE_NOFOCUS);
1517 /* Notify the ICommDlgBrowser */
1518 OnStateChange(CDBOSC_KILLFOCUS);
1519
1520 return 0;
1521 }
1522
1523 /**********************************************************
1524 * ShellView_OnCommand()
1525 *
1526 * NOTES
1527 * the CmdID's are the ones from the context menu
1528 */
1529 LRESULT CDefView::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1530 {
1531 DWORD dwCmdID;
1532 DWORD dwCmd;
1533 HWND hwndCmd;
1534
1535 dwCmdID = GET_WM_COMMAND_ID(wParam, lParam);
1536 dwCmd = GET_WM_COMMAND_CMD(wParam, lParam);
1537 hwndCmd = GET_WM_COMMAND_HWND(wParam, lParam);
1538
1539 TRACE("(%p)->(0x%08x 0x%08x %p) stub\n",this, dwCmdID, dwCmd, hwndCmd);
1540
1541 switch (dwCmdID)
1542 {
1543 case FCIDM_SHVIEW_SMALLICON:
1544 FolderSettings.ViewMode = FVM_SMALLICON;
1545 SetStyle (LVS_SMALLICON, LVS_TYPEMASK);
1546 CheckToolbar();
1547 break;
1548
1549 case FCIDM_SHVIEW_BIGICON:
1550 FolderSettings.ViewMode = FVM_ICON;
1551 SetStyle (LVS_ICON, LVS_TYPEMASK);
1552 CheckToolbar();
1553 break;
1554
1555 case FCIDM_SHVIEW_LISTVIEW:
1556 FolderSettings.ViewMode = FVM_LIST;
1557 SetStyle (LVS_LIST, LVS_TYPEMASK);
1558 CheckToolbar();
1559 break;
1560
1561 case FCIDM_SHVIEW_REPORTVIEW:
1562 FolderSettings.ViewMode = FVM_DETAILS;
1563 SetStyle (LVS_REPORT, LVS_TYPEMASK);
1564 CheckToolbar();
1565 break;
1566
1567 /* the menu-ID's for sorting are 0x30... see shrec.rc */
1568 case 0x30:
1569 case 0x31:
1570 case 0x32:
1571 case 0x33:
1572 ListViewSortInfo.nHeaderID = (LPARAM) (dwCmdID - 0x30);
1573 ListViewSortInfo.bIsAscending = TRUE;
1574 ListViewSortInfo.nLastHeaderID = ListViewSortInfo.nHeaderID;
1575 SendMessageA(hWndList, LVM_SORTITEMS, (WPARAM) &ListViewSortInfo, (LPARAM)ListViewCompareItems);
1576 break;
1577
1578 default:
1579 TRACE("-- COMMAND 0x%04x unhandled\n", dwCmdID);
1580 }
1581
1582 return 0;
1583 }
1584
1585 /**********************************************************
1586 * ShellView_OnNotify()
1587 */
1588
1589 LRESULT CDefView::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
1590 {
1591 UINT CtlID;
1592 LPNMHDR lpnmh;
1593 LPNMLISTVIEW lpnmlv;
1594 NMLVDISPINFOW *lpdi;
1595 LPITEMIDLIST pidl;
1596 BOOL unused;
1597
1598 CtlID = wParam;
1599 lpnmh = (LPNMHDR)lParam;
1600 lpnmlv = (LPNMLISTVIEW)lpnmh;
1601 lpdi = (NMLVDISPINFOW *)lpnmh;
1602
1603 TRACE("%p CtlID=%u lpnmh->code=%x\n",this,CtlID,lpnmh->code);
1604
1605 switch (lpnmh->code)
1606 {
1607 case NM_SETFOCUS:
1608 TRACE("-- NM_SETFOCUS %p\n", this);
1609 OnSetFocus(0, 0, 0, unused);
1610 break;
1611
1612 case NM_KILLFOCUS:
1613 TRACE("-- NM_KILLFOCUS %p\n", this);
1614 OnDeactivate();
1615 /* Notify the ICommDlgBrowser interface */
1616 OnStateChange(CDBOSC_KILLFOCUS);
1617 break;
1618
1619 case NM_CUSTOMDRAW:
1620 TRACE("-- NM_CUSTOMDRAW %p\n", this);
1621 return CDRF_DODEFAULT;
1622
1623 case NM_RELEASEDCAPTURE:
1624 TRACE("-- NM_RELEASEDCAPTURE %p\n", this);
1625 break;
1626
1627 case NM_CLICK:
1628 TRACE("-- NM_CLICK %p\n", this);
1629 break;
1630
1631 case NM_RCLICK:
1632 TRACE("-- NM_RCLICK %p\n", this);
1633 break;
1634
1635 case NM_DBLCLK:
1636 TRACE("-- NM_DBLCLK %p\n", this);
1637 if (OnDefaultCommand() != S_OK) OpenSelectedItems();
1638 break;
1639
1640 case NM_RETURN:
1641 TRACE("-- NM_RETURN %p\n", this);
1642 if (OnDefaultCommand() != S_OK) OpenSelectedItems();
1643 break;
1644
1645 case HDN_ENDTRACKW:
1646 TRACE("-- HDN_ENDTRACKW %p\n", this);
1647 /*nColumn1 = ListView_GetColumnWidth(hWndList, 0);
1648 nColumn2 = ListView_GetColumnWidth(hWndList, 1);*/
1649 break;
1650
1651 case LVN_DELETEITEM:
1652 TRACE("-- LVN_DELETEITEM %p\n", this);
1653 SHFree((LPITEMIDLIST)lpnmlv->lParam); /*delete the pidl because we made a copy of it*/
1654 break;
1655
1656 case LVN_DELETEALLITEMS:
1657 TRACE("-- LVN_DELETEALLITEMS %p\n", this);
1658 return FALSE;
1659
1660 case LVN_INSERTITEM:
1661 TRACE("-- LVN_INSERTITEM (STUB)%p\n", this);
1662 break;
1663
1664 case LVN_ITEMACTIVATE:
1665 TRACE("-- LVN_ITEMACTIVATE %p\n", this);
1666 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1667 break;
1668
1669 case LVN_COLUMNCLICK:
1670 ListViewSortInfo.nHeaderID = lpnmlv->iSubItem;
1671 if (ListViewSortInfo.nLastHeaderID == ListViewSortInfo.nHeaderID)
1672 {
1673 ListViewSortInfo.bIsAscending = !ListViewSortInfo.bIsAscending;
1674 }
1675 else
1676 {
1677 ListViewSortInfo.bIsAscending = TRUE;
1678 }
1679 ListViewSortInfo.nLastHeaderID = ListViewSortInfo.nHeaderID;
1680
1681 SendMessageW(lpnmlv->hdr.hwndFrom, LVM_SORTITEMS, (WPARAM) &ListViewSortInfo, (LPARAM)ListViewCompareItems);
1682 break;
1683
1684 case LVN_GETDISPINFOA:
1685 case LVN_GETDISPINFOW:
1686 TRACE("-- LVN_GETDISPINFO %p\n", this);
1687 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1688
1689 if (lpdi->item.mask & LVIF_TEXT) /* text requested */
1690 {
1691 if (pSF2Parent)
1692 {
1693 SHELLDETAILS sd;
1694 pSF2Parent->GetDetailsOf(pidl, lpdi->item.iSubItem, &sd);
1695 if (lpnmh->code == LVN_GETDISPINFOA)
1696 {
1697 /* shouldn't happen */
1698 NMLVDISPINFOA *lpdiA = (NMLVDISPINFOA *)lpnmh;
1699 StrRetToStrNA( lpdiA->item.pszText, lpdiA->item.cchTextMax, &sd.str, NULL);
1700 TRACE("-- text=%s\n",lpdiA->item.pszText);
1701 }
1702 else /* LVN_GETDISPINFOW */
1703 {
1704 StrRetToStrNW( lpdi->item.pszText, lpdi->item.cchTextMax, &sd.str, NULL);
1705 TRACE("-- text=%s\n",debugstr_w(lpdi->item.pszText));
1706 }
1707 }
1708 else
1709 {
1710 FIXME("no SF2\n");
1711 }
1712 }
1713 if(lpdi->item.mask & LVIF_IMAGE) /* image requested */
1714 {
1715 lpdi->item.iImage = SHMapPIDLToSystemImageListIndex(pSFParent, pidl, 0);
1716 }
1717 lpdi->item.mask |= LVIF_DI_SETITEM;
1718 break;
1719
1720 case LVN_ITEMCHANGED:
1721 TRACE("-- LVN_ITEMCHANGED %p\n", this);
1722 OnStateChange(CDBOSC_SELCHANGE); /* the browser will get the IDataObject now */
1723 break;
1724
1725 case LVN_BEGINDRAG:
1726 case LVN_BEGINRDRAG:
1727 TRACE("-- LVN_BEGINDRAG\n");
1728
1729 if (GetSelections())
1730 {
1731 IDataObject * pda;
1732 DWORD dwAttributes = SFGAO_CANLINK;
1733 DWORD dwEffect = DROPEFFECT_COPY | DROPEFFECT_MOVE;
1734
1735 if (SUCCEEDED(pSFParent->GetUIObjectOf(m_hWnd, cidl, (LPCITEMIDLIST*)apidl, IID_IDataObject,0,(LPVOID *)&pda)))
1736 {
1737 IDropSource * pds = (IDropSource *)this; /* own DropSource interface */
1738
1739 if (SUCCEEDED(pSFParent->GetAttributesOf(cidl, (LPCITEMIDLIST*)apidl, &dwAttributes)))
1740 {
1741 if (dwAttributes & SFGAO_CANLINK)
1742 {
1743 dwEffect |= DROPEFFECT_LINK;
1744 }
1745 }
1746
1747 if (pds)
1748 {
1749 DWORD dwEffect2;
1750 DoDragDrop(pda, pds, dwEffect, &dwEffect2);
1751 }
1752 pda->Release();
1753 }
1754 }
1755 break;
1756
1757 case LVN_BEGINLABELEDITW:
1758 {
1759 DWORD dwAttr = SFGAO_CANRENAME;
1760 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1761
1762 TRACE("-- LVN_BEGINLABELEDITW %p\n", this);
1763
1764 pSFParent->GetAttributesOf(1, (LPCITEMIDLIST*)&pidl, &dwAttr);
1765 if (SFGAO_CANRENAME & dwAttr)
1766 {
1767 return FALSE;
1768 }
1769 return TRUE;
1770 }
1771
1772 case LVN_ENDLABELEDITW:
1773 {
1774 TRACE("-- LVN_ENDLABELEDITW %p\n", this);
1775 if (lpdi->item.pszText)
1776 {
1777 HRESULT hr;
1778 LVITEMW lvItem;
1779
1780 lvItem.iItem = lpdi->item.iItem;
1781 lvItem.iSubItem = 0;
1782 lvItem.mask = LVIF_PARAM;
1783 SendMessageW(hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
1784
1785 pidl = (LPITEMIDLIST)lpdi->item.lParam;
1786 hr = pSFParent->SetNameOf(0, pidl, lpdi->item.pszText, SHGDN_INFOLDER, &pidl);
1787
1788 if (SUCCEEDED(hr) && pidl)
1789 {
1790 lvItem.mask = LVIF_PARAM;
1791 lvItem.lParam = (LPARAM)pidl;
1792 SendMessageW(hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
1793
1794 return TRUE;
1795 }
1796 }
1797
1798 return FALSE;
1799 }
1800
1801 case LVN_KEYDOWN:
1802 {
1803 /* MSG msg;
1804 msg.hwnd = m_hWnd;
1805 msg.message = WM_KEYDOWN;
1806 msg.wParam = plvKeyDown->wVKey;
1807 msg.lParam = 0;
1808 msg.time = 0;
1809 msg.pt = 0;*/
1810
1811 LPNMLVKEYDOWN plvKeyDown = (LPNMLVKEYDOWN) lpnmh;
1812 SHORT ctrl = GetKeyState(VK_CONTROL) & 0x8000;
1813
1814 /* initiate a rename of the selected file or directory */
1815 if (plvKeyDown->wVKey == VK_F2)
1816 {
1817 /* see how many files are selected */
1818 int i = ListView_GetSelectedCount(hWndList);
1819
1820 /* get selected item */
1821 if (i == 1)
1822 {
1823 /* get selected item */
1824 i = ListView_GetNextItem(hWndList, -1, LVNI_SELECTED);
1825
1826 SendMessageW(hWndList, LVM_ENSUREVISIBLE, i, 0);
1827 SendMessageW(hWndList, LVM_EDITLABELW, i, 0);
1828 }
1829 }
1830 #if 0
1831 TranslateAccelerator(m_hWnd, hAccel, &msg)
1832 #endif
1833 else if(plvKeyDown->wVKey == VK_DELETE)
1834 {
1835 UINT i;
1836 int item_index;
1837 LVITEMA item;
1838 LPITEMIDLIST* pItems;
1839 ISFHelper *psfhlp;
1840
1841 pSFParent->QueryInterface(IID_ISFHelper,
1842 (LPVOID*)&psfhlp);
1843
1844 if (psfhlp == NULL)
1845 break;
1846
1847 if (!(i = ListView_GetSelectedCount(hWndList)))
1848 break;
1849
1850 /* allocate memory for the pidl array */
1851 pItems = (LPITEMIDLIST *)HeapAlloc(GetProcessHeap(), 0,
1852 sizeof(LPITEMIDLIST) * i);
1853
1854 /* retrieve all selected items */
1855 i = 0;
1856 item_index = -1;
1857 while (ListView_GetSelectedCount(hWndList) > i)
1858 {
1859 /* get selected item */
1860 item_index = ListView_GetNextItem(hWndList,
1861 item_index, LVNI_SELECTED);
1862 item.iItem = item_index;
1863 item.mask = LVIF_PARAM;
1864 SendMessageA(hWndList, LVM_GETITEMA, 0, (LPARAM) &item);
1865
1866 /* get item pidl */
1867 pItems[i] = (LPITEMIDLIST)item.lParam;
1868
1869 i++;
1870 }
1871
1872 /* perform the item deletion */
1873 psfhlp->DeleteItems(i, (LPCITEMIDLIST*)pItems);
1874
1875 /* free pidl array memory */
1876 HeapFree(GetProcessHeap(), 0, pItems);
1877 }
1878 /* Initiate a refresh */
1879 else if (plvKeyDown->wVKey == VK_F5)
1880 {
1881 Refresh();
1882 }
1883 else if (plvKeyDown->wVKey == VK_BACK)
1884 {
1885 LPSHELLBROWSER lpSb;
1886 if ((lpSb = (LPSHELLBROWSER)SendMessageW(hWndParent, CWM_GETISHELLBROWSER, 0, 0)))
1887 {
1888 lpSb->BrowseObject(NULL, SBSP_PARENT);
1889 }
1890 }
1891 else if (plvKeyDown->wVKey == 'C' && ctrl)
1892 {
1893 if (GetSelections())
1894 {
1895 CComPtr<IDataObject> pda;
1896
1897 if (SUCCEEDED(pSFParent->GetUIObjectOf(m_hWnd, cidl, (LPCITEMIDLIST*)apidl, IID_IDataObject, 0, (LPVOID *)&pda)))
1898 {
1899 HRESULT hr = OleSetClipboard(pda);
1900 if (FAILED(hr))
1901 {
1902 WARN("OleSetClipboard failed");
1903 }
1904 }
1905 }
1906 break;
1907 }
1908 else if(plvKeyDown->wVKey == 'V' && ctrl)
1909 {
1910 CComPtr<IDataObject> pda;
1911 STGMEDIUM medium;
1912 FORMATETC formatetc;
1913 LPITEMIDLIST * apidl;
1914 LPITEMIDLIST pidl;
1915 CComPtr<IShellFolder> psfFrom;
1916 CComPtr<IShellFolder> psfDesktop;
1917 CComPtr<IShellFolder> psfTarget;
1918 LPIDA lpcida;
1919 CComPtr<ISFHelper> psfhlpdst;
1920 CComPtr<ISFHelper> psfhlpsrc;
1921 HRESULT hr;
1922
1923 hr = OleGetClipboard(&pda);
1924 if (hr != S_OK)
1925 {
1926 ERR("Failed to get clipboard with %lx\n", hr);
1927 return E_FAIL;
1928 }
1929
1930 InitFormatEtc(formatetc, RegisterClipboardFormatW(CFSTR_SHELLIDLIST), TYMED_HGLOBAL);
1931 hr = pda->GetData(&formatetc, &medium);
1932
1933 if (FAILED(hr))
1934 {
1935 ERR("Failed to get clipboard data with %lx\n", hr);
1936 return E_FAIL;
1937 }
1938
1939 /* lock the handle */
1940 lpcida = (LPIDA)GlobalLock(medium.hGlobal);
1941 if (!lpcida)
1942 {
1943 ERR("failed to lock pidl\n");
1944 ReleaseStgMedium(&medium);
1945 return E_FAIL;
1946 }
1947
1948 /* convert the data into pidl */
1949 apidl = _ILCopyCidaToaPidl(&pidl, lpcida);
1950
1951 if (!apidl)
1952 {
1953 ERR("failed to copy pidl\n");
1954 return E_FAIL;
1955 }
1956
1957 if (FAILED(SHGetDesktopFolder(&psfDesktop)))
1958 {
1959 ERR("failed to get desktop folder\n");
1960 SHFree(pidl);
1961 _ILFreeaPidl(apidl, lpcida->cidl);
1962 ReleaseStgMedium(&medium);
1963 return E_FAIL;
1964 }
1965
1966 if (_ILIsDesktop(pidl))
1967 {
1968 /* use desktop shellfolder */
1969 psfFrom = psfDesktop;
1970 }
1971 else if (FAILED(psfDesktop->BindToObject(pidl, NULL, IID_IShellFolder, (LPVOID*)&psfFrom)))
1972 {
1973 ERR("no IShellFolder\n");
1974
1975 SHFree(pidl);
1976 _ILFreeaPidl(apidl, lpcida->cidl);
1977 ReleaseStgMedium(&medium);
1978
1979 return E_FAIL;
1980 }
1981
1982 psfTarget = pSFParent;
1983
1984
1985 /* get source and destination shellfolder */
1986 if (FAILED(psfTarget->QueryInterface(IID_ISFHelper, (LPVOID*)&psfhlpdst)))
1987 {
1988 ERR("no IID_ISFHelper for destination\n");
1989
1990 SHFree(pidl);
1991 _ILFreeaPidl(apidl, lpcida->cidl);
1992 ReleaseStgMedium(&medium);
1993
1994 return E_FAIL;
1995 }
1996
1997 if (FAILED(psfFrom->QueryInterface(IID_ISFHelper, (LPVOID*)&psfhlpsrc)))
1998 {
1999 ERR("no IID_ISFHelper for source\n");
2000
2001 SHFree(pidl);
2002 _ILFreeaPidl(apidl, lpcida->cidl);
2003 ReleaseStgMedium(&medium);
2004 return E_FAIL;
2005 }
2006
2007 /* FIXXME
2008 * do we want to perform a copy or move ???
2009 */
2010 hr = psfhlpdst->CopyItems(psfFrom, lpcida->cidl, (LPCITEMIDLIST*)apidl);
2011
2012 SHFree(pidl);
2013 _ILFreeaPidl(apidl, lpcida->cidl);
2014 ReleaseStgMedium(&medium);
2015
2016 TRACE("paste end hr %x\n", hr);
2017 break;
2018 }
2019 else
2020 FIXME("LVN_KEYDOWN key=0x%08x\n",plvKeyDown->wVKey);
2021 }
2022 break;
2023
2024 default:
2025 TRACE("-- %p WM_COMMAND %x unhandled\n", this, lpnmh->code);
2026 break;
2027 }
2028
2029 return 0;
2030 }
2031
2032 /**********************************************************
2033 * ShellView_OnChange()
2034 */
2035 LRESULT CDefView::OnChangeNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2036 {
2037 LPITEMIDLIST *Pidls;
2038
2039 Pidls = (LPITEMIDLIST *)wParam;
2040
2041 TRACE("(%p)(%p,%p,0x%08x)\n", this, Pidls[0], Pidls[1], lParam);
2042
2043 switch (lParam)
2044 {
2045 case SHCNE_MKDIR:
2046 case SHCNE_CREATE:
2047 LV_AddItem(Pidls[0]);
2048 break;
2049
2050 case SHCNE_RMDIR:
2051 case SHCNE_DELETE:
2052 LV_DeleteItem(Pidls[0]);
2053 break;
2054
2055 case SHCNE_RENAMEFOLDER:
2056 case SHCNE_RENAMEITEM:
2057 LV_RenameItem(Pidls[0], Pidls[1]);
2058 break;
2059
2060 case SHCNE_UPDATEITEM:
2061 break;
2062 }
2063
2064 return TRUE;
2065 }
2066
2067 /**********************************************************
2068 * ShellView_DoMeasureItem
2069 */
2070 LRESULT CDefView::OnCustomItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
2071 {
2072 if (!pCM.p)
2073 {
2074 /* no menu */
2075 ERR("no menu!!!\n");
2076 return FALSE;
2077 }
2078
2079 if (pCM.p->HandleMenuMsg(uMsg, (WPARAM)m_hWnd, lParam) == S_OK)
2080 return TRUE;
2081 else
2082 return FALSE;
2083 }
2084
2085 /**********************************************************
2086 *
2087 *
2088 * The INTERFACE of the IShellView object
2089 *
2090 *
2091 **********************************************************
2092 */
2093
2094 /**********************************************************
2095 * ShellView_GetWindow
2096 */
2097 HRESULT WINAPI CDefView::GetWindow(HWND *phWnd)
2098 {
2099 TRACE("(%p)\n",this);
2100
2101 *phWnd = m_hWnd;
2102
2103 return S_OK;
2104 }
2105
2106 HRESULT WINAPI CDefView::ContextSensitiveHelp(BOOL fEnterMode)
2107 {
2108 FIXME("(%p) stub\n",this);
2109
2110 return E_NOTIMPL;
2111 }
2112
2113 /**********************************************************
2114 * IShellView_TranslateAccelerator
2115 *
2116 * FIXME:
2117 * use the accel functions
2118 */
2119 HRESULT WINAPI CDefView::TranslateAccelerator(LPMSG lpmsg)
2120 {
2121 #if 0
2122 FIXME("(%p)->(%p: hwnd=%x msg=%x lp=%x wp=%x) stub\n",this,lpmsg, lpmsg->hwnd, lpmsg->message, lpmsg->lParam, lpmsg->wParam);
2123 #endif
2124
2125 if (lpmsg->message >= WM_KEYFIRST && lpmsg->message >= WM_KEYLAST)
2126 {
2127 TRACE("-- key=0x04%lx\n",lpmsg->wParam) ;
2128 }
2129
2130 return S_FALSE; /* not handled */
2131 }
2132
2133 HRESULT WINAPI CDefView::EnableModeless(BOOL fEnable)
2134 {
2135 FIXME("(%p) stub\n",this);
2136
2137 return E_NOTIMPL;
2138 }
2139
2140 HRESULT WINAPI CDefView::UIActivate(UINT uState)
2141 {
2142 /*
2143 CHAR szName[MAX_PATH];
2144 */
2145 LRESULT lResult;
2146 int nPartArray[1] = {-1};
2147
2148 TRACE("(%p)->(state=%x) stub\n",this, uState);
2149
2150 /*don't do anything if the state isn't really changing*/
2151 if (uState == uState)
2152 {
2153 return S_OK;
2154 }
2155
2156 /*OnActivate handles the menu merging and internal state*/
2157 DoActivate(uState);
2158
2159 /*only do This if we are active*/
2160 if (uState != SVUIA_DEACTIVATE)
2161 {
2162
2163 /*
2164 GetFolderPath is not a method of IShellFolder
2165 IShellFolder_GetFolderPath( pSFParent, szName, sizeof(szName) );
2166 */
2167 /* set the number of parts */
2168 pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult);
2169
2170 /* set the text for the parts */
2171 /*
2172 pShellBrowser->SendControlMsg(FCW_STATUS, SB_SETTEXTA, 0, (LPARAM)szName, &lResult);
2173 */
2174 }
2175
2176 return S_OK;
2177 }
2178
2179 HRESULT WINAPI CDefView::Refresh()
2180 {
2181 TRACE("(%p)\n",this);
2182
2183 SendMessageW(hWndList, LVM_DELETEALLITEMS, 0, 0);
2184 FillList();
2185
2186 return S_OK;
2187 }
2188
2189 HRESULT WINAPI CDefView::CreateViewWindow(IShellView *lpPrevView, LPCFOLDERSETTINGS lpfs, IShellBrowser *psb, RECT *prcView, HWND *phWnd)
2190 {
2191 *phWnd = 0;
2192
2193 TRACE("(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",this, lpPrevView,lpfs, psb, prcView, phWnd);
2194
2195 DbgPrint("[shell32, CDefView::CreateViewWindow] Called lpfs = 0x%x, psb = 0x%x\n", lpfs, psb);
2196
2197 if (lpfs != NULL)
2198 TRACE("-- vmode=%x flags=%x\n", lpfs->ViewMode, lpfs->fFlags);
2199 if (prcView != NULL)
2200 TRACE("-- left=%i top=%i right=%i bottom=%i\n", prcView->left, prcView->top, prcView->right, prcView->bottom);
2201
2202 /* Validate the Shell Browser */
2203 if (psb == NULL)
2204 return E_UNEXPECTED;
2205
2206 /*set up the member variables*/
2207 pShellBrowser = psb;
2208 FolderSettings = *lpfs;
2209
2210 /*get our parent window*/
2211 pShellBrowser->GetWindow(&hWndParent);
2212
2213 /* try to get the ICommDlgBrowserInterface, adds a reference !!! */
2214 pCommDlgBrowser = NULL;
2215 if (SUCCEEDED(pShellBrowser->QueryInterface(IID_ICommDlgBrowser, (LPVOID *)&pCommDlgBrowser)))
2216 {
2217 TRACE("-- CommDlgBrowser\n");
2218 }
2219
2220 DbgPrint("[shell32, CDefView::CreateViewWindow] About to call the create function\n");
2221
2222 Create(hWndParent, prcView, NULL, WS_CHILD | WS_TABSTOP, 0, 0U);
2223 if (m_hWnd == NULL)
2224 return E_FAIL;
2225
2226 *phWnd = m_hWnd;
2227
2228 CheckToolbar();
2229
2230 if (!*phWnd)
2231 return E_FAIL;
2232
2233 SetWindowPos(HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW);
2234 UpdateWindow();
2235
2236 return S_OK;
2237 }
2238
2239 HRESULT WINAPI CDefView::DestroyViewWindow()
2240 {
2241 TRACE("(%p)\n",this);
2242
2243 /*Make absolutely sure all our UI is cleaned up.*/
2244 UIActivate(SVUIA_DEACTIVATE);
2245
2246 if (hMenu)
2247 {
2248 DestroyMenu(hMenu);
2249 }
2250
2251 DestroyWindow();
2252 pShellBrowser.Release();
2253 pCommDlgBrowser.Release();
2254
2255 return S_OK;
2256 }
2257
2258 HRESULT WINAPI CDefView::GetCurrentInfo(LPFOLDERSETTINGS lpfs)
2259 {
2260 TRACE("(%p)->(%p) vmode=%x flags=%x\n",this, lpfs,
2261 FolderSettings.ViewMode, FolderSettings.fFlags);
2262
2263 if (!lpfs)
2264 return E_INVALIDARG;
2265
2266 *lpfs = FolderSettings;
2267 return NOERROR;
2268 }
2269
2270 HRESULT WINAPI CDefView::AddPropertySheetPages(DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
2271 {
2272 FIXME("(%p) stub\n",this);
2273
2274 return E_NOTIMPL;
2275 }
2276
2277 HRESULT WINAPI CDefView::SaveViewState()
2278 {
2279 FIXME("(%p) stub\n",this);
2280
2281 return S_OK;
2282 }
2283
2284 HRESULT WINAPI CDefView::SelectItem(LPCITEMIDLIST pidl, UINT uFlags)
2285 {
2286 int i;
2287
2288 TRACE("(%p)->(pidl=%p, 0x%08x) stub\n",this, pidl, uFlags);
2289
2290 i = LV_FindItemByPidl(pidl);
2291
2292 if (i != -1)
2293 {
2294 LVITEMW lvItem;
2295
2296 if(uFlags & SVSI_ENSUREVISIBLE)
2297 SendMessageW(hWndList, LVM_ENSUREVISIBLE, i, 0);
2298
2299 lvItem.mask = LVIF_STATE;
2300 lvItem.stateMask = LVIS_SELECTED | LVIS_FOCUSED;
2301 lvItem.iItem = 0;
2302 lvItem.iSubItem = 0;
2303
2304 while (SendMessageW(hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem))
2305 {
2306 if (lvItem.iItem == i)
2307 {
2308 if (uFlags & SVSI_SELECT)
2309 lvItem.state |= LVIS_SELECTED;
2310 else
2311 lvItem.state &= ~LVIS_SELECTED;
2312
2313 if (uFlags & SVSI_FOCUSED)
2314 lvItem.state &= ~LVIS_FOCUSED;
2315 }
2316 else
2317 {
2318 if (uFlags & SVSI_DESELECTOTHERS)
2319 lvItem.state &= ~LVIS_SELECTED;
2320 }
2321
2322 SendMessageW(hWndList, LVM_SETITEMW, 0, (LPARAM) &lvItem);
2323 lvItem.iItem++;
2324 }
2325
2326
2327 if(uFlags & SVSI_EDIT)
2328 SendMessageW(hWndList, LVM_EDITLABELW, i, 0);
2329 }
2330
2331 return S_OK;
2332 }
2333
2334 HRESULT WINAPI CDefView::GetItemObject(UINT uItem, REFIID riid, LPVOID *ppvOut)
2335 {
2336 HRESULT hr = E_FAIL;
2337
2338 TRACE("(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)\n",this, uItem, debugstr_guid(&riid), ppvOut);
2339
2340 *ppvOut = NULL;
2341
2342 switch (uItem)
2343 {
2344 case SVGIO_BACKGROUND:
2345 if (IsEqualIID(riid, IID_IContextMenu))
2346 {
2347 //*ppvOut = ISvBgCm_Constructor(pSFParent, FALSE);
2348 CDefFolderMenu_Create2(NULL, NULL, cidl, (LPCITEMIDLIST*)apidl, pSFParent, NULL, 0, NULL, (IContextMenu**)ppvOut);
2349 if (!ppvOut)
2350 hr = E_OUTOFMEMORY;
2351 }
2352 break;
2353
2354 case SVGIO_SELECTION:
2355 GetSelections();
2356 hr = pSFParent->GetUIObjectOf(m_hWnd, cidl, (LPCITEMIDLIST*)apidl, riid, 0, ppvOut);
2357 break;
2358 }
2359
2360 TRACE("-- (%p)->(interface=%p)\n",this, *ppvOut);
2361
2362 return hr;
2363 }
2364
2365 HRESULT STDMETHODCALLTYPE CDefView::GetCurrentViewMode(UINT *pViewMode)
2366 {
2367 return E_NOTIMPL;
2368 }
2369
2370 HRESULT STDMETHODCALLTYPE CDefView::SetCurrentViewMode(UINT ViewMode)
2371 {
2372 return E_NOTIMPL;
2373 }
2374
2375 HRESULT STDMETHODCALLTYPE CDefView::GetFolder(REFIID riid, void **ppv)
2376 {
2377 if (pSFParent == NULL)
2378 return E_FAIL;
2379
2380 return pSFParent->QueryInterface(riid, ppv);
2381 }
2382
2383 HRESULT STDMETHODCALLTYPE CDefView::Item(int iItemIndex, LPITEMIDLIST *ppidl)
2384 {
2385 return E_NOTIMPL;
2386 }
2387
2388 HRESULT STDMETHODCALLTYPE CDefView::ItemCount(UINT uFlags, int *pcItems)
2389 {
2390 return E_NOTIMPL;
2391 }
2392
2393 HRESULT STDMETHODCALLTYPE CDefView::Items(UINT uFlags, REFIID riid, void **ppv)
2394 {
2395 return E_NOTIMPL;
2396 }
2397
2398 HRESULT STDMETHODCALLTYPE CDefView::GetSelectionMarkedItem(int *piItem)
2399 {
2400 return E_NOTIMPL;
2401 }
2402
2403 HRESULT STDMETHODCALLTYPE CDefView::GetFocusedItem(int *piItem)
2404 {
2405 return E_NOTIMPL;
2406 }
2407
2408 HRESULT STDMETHODCALLTYPE CDefView::GetItemPosition(LPCITEMIDLIST pidl, POINT *ppt)
2409 {
2410 return E_NOTIMPL;
2411 }
2412
2413 HRESULT STDMETHODCALLTYPE CDefView::GetSpacing(POINT *ppt)
2414 {
2415 return E_NOTIMPL;
2416 }
2417
2418 HRESULT STDMETHODCALLTYPE CDefView::GetDefaultSpacing(POINT *ppt)
2419 {
2420 return E_NOTIMPL;
2421 }
2422
2423 HRESULT STDMETHODCALLTYPE CDefView::GetAutoArrange()
2424 {
2425 return E_NOTIMPL;
2426 }
2427
2428 HRESULT STDMETHODCALLTYPE CDefView::SelectItem(int iItem, DWORD dwFlags)
2429 {
2430 return E_NOTIMPL;
2431 }
2432
2433 HRESULT STDMETHODCALLTYPE CDefView::SelectAndPositionItems(UINT cidl, LPCITEMIDLIST *apidl, POINT *apt, DWORD dwFlags)
2434 {
2435 return E_NOTIMPL;
2436 }
2437
2438 /**********************************************************
2439 * ISVOleCmdTarget_QueryStatus (IOleCommandTarget)
2440 */
2441 HRESULT WINAPI CDefView::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT *pCmdText)
2442 {
2443 FIXME("(%p)->(%p(%s) 0x%08x %p %p\n",
2444 this, pguidCmdGroup, debugstr_guid(pguidCmdGroup), cCmds, prgCmds, pCmdText);
2445
2446 if (!prgCmds)
2447 return E_POINTER;
2448
2449 for (UINT i=0; i < cCmds; i++)
2450 {
2451 FIXME("\tprgCmds[%d].cmdID = %d\n", i, prgCmds[i].cmdID);
2452 prgCmds[i].cmdf = 0;
2453 }
2454
2455 return OLECMDERR_E_UNKNOWNGROUP;
2456 }
2457
2458 /**********************************************************
2459 * ISVOleCmdTarget_Exec (IOleCommandTarget)
2460 *
2461 * nCmdID is the OLECMDID_* enumeration
2462 */
2463 HRESULT WINAPI CDefView::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
2464 {
2465 FIXME("(%p)->(\n\tTarget GUID:%s Command:0x%08x Opt:0x%08x %p %p)\n",
2466 this, debugstr_guid(pguidCmdGroup), nCmdID, nCmdexecopt, pvaIn, pvaOut);
2467
2468 if (IsEqualIID(*pguidCmdGroup, CGID_Explorer) &&
2469 (nCmdID == 0x29) &&
2470 (nCmdexecopt == 4) && pvaOut)
2471 return S_OK;
2472
2473 if (IsEqualIID(*pguidCmdGroup, CGID_ShellDocView) &&
2474 (nCmdID == 9) &&
2475 (nCmdexecopt == 0))
2476 return 1;
2477
2478 return OLECMDERR_E_UNKNOWNGROUP;
2479 }
2480
2481 /**********************************************************
2482 * ISVDropTarget implementation
2483 */
2484
2485 /******************************************************************************
2486 * drag_notify_subitem [Internal]
2487 *
2488 * Figure out the shellfolder object, which is currently under the mouse cursor
2489 * and notify it via the IDropTarget interface.
2490 */
2491
2492 #define SCROLLAREAWIDTH 20
2493
2494 HRESULT CDefView::drag_notify_subitem(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2495 {
2496 LVHITTESTINFO htinfo;
2497 LVITEMW lvItem;
2498 LONG lResult;
2499 HRESULT hr;
2500 RECT clientRect;
2501
2502 /* Map from global to client coordinates and query the index of the listview-item, which is
2503 * currently under the mouse cursor. */
2504 htinfo.pt.x = pt.x;
2505 htinfo.pt.y = pt.y;
2506 htinfo.flags = LVHT_ONITEM;
2507 ::ScreenToClient(hWndList, &htinfo.pt);
2508 lResult = SendMessageW(hWndList, LVM_HITTEST, 0, (LPARAM)&htinfo);
2509
2510 /* Send WM_*SCROLL messages every 250 ms during drag-scrolling */
2511 ::GetClientRect(hWndList, &clientRect);
2512 if (htinfo.pt.x == ptLastMousePos.x && htinfo.pt.y == ptLastMousePos.y &&
2513 (htinfo.pt.x < SCROLLAREAWIDTH || htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH ||
2514 htinfo.pt.y < SCROLLAREAWIDTH || htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH ))
2515 {
2516 cScrollDelay = (cScrollDelay + 1) % 5; /* DragOver is called every 50 ms */
2517 if (cScrollDelay == 0)
2518 {
2519 /* Mouse did hover another 250 ms over the scroll-area */
2520 if (htinfo.pt.x < SCROLLAREAWIDTH)
2521 SendMessageW(hWndList, WM_HSCROLL, SB_LINEUP, 0);
2522
2523 if (htinfo.pt.x > clientRect.right - SCROLLAREAWIDTH)
2524 SendMessageW(hWndList, WM_HSCROLL, SB_LINEDOWN, 0);
2525
2526 if (htinfo.pt.y < SCROLLAREAWIDTH)
2527 SendMessageW(hWndList, WM_VSCROLL, SB_LINEUP, 0);
2528
2529 if (htinfo.pt.y > clientRect.bottom - SCROLLAREAWIDTH)
2530 SendMessageW(hWndList, WM_VSCROLL, SB_LINEDOWN, 0);
2531 }
2532 }
2533 else
2534 {
2535 cScrollDelay = 0; /* Reset, if the cursor is not over the listview's scroll-area */
2536 }
2537
2538 ptLastMousePos = htinfo.pt;
2539
2540 /* If we are still over the previous sub-item, notify it via DragOver and return. */
2541 if (pCurDropTarget && lResult == iDragOverItem)
2542 return pCurDropTarget->DragOver(grfKeyState, pt, pdwEffect);
2543
2544 /* We've left the previous sub-item, notify it via DragLeave and Release it. */
2545 if (pCurDropTarget)
2546 {
2547 pCurDropTarget->DragLeave();
2548 pCurDropTarget.Release();
2549 }
2550
2551 iDragOverItem = lResult;
2552 if (lResult == -1)
2553 {
2554 /* We are not above one of the listview's subitems. Bind to the parent folder's
2555 * DropTarget interface. */
2556 hr = pSFParent->QueryInterface(IID_IDropTarget,
2557 (LPVOID*)&pCurDropTarget);
2558 }
2559 else
2560 {
2561 /* Query the relative PIDL of the shellfolder object represented by the currently
2562 * dragged over listview-item ... */
2563 lvItem.mask = LVIF_PARAM;
2564 lvItem.iItem = lResult;
2565 lvItem.iSubItem = 0;
2566 SendMessageW(hWndList, LVM_GETITEMW, 0, (LPARAM) &lvItem);
2567
2568 /* ... and bind pCurDropTarget to the IDropTarget interface of an UIObject of this object */
2569 hr = pSFParent->GetUIObjectOf(hWndList, 1,
2570 (LPCITEMIDLIST*)&lvItem.lParam, IID_IDropTarget, NULL, (LPVOID*)&pCurDropTarget);
2571 }
2572
2573 /* If anything failed, pCurDropTarget should be NULL now, which ought to be a save state. */
2574 if (FAILED(hr))
2575 return hr;
2576
2577 /* Notify the item just entered via DragEnter. */
2578 return pCurDropTarget->DragEnter(pCurDataObject, grfKeyState, pt, pdwEffect);
2579 }
2580
2581 HRESULT WINAPI CDefView::DragEnter(IDataObject *pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2582 {
2583 /* Get a hold on the data object for later calls to DragEnter on the sub-folders */
2584 pCurDataObject = pDataObject;
2585 pDataObject->AddRef();
2586
2587 return drag_notify_subitem(grfKeyState, pt, pdwEffect);
2588 }
2589
2590 HRESULT WINAPI CDefView::DragOver(DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2591 {
2592 return drag_notify_subitem(grfKeyState, pt, pdwEffect);
2593 }
2594
2595 HRESULT WINAPI CDefView::DragLeave()
2596 {
2597 if (pCurDropTarget)
2598 {
2599 pCurDropTarget->DragLeave();
2600 pCurDropTarget.Release();
2601 }
2602
2603 if (pCurDataObject != NULL)
2604 {
2605 pCurDataObject.Release();
2606 }
2607
2608 iDragOverItem = 0;
2609
2610 return S_OK;
2611 }
2612
2613 HRESULT WINAPI CDefView::Drop(IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
2614 {
2615 if (pCurDropTarget)
2616 {
2617 pCurDropTarget->Drop(pDataObject, grfKeyState, pt, pdwEffect);
2618 pCurDropTarget.Release();
2619 }
2620
2621 pCurDataObject.Release();
2622 iDragOverItem = 0;
2623
2624 return S_OK;
2625 }
2626
2627 /**********************************************************
2628 * ISVDropSource implementation
2629 */
2630
2631 HRESULT WINAPI CDefView::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
2632 {
2633 TRACE("(%p)\n",this);
2634
2635 if (fEscapePressed)
2636 return DRAGDROP_S_CANCEL;
2637 else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON))
2638 return DRAGDROP_S_DROP;
2639 else
2640 return NOERROR;
2641 }
2642
2643 HRESULT WINAPI CDefView::GiveFeedback(DWORD dwEffect)
2644 {
2645 TRACE("(%p)\n",this);
2646
2647 return DRAGDROP_S_USEDEFAULTCURSORS;
2648 }
2649
2650 /**********************************************************
2651 * ISVViewObject implementation
2652 */
2653
2654 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)
2655 {
2656 FIXME("Stub: this=%p\n",this);
2657
2658 return E_NOTIMPL;
2659 }
2660
2661 HRESULT WINAPI CDefView::GetColorSet(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDevice, LOGPALETTE **ppColorSet)
2662 {
2663 FIXME("Stub: this=%p\n",this);
2664
2665 return E_NOTIMPL;
2666 }
2667
2668 HRESULT WINAPI CDefView::Freeze(DWORD dwDrawAspect, LONG lindex, void *pvAspect, DWORD *pdwFreeze)
2669 {
2670 FIXME("Stub: this=%p\n",this);
2671
2672 return E_NOTIMPL;
2673 }
2674
2675 HRESULT WINAPI CDefView::Unfreeze(DWORD dwFreeze)
2676 {
2677 FIXME("Stub: this=%p\n",this);
2678
2679 return E_NOTIMPL;
2680 }
2681
2682 HRESULT WINAPI CDefView::SetAdvise(DWORD aspects, DWORD advf, IAdviseSink *pAdvSink)
2683 {
2684 FIXME("partial stub: %p %08x %08x %p\n", this, aspects, advf, pAdvSink);
2685
2686 /* FIXME: we set the AdviseSink, but never use it to send any advice */
2687 pAdvSink = pAdvSink;
2688 dwAspects = aspects;
2689 dwAdvf = advf;
2690
2691 return S_OK;
2692 }
2693
2694 HRESULT WINAPI CDefView::GetAdvise(DWORD *pAspects, DWORD *pAdvf, IAdviseSink **ppAdvSink)
2695 {
2696 TRACE("this=%p pAspects=%p pAdvf=%p ppAdvSink=%p\n", this, pAspects, pAdvf, ppAdvSink);
2697
2698 if (ppAdvSink)
2699 {
2700 *ppAdvSink = pAdvSink;
2701 pAdvSink.p->AddRef();
2702 }
2703
2704 if (pAspects)
2705 *pAspects = dwAspects;
2706
2707 if (pAdvf)
2708 *pAdvf = dwAdvf;
2709
2710 return S_OK;
2711 }
2712
2713 HRESULT STDMETHODCALLTYPE CDefView::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
2714 {
2715 if (IsEqualIID(guidService, SID_IShellBrowser))
2716 return pShellBrowser->QueryInterface(riid, ppvObject);
2717 return E_NOINTERFACE;
2718 }
2719
2720 /**********************************************************
2721 * IShellView_Constructor
2722 */
2723 HRESULT WINAPI IShellView_Constructor(IShellFolder *pFolder, IShellView **newView)
2724 {
2725 CComObject<CDefView> *theView;
2726 CComPtr<IShellView> result;
2727 HRESULT hResult;
2728
2729 if (newView == NULL)
2730 return E_POINTER;
2731
2732 *newView = NULL;
2733 ATLTRY (theView = new CComObject<CDefView>);
2734
2735 if (theView == NULL)
2736 return E_OUTOFMEMORY;
2737
2738 hResult = theView->QueryInterface (IID_IShellView, (void **)&result);
2739 if (FAILED (hResult))
2740 {
2741 delete theView;
2742 return hResult;
2743 }
2744
2745 hResult = theView->Initialize (pFolder);
2746 if (FAILED (hResult))
2747 return hResult;
2748 *newView = result.Detach ();
2749
2750 return S_OK;
2751 }