- implemented sorting the listview by clicking on the column header
- implemented the context menu entrys for sorting - some more functions to gather data form pidls
This commit is contained in:
parent
3c216d01eb
commit
e340c707ba
|
@ -6203,6 +6203,25 @@ static LRESULT LISTVIEW_Notify(HWND hwnd, INT nCtrlId, LPNMHDR lpnmh)
|
|||
infoPtr->nItemWidth = LISTVIEW_GetItemWidth(hwnd);
|
||||
InvalidateRect(hwnd, NULL, TRUE);
|
||||
}
|
||||
if(lpnmh->code == HDN_ITEMCLICKA)
|
||||
{
|
||||
/* Handle sorting by Header Column */
|
||||
NMLISTVIEW nmlv;
|
||||
LPNMHEADERA pnmHeader = (LPNMHEADERA) lpnmh;
|
||||
LONG lCtrlId = GetWindowLongA(hwnd, GWL_ID);
|
||||
|
||||
ZeroMemory(&nmlv, sizeof(NMLISTVIEW));
|
||||
nmlv.hdr.hwndFrom = hwnd;
|
||||
nmlv.hdr.idFrom = lCtrlId;
|
||||
nmlv.hdr.code = LVN_COLUMNCLICK;
|
||||
nmlv.iItem = -1;
|
||||
nmlv.iSubItem = pnmHeader->iItem;
|
||||
|
||||
ListView_LVNotify(GetParent(hwnd),lCtrlId, &nmlv);
|
||||
InvalidateRect(hwnd, NULL, TRUE);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "winnls.h"
|
||||
#include "winversion.h"
|
||||
#include "shell32_main.h"
|
||||
#include "shellapi.h"
|
||||
|
||||
#include "pidl.h"
|
||||
#include "wine/undocshell.h"
|
||||
|
@ -1512,36 +1513,79 @@ REFIID WINAPI _ILGetGUIDPointer(LPCITEMIDLIST pidl)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* _ILGetFileDateTime
|
||||
*
|
||||
* Given the ItemIdList, get the FileTime
|
||||
*
|
||||
* PARAMS
|
||||
* pidl [I] The ItemIDList
|
||||
* pFt [I] the resulted FILETIME of the file
|
||||
*
|
||||
* RETURNS
|
||||
* True if Successful
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
*/
|
||||
BOOL _ILGetFileDateTime(LPCITEMIDLIST pidl, FILETIME *pFt)
|
||||
{
|
||||
LPPIDLDATA pdata =_ILGetDataPointer(pidl);
|
||||
|
||||
switch (pdata->type)
|
||||
{
|
||||
case PT_FOLDER:
|
||||
DosDateTimeToFileTime(pdata->u.folder.uFileDate, pdata->u.folder.uFileTime, pFt);
|
||||
break;
|
||||
case PT_VALUE:
|
||||
DosDateTimeToFileTime(pdata->u.file.uFileDate, pdata->u.file.uFileTime, pFt);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL WINAPI _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
|
||||
{ LPPIDLDATA pdata =_ILGetDataPointer(pidl);
|
||||
{
|
||||
FILETIME ft;
|
||||
SYSTEMTIME time;
|
||||
|
||||
switch (pdata->type)
|
||||
{ case PT_FOLDER:
|
||||
DosDateTimeToFileTime(pdata->u.folder.uFileDate, pdata->u.folder.uFileTime, &ft);
|
||||
break;
|
||||
case PT_VALUE:
|
||||
DosDateTimeToFileTime(pdata->u.file.uFileDate, pdata->u.file.uFileTime, &ft);
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
if (! _ILGetFileDateTime( pidl, &ft )) return FALSE;
|
||||
|
||||
FileTimeToSystemTime (&ft, &time);
|
||||
return GetDateFormatA(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&time, NULL, pOut, uOutSize);
|
||||
}
|
||||
|
||||
BOOL WINAPI _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
|
||||
{ LPPIDLDATA pdata =_ILGetDataPointer(pidl);
|
||||
/*************************************************************************
|
||||
* _ILGetFileSize
|
||||
*
|
||||
* Given the ItemIdList, get the FileSize
|
||||
*
|
||||
* PARAMS
|
||||
* pidl [I] The ItemIDList
|
||||
* pOut [I] The buffer to save the result
|
||||
* uOutsize [I] The size of the buffer
|
||||
*
|
||||
* RETURNS
|
||||
* The FileSize
|
||||
*
|
||||
* NOTES
|
||||
* pOut can be null when no string is needed
|
||||
*
|
||||
*/
|
||||
DWORD WINAPI _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
|
||||
{
|
||||
LPPIDLDATA pdata =_ILGetDataPointer(pidl);
|
||||
DWORD dwSize;
|
||||
|
||||
switch (pdata->type)
|
||||
{ case PT_VALUE:
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
dwSize = pdata->u.file.dwFileSize;
|
||||
if (pOut) StrFormatByteSizeA(dwSize, pOut, uOutSize);
|
||||
return dwSize;
|
||||
}
|
||||
StrFormatByteSizeA(pdata->u.file.dwFileSize, pOut, uOutSize);
|
||||
return TRUE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL WINAPI _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
|
||||
|
@ -1570,3 +1614,103 @@ BOOL WINAPI _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* _ILGetFileType
|
||||
*
|
||||
* Given the ItemIdList, get the file type description
|
||||
*
|
||||
* PARAMS
|
||||
* pidl [I] The ItemIDList (simple)
|
||||
* pOut [I] The buffer to save the result
|
||||
* uOutsize [I] The size of the buffer
|
||||
*
|
||||
* RETURNS
|
||||
* nothing
|
||||
*
|
||||
* NOTES
|
||||
* This function copies as much as possible into the buffer.
|
||||
*/
|
||||
void _ILGetFileType(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
|
||||
{
|
||||
if(_ILIsValue(pidl))
|
||||
{
|
||||
char sTemp[64];
|
||||
if (_ILGetExtension (pidl, sTemp, 64))
|
||||
{
|
||||
if (!( HCR_MapTypeToValue(sTemp, sTemp, 64, TRUE)
|
||||
&& HCR_MapTypeToValue(sTemp, pOut, uOutSize, FALSE )))
|
||||
{
|
||||
lstrcpynA (pOut, sTemp, uOutSize - 6);
|
||||
strcat (pOut, "-file");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lstrcpynA(pOut, "Folder", uOutSize);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
* _ILGetAttributeStr
|
||||
*
|
||||
* Given the ItemIdList, get the Attrib string format
|
||||
*
|
||||
* PARAMS
|
||||
* pidl [I] The ItemIDList
|
||||
* pOut [I] The buffer to save the result
|
||||
* uOutsize [I] The size of the Buffer
|
||||
*
|
||||
* RETURNS
|
||||
* True if successful
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
*/
|
||||
BOOL _ILGetAttributeStr(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize)
|
||||
{
|
||||
LPPIDLDATA pData =_ILGetDataPointer(pidl);
|
||||
WORD wAttrib;
|
||||
int i;
|
||||
|
||||
/* Need At Least 6 characters to represent the Attrib String */
|
||||
if(uOutSize < 6)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
switch(pData->type)
|
||||
{
|
||||
case PT_FOLDER:
|
||||
wAttrib = pData->u.folder.uFileAttribs;
|
||||
break;
|
||||
case PT_VALUE:
|
||||
wAttrib = pData->u.file.uFileAttribs;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
i=0;
|
||||
if(wAttrib & FILE_ATTRIBUTE_READONLY)
|
||||
{
|
||||
pOut[i++] = 'R';
|
||||
}
|
||||
if(wAttrib & FILE_ATTRIBUTE_HIDDEN)
|
||||
{
|
||||
pOut[i++] = 'H';
|
||||
}
|
||||
if(wAttrib & FILE_ATTRIBUTE_SYSTEM)
|
||||
{
|
||||
pOut[i++] = 'S';
|
||||
}
|
||||
if(wAttrib & FILE_ATTRIBUTE_ARCHIVE)
|
||||
{
|
||||
pOut[i++] = 'A';
|
||||
}
|
||||
if(wAttrib & FILE_ATTRIBUTE_COMPRESSED)
|
||||
{
|
||||
pOut[i++] = 'C';
|
||||
}
|
||||
pOut[i] = 0x00;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ DWORD WINAPI _ILGetDrive(LPCITEMIDLIST,LPSTR,UINT16);
|
|||
* getting special values from simple pidls
|
||||
*/
|
||||
BOOL WINAPI _ILGetFileDate (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize);
|
||||
BOOL WINAPI _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize);
|
||||
DWORD _ILGetFileSize (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize);
|
||||
BOOL WINAPI _ILGetExtension (LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize);
|
||||
|
||||
|
||||
|
@ -168,4 +168,12 @@ REFIID WINAPI _ILGetGUIDPointer(LPCITEMIDLIST pidl);
|
|||
|
||||
void pdump (LPCITEMIDLIST pidl);
|
||||
BOOL pcheck (LPCITEMIDLIST pidl);
|
||||
|
||||
/*
|
||||
* ItemIDList File helper functions
|
||||
*/
|
||||
void _ILGetFileType(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize);
|
||||
BOOL _ILGetFileDateTime(LPCITEMIDLIST pidl, FILETIME *ft);
|
||||
BOOL _ILGetAttributeStr(LPCITEMIDLIST pidl, LPSTR pOut, UINT uOutSize);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -170,23 +170,7 @@ DWORD WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
|
|||
/* get the type name */
|
||||
if (SUCCEEDED(hr) && (flags & SHGFI_TYPENAME))
|
||||
{
|
||||
if(_ILIsValue(pidlLast))
|
||||
{
|
||||
char sTemp[64];
|
||||
if (_ILGetExtension (pidlLast, sTemp, 64))
|
||||
{
|
||||
if (!( HCR_MapTypeToValue(sTemp, sTemp, 64, TRUE)
|
||||
&& HCR_MapTypeToValue(sTemp, psfi->szTypeName, 80, FALSE )))
|
||||
{
|
||||
lstrcpynA (psfi->szTypeName, sTemp, 74);
|
||||
strcat (psfi->szTypeName, "-file");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(psfi->szTypeName, "Folder");
|
||||
}
|
||||
_ILGetFileType(pidlLast, psfi->szTypeName, 80);
|
||||
}
|
||||
|
||||
/* ### icons ###*/
|
||||
|
|
|
@ -71,6 +71,13 @@ static struct ICOM_VTABLE(IViewObject) vovt;
|
|||
#define _IViewObject_Offset ((int)(&(((IShellViewImpl*)0)->lpvtblViewObject)))
|
||||
#define _ICOM_THIS_From_IViewObject(class, name) class* This = (class*)(((char*)name)-_IViewObject_Offset);
|
||||
|
||||
/* 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)
|
||||
|
@ -314,6 +321,96 @@ static INT CALLBACK ShellView_CompareItems(LPVOID lParam1, LPVOID lParam2, LPARA
|
|||
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
|
||||
*
|
||||
*/
|
||||
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;
|
||||
LPITEMIDLIST pItemIdList2 = (LPITEMIDLIST) lParam2;
|
||||
|
||||
|
||||
bIsFolder1 = _ILIsFolder(pItemIdList1);
|
||||
bIsFolder2 = _ILIsFolder(pItemIdList2);
|
||||
bIsBothFolder = bIsFolder1 && bIsFolder2;
|
||||
|
||||
/* When sorting between a File and a Folder, the Folder gets sorted first */
|
||||
if( (bIsFolder1 || bIsFolder2) && !bIsBothFolder)
|
||||
{
|
||||
nDiff = bIsFolder1 ? -1 : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Sort by Time: Folders or Files can be sorted */
|
||||
|
||||
if(lpData == LISTVIEW_COLUMN_TIME)
|
||||
{
|
||||
_ILGetFileDateTime(pItemIdList1, &fd1);
|
||||
_ILGetFileDateTime(pItemIdList2, &fd2);
|
||||
nDiff = CompareFileTime(&fd2, &fd1);
|
||||
}
|
||||
/* Sort by Attribute: Folder or Files can be sorted */
|
||||
else if(lpData == LISTVIEW_COLUMN_ATTRIB)
|
||||
{
|
||||
_ILGetAttributeStr(pItemIdList1, strName1, MAX_PATH);
|
||||
_ILGetAttributeStr(pItemIdList2, strName2, MAX_PATH);
|
||||
nDiff = strcasecmp(strName1, strName2);
|
||||
}
|
||||
/* Sort by FileName: Folder or Files can be sorted */
|
||||
else if(lpData == LISTVIEW_COLUMN_NAME || bIsBothFolder)
|
||||
{
|
||||
/* Sort by Text */
|
||||
_ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
|
||||
_ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
|
||||
nDiff = strcasecmp(strName1, strName2);
|
||||
}
|
||||
/* Sort by File Size, Only valid for Files */
|
||||
else if(lpData == LISTVIEW_COLUMN_SIZE)
|
||||
{
|
||||
nDiff = _ILGetFileSize(pItemIdList1, NULL, 0) - _ILGetFileSize(pItemIdList2, NULL, 0);
|
||||
}
|
||||
/* Sort by File Type, Only valid for Files */
|
||||
else if(lpData == LISTVIEW_COLUMN_TYPE)
|
||||
{
|
||||
/* Sort by Type */
|
||||
_ILGetFileType(pItemIdList1, strName1, MAX_PATH);
|
||||
_ILGetFileType(pItemIdList2, strName2, MAX_PATH);
|
||||
nDiff = strcasecmp(strName1, strName2);
|
||||
}
|
||||
}
|
||||
/* If the Date, FileSize, FileType, Attrib was the same, sort by FileName */
|
||||
|
||||
if(nDiff == 0)
|
||||
{
|
||||
_ILSimpleGetText(pItemIdList1, strName1, MAX_PATH);
|
||||
_ILSimpleGetText(pItemIdList2, strName2, MAX_PATH);
|
||||
nDiff = strcasecmp(strName1, strName2);
|
||||
}
|
||||
|
||||
return nDiff;
|
||||
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
* ShellView_FillList()
|
||||
*
|
||||
|
@ -812,6 +909,9 @@ static LRESULT ShellView_OnKillFocus(IShellViewImpl * This)
|
|||
|
||||
/**********************************************************
|
||||
* ShellView_OnCommand()
|
||||
*
|
||||
* NOTES
|
||||
* the CmdID's are the ones from the context menu
|
||||
*/
|
||||
static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dwCmd, HWND hwndCmd)
|
||||
{
|
||||
|
@ -839,6 +939,14 @@ static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dw
|
|||
SetStyle (This, LVS_REPORT, LVS_TYPEMASK);
|
||||
break;
|
||||
|
||||
/* the menu-ID's for sorting are 0x30... see shrec.rc */
|
||||
case 0x30:
|
||||
case 0x31:
|
||||
case 0x32:
|
||||
case 0x33:
|
||||
ListView_SortItems(This->hWndList, ShellView_ListViewCompareItems, (LPARAM) (dwCmdID - 0x30));
|
||||
break;
|
||||
|
||||
default:
|
||||
TRACE("-- COMMAND 0x%04lx unhandled\n", dwCmdID);
|
||||
}
|
||||
|
@ -850,7 +958,7 @@ static LRESULT ShellView_OnCommand(IShellViewImpl * This,DWORD dwCmdID, DWORD dw
|
|||
*/
|
||||
|
||||
static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpnmh)
|
||||
{ NM_LISTVIEW *lpnmlv = (NM_LISTVIEW*)lpnmh;
|
||||
{ LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lpnmh;
|
||||
NMLVDISPINFOA *lpdi = (NMLVDISPINFOA *)lpnmh;
|
||||
LPITEMIDLIST pidl;
|
||||
STRRET str;
|
||||
|
@ -888,6 +996,12 @@ static LRESULT ShellView_OnNotify(IShellViewImpl * This, UINT CtlID, LPNMHDR lpn
|
|||
ShellView_DoContextMenu(This, 0, 0, TRUE);
|
||||
break;
|
||||
|
||||
case LVN_COLUMNCLICK:
|
||||
{
|
||||
ListView_SortItems(lpnmlv->hdr.hwndFrom, ShellView_ListViewCompareItems, (LPARAM) (lpnmlv->iSubItem));
|
||||
break;
|
||||
}
|
||||
|
||||
case LVN_GETDISPINFOA:
|
||||
TRACE("-- LVN_GETDISPINFOA %p\n",This);
|
||||
pidl = (LPITEMIDLIST)lpdi->item.lParam;
|
||||
|
|
|
@ -203,6 +203,10 @@ static HRESULT WINAPI ISVBgCm_fnInvokeCommand(
|
|||
case FCIDM_SHVIEW_REPORTVIEW:
|
||||
SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(FCIDM_SHVIEW_REPORTVIEW,0),0 );
|
||||
break;
|
||||
|
||||
default:
|
||||
SendMessageA(hWndSV, WM_COMMAND, MAKEWPARAM(LOWORD(lpcmi->lpVerb), 0),0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue