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