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