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