📄 shlview.c
字号:
/*
* ShellView
*
* Copyright 1998,1999 <juergen.schmied@debitel.net>
*
* This is the view visualizing the data provied by the shellfolder.
* No direct access to data from pidls should be done from here.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
* FIXME: The order by part of the background context menu should be
* buily according to the columns shown.
*
* FIXME: Load/Save the view state from/into the stream provied by
* the ShellBrowser
*
* FIXME: CheckToolbar: handle the "new folder" and "folder up" button
*
* FIXME: ShellView_FillList: consider sort orders
*
* FIXME: implement the drag and drop in the old (msg-based) way
*
* FIXME: when the ShellView_WndProc gets a WM_NCDESTROY should we do a
* Release() ???
*/
#include "config.h"
#include "wine/port.h"
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winerror.h"
#include "winbase.h"
#include "winnls.h"
#include "objbase.h"
#include "servprov.h"
#include "shlguid.h"
#include "wingdi.h"
#include "winuser.h"
#include "shlobj.h"
#include "undocshell.h"
#include "shresdef.h"
#include "wine/debug.h"
#include "docobj.h"
#include "pidl.h"
#include "shell32_main.h"
#include "shellfolder.h"
WINE_DEFAULT_DEBUG_CHANNEL(shell);
typedef struct
{ BOOL bIsAscending;
INT nHeaderID;
INT nLastHeaderID;
}LISTVIEW_SORT_INFO, *LPLISTVIEW_SORT_INFO;
typedef struct
{
const IShellViewVtbl* lpVtbl;
LONG ref;
const IOleCommandTargetVtbl* lpvtblOleCommandTarget;
const IDropTargetVtbl* lpvtblDropTarget;
const IDropSourceVtbl* lpvtblDropSource;
const IViewObjectVtbl* lpvtblViewObject;
IShellFolder* pSFParent;
IShellFolder2* pSF2Parent;
IShellBrowser* pShellBrowser;
ICommDlgBrowser* pCommDlgBrowser;
HWND hWnd; /* SHELLDLL_DefView */
HWND hWndList; /* ListView control */
HWND hWndParent;
FOLDERSETTINGS FolderSettings;
HMENU hMenu;
UINT uState;
UINT cidl;
LPITEMIDLIST *apidl;
LISTVIEW_SORT_INFO ListViewSortInfo;
ULONG hNotify; /* change notification handle */
HANDLE hAccel;
DWORD dwAspects;
DWORD dwAdvf;
IAdviseSink *pAdvSink;
IDropTarget* pCurDropTarget; /* The sub-item, which is currently dragged over */
IDataObject* pCurDataObject; /* The dragged data-object */
LONG iDragOverItem; /* Dragged over item's index, iff pCurDropTarget != NULL */
UINT cScrollDelay; /* Send a WM_*SCROLL msg every 250 ms during drag-scroll */
POINT ptLastMousePos; /* Mouse position at last DragOver call */
} IShellViewImpl;
static const IShellViewVtbl svvt;
static const IOleCommandTargetVtbl ctvt;
static const IDropTargetVtbl dtvt;
static const IDropSourceVtbl dsvt;
static const IViewObjectVtbl vovt;
static inline IShellViewImpl *impl_from_IOleCommandTarget( IOleCommandTarget *iface )
{
return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblOleCommandTarget));
}
static inline IShellViewImpl *impl_from_IDropTarget( IDropTarget *iface )
{
return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropTarget));
}
static inline IShellViewImpl *impl_from_IDropSource( IDropSource *iface )
{
return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblDropSource));
}
static inline IShellViewImpl *impl_from_IViewObject( IViewObject *iface )
{
return (IShellViewImpl *)((char*)iface - FIELD_OFFSET(IShellViewImpl, lpvtblViewObject));
}
/* ListView Header ID's */
#define LISTVIEW_COLUMN_NAME 0
#define LISTVIEW_COLUMN_SIZE 1
#define LISTVIEW_COLUMN_TYPE 2
#define LISTVIEW_COLUMN_TIME 3
#define LISTVIEW_COLUMN_ATTRIB 4
/*menu items */
#define IDM_VIEW_FILES (FCIDM_SHVIEWFIRST + 0x500)
#define IDM_VIEW_IDW (FCIDM_SHVIEWFIRST + 0x501)
#define IDM_MYFILEITEM (FCIDM_SHVIEWFIRST + 0x502)
#define ID_LISTVIEW 1
#define SHV_CHANGE_NOTIFY WM_USER + 0x1111
/*windowsx.h */
#define GET_WM_COMMAND_ID(wp, lp) LOWORD(wp)
#define GET_WM_COMMAND_HWND(wp, lp) (HWND)(lp)
#define GET_WM_COMMAND_CMD(wp, lp) HIWORD(wp)
/*
Items merged into the toolbar and the filemenu
*/
typedef struct
{ int idCommand;
int iImage;
int idButtonString;
int idMenuString;
BYTE bState;
BYTE bStyle;
} MYTOOLINFO, *LPMYTOOLINFO;
static const MYTOOLINFO Tools[] =
{
{ FCIDM_SHVIEW_BIGICON, 0, 0, IDS_VIEW_LARGE, TBSTATE_ENABLED, BTNS_BUTTON },
{ FCIDM_SHVIEW_SMALLICON, 0, 0, IDS_VIEW_SMALL, TBSTATE_ENABLED, BTNS_BUTTON },
{ FCIDM_SHVIEW_LISTVIEW, 0, 0, IDS_VIEW_LIST, TBSTATE_ENABLED, BTNS_BUTTON },
{ FCIDM_SHVIEW_REPORTVIEW, 0, 0, IDS_VIEW_DETAILS, TBSTATE_ENABLED, BTNS_BUTTON },
{ -1, 0, 0, 0, 0, 0}
};
typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
/**********************************************************
* IShellView_Constructor
*/
IShellView * IShellView_Constructor( IShellFolder * pFolder)
{ IShellViewImpl * sv;
sv=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IShellViewImpl));
sv->ref=1;
sv->lpVtbl=&svvt;
sv->lpvtblOleCommandTarget=&ctvt;
sv->lpvtblDropTarget=&dtvt;
sv->lpvtblDropSource=&dsvt;
sv->lpvtblViewObject=&vovt;
sv->pSFParent = pFolder;
if(pFolder) IShellFolder_AddRef(pFolder);
IShellFolder_QueryInterface(sv->pSFParent, &IID_IShellFolder2, (LPVOID*)&sv->pSF2Parent);
sv->pCurDropTarget = NULL;
sv->pCurDataObject = NULL;
sv->iDragOverItem = 0;
sv->cScrollDelay = 0;
sv->ptLastMousePos.x = 0;
sv->ptLastMousePos.y = 0;
TRACE("(%p)->(%p)\n",sv, pFolder);
return (IShellView *) sv;
}
/**********************************************************
*
* ##### helperfunctions for communication with ICommDlgBrowser #####
*/
static BOOL IsInCommDlg(IShellViewImpl * This)
{ return(This->pCommDlgBrowser != NULL);
}
static HRESULT IncludeObject(IShellViewImpl * This, LPCITEMIDLIST pidl)
{
HRESULT ret = S_OK;
if ( IsInCommDlg(This) )
{
TRACE("ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
ret = ICommDlgBrowser_IncludeObject(This->pCommDlgBrowser, (IShellView*)This, pidl);
TRACE("--0x%08x\n", ret);
}
return ret;
}
static HRESULT OnDefaultCommand(IShellViewImpl * This)
{
HRESULT ret = S_FALSE;
if (IsInCommDlg(This))
{
TRACE("ICommDlgBrowser::OnDefaultCommand\n");
ret = ICommDlgBrowser_OnDefaultCommand(This->pCommDlgBrowser, (IShellView*)This);
TRACE("-- returns %08x\n", ret);
}
return ret;
}
static HRESULT OnStateChange(IShellViewImpl * This, UINT uFlags)
{
HRESULT ret = S_FALSE;
if (IsInCommDlg(This))
{
TRACE("ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
ret = ICommDlgBrowser_OnStateChange(This->pCommDlgBrowser, (IShellView*)This, uFlags);
TRACE("--\n");
}
return ret;
}
/**********************************************************
* set the toolbar of the filedialog buttons
*
* - activates the buttons from the shellbrowser according to
* the view state
*/
static void CheckToolbar(IShellViewImpl * This)
{
LRESULT result;
TRACE("\n");
if (IsInCommDlg(This))
{
IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
FCIDM_TB_SMALLICON, (This->FolderSettings.ViewMode==FVM_LIST)? TRUE : FALSE, &result);
IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_CHECKBUTTON,
FCIDM_TB_REPORTVIEW, (This->FolderSettings.ViewMode==FVM_DETAILS)? TRUE : FALSE, &result);
IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
FCIDM_TB_SMALLICON, TRUE, &result);
IShellBrowser_SendControlMsg(This->pShellBrowser, FCW_TOOLBAR, TB_ENABLEBUTTON,
FCIDM_TB_REPORTVIEW, TRUE, &result);
}
}
/**********************************************************
*
* ##### helperfunctions for initializing the view #####
*/
/**********************************************************
* change the style of the listview control
*/
static void SetStyle(IShellViewImpl * This, DWORD dwAdd, DWORD dwRemove)
{
DWORD tmpstyle;
TRACE("(%p)\n", This);
tmpstyle = GetWindowLongA(This->hWndList, GWL_STYLE);
SetWindowLongA(This->hWndList, GWL_STYLE, dwAdd | (tmpstyle & ~dwRemove));
}
/**********************************************************
* ShellView_CreateList()
*
* - creates the list view window
*/
static BOOL ShellView_CreateList (IShellViewImpl * This)
{ DWORD dwStyle, dwExStyle;
TRACE("%p\n",This);
dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
LVS_SHAREIMAGELISTS | LVS_EDITLABELS | LVS_ALIGNLEFT | LVS_AUTOARRANGE;
dwExStyle = WS_EX_CLIENTEDGE;
switch (This->FolderSettings.ViewMode)
{
case FVM_ICON: dwStyle |= LVS_ICON; break;
case FVM_DETAILS: dwStyle |= LVS_REPORT; break;
case FVM_SMALLICON: dwStyle |= LVS_SMALLICON; break;
case FVM_LIST: dwStyle |= LVS_LIST; break;
default: dwStyle |= LVS_LIST; break;
}
if (This->FolderSettings.fFlags & FWF_AUTOARRANGE) dwStyle |= LVS_AUTOARRANGE;
if (This->FolderSettings.fFlags & FWF_DESKTOP)
This->FolderSettings.fFlags |= FWF_NOCLIENTEDGE | FWF_NOSCROLL;
if (This->FolderSettings.fFlags & FWF_SINGLESEL) dwStyle |= LVS_SINGLESEL;
if (This->FolderSettings.fFlags & FWF_NOCLIENTEDGE)
dwExStyle &= ~WS_EX_CLIENTEDGE;
This->hWndList=CreateWindowExA( dwExStyle,
WC_LISTVIEWA,
NULL,
dwStyle,
0,0,0,0,
This->hWnd,
(HMENU)ID_LISTVIEW,
shell32_hInstance,
NULL);
if(!This->hWndList)
return FALSE;
This->ListViewSortInfo.bIsAscending = TRUE;
This->ListViewSortInfo.nHeaderID = -1;
This->ListViewSortInfo.nLastHeaderID = -1;
if (This->FolderSettings.fFlags & FWF_DESKTOP) {
/*
* FIXME: look at the registry value
* HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow
* and activate drop shadows if necessary
*/
if (0)
SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, CLR_NONE);
else
SendMessageW(This->hWndList, LVM_SETTEXTBKCOLOR, 0, GetSysColor(COLOR_DESKTOP));
SendMessageW(This->hWndList, LVM_SETTEXTCOLOR, 0, RGB(255,255,255));
}
/* UpdateShellSettings(); */
return TRUE;
}
/**********************************************************
* ShellView_InitList()
*
* - adds all needed columns to the shellview
*/
static BOOL ShellView_InitList(IShellViewImpl * This)
{
LVCOLUMNW lvColumn;
SHELLDETAILS sd;
int i;
WCHAR szTemp[50];
TRACE("%p\n",This);
SendMessageW(This->hWndList, LVM_DELETEALLITEMS, 0, 0);
lvColumn.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
lvColumn.pszText = szTemp;
if (This->pSF2Parent)
{
for (i=0; 1; i++)
{
if (!SUCCEEDED(IShellFolder2_GetDetailsOf(This->pSF2Parent, NULL, i, &sd)))
break;
lvColumn.fmt = sd.fmt;
lvColumn.cx = sd.cxChar*8; /* chars->pixel */
StrRetToStrNW( szTemp, 50, &sd.str, NULL);
SendMessageW(This->hWndList, LVM_INSERTCOLUMNW, i, (LPARAM) &lvColumn);
}
}
else
{
FIXME("no SF2\n");
}
SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_SMALL, (LPARAM)ShellSmallIconList);
SendMessageW(This->hWndList, LVM_SETIMAGELIST, LVSIL_NORMAL, (LPARAM)ShellBigIconList);
return TRUE;
}
/**********************************************************
* ShellView_CompareItems()
*
* NOTES
* internal, CALLBACK for DSA_Sort
*/
static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
{
int ret;
TRACE("pidl1=%p pidl2=%p lpsf=%p\n", lParam1, lParam2, (LPVOID) lpData);
if(!lpData) return 0;
ret = (SHORT) SCODE_CODE(IShellFolder_CompareIDs((LPSHELLFOLDER)lpData, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2));
TRACE("ret=%i\n",ret);
return ret;
}
/*************************************************************************
* ShellView_ListViewCompareItems
*
* Compare Function for the Listview (FileOpen Dialog)
*
* PARAMS
* lParam1 [I] the first ItemIdList to compare with
* lParam2 [I] the second ItemIdList to compare with
* lpData [I] The column ID for the header Ctrl to process
*
* RETURNS
* A negative value if the first item should precede the second,
* a positive value if the first item should follow the second,
* or zero if the two items are equivalent
*
* NOTES
* FIXME: function does what ShellView_CompareItems is supposed to do.
* unify it and figure out how to use the undocumented first parameter
* of IShellFolder_CompareIDs to do the job this function does and
* move this code to IShellFolder.
* make LISTVIEW_SORT_INFO obsolete
* the way this function works is only usable if we had only
* filesystemfolders (25/10/99 jsch)
*/
static INT CALLBACK ShellView_ListViewCompareItems(LPVOID lParam1, LPVOID lParam2, LPARAM lpData)
{
INT nDiff=0;
FILETIME fd1, fd2;
char strName1[MAX_PATH], strName2[MAX_PATH];
BOOL bIsFolder1, bIsFolder2,bIsBothFolder;
LPITEMIDLIST pItemIdList1 = (LPITEMIDLIST) lParam1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -