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