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