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