📄 browser.c
字号:
{
if( pidl1)
hmemcpy(pidlNew, pidl1, cb1) ;
hmemcpy(((LPSTR)pidlNew) + cb1, pidl2, cb2) ;
}
return pidlNew;
}
LPITEMIDLIST CopyITEMID(LPMALLOC lpMalloc, LPITEMIDLIST lpi)
{
LPITEMIDLIST lpiTemp;
lpiTemp=(LPITEMIDLIST)lpMalloc -> lpVtbl -> Alloc(lpMalloc,
lpi -> mkid.cb+sizeof(lpi -> mkid.cb)) ;
CopyMemory((PVOID)lpiTemp, (CONST VOID *)lpi, lpi -> mkid.cb+sizeof(lpi -> mkid.cb)) ;
return lpiTemp;
}
BOOL GetName(LPSHELLFOLDER lpsf,
LPITEMIDLIST lpi,
DWORD dwFlags,
LPSTR lpFriendlyName)
{
BOOL bSuccess=TRUE;
STRRET str;
if( NOERROR==lpsf -> lpVtbl -> GetDisplayNameOf(lpsf,
lpi,
dwFlags,
&str))
{
switch (str.uType)
{
case STRRET_WSTR:
WideCharToMultiByte(CP_ACP, // CodePage
0, // dwFlags
str.pOleStr, // lpWideCharStr
-1, // cchWideChar
lpFriendlyName, // lpMultiByteStr
sizeof(lpFriendlyName), // cchMultiByte,
NULL, // lpDefaultChar,
NULL) ; // lpUsedDefaultChar
break;
case STRRET_OFFSET:
lstrcpy(lpFriendlyName, (LPSTR)lpi+str.uOffset) ;
break;
case STRRET_CSTR:
lstrcpy(lpFriendlyName, (LPSTR)str.cStr) ;
break;
default:
bSuccess = FALSE;
break;
}
}
else
bSuccess = FALSE;
return bSuccess;
}
LPITEMIDLIST GetFullyQualPidl(LPSHELLFOLDER lpsf, LPITEMIDLIST lpi)
{
char szBuff[MAX_PATH];
OLECHAR szOleChar[MAX_PATH];
LPSHELLFOLDER lpsfDeskTop;
LPITEMIDLIST lpifq;
ULONG ulEaten, ulAttribs;
HRESULT hr;
if( !GetName(lpsf, lpi, SHGDN_FORPARSING, szBuff))
return NULL;
hr=SHGetDesktopFolder(&lpsfDeskTop) ;
if( FAILED(hr))
return NULL;
MultiByteToWideChar(CP_ACP,
MB_PRECOMPOSED,
szBuff,
-1,
szOleChar,
sizeof(szOleChar)) ;
hr=lpsfDeskTop -> lpVtbl -> ParseDisplayName(lpsfDeskTop,
NULL,
NULL,
szOleChar,
&ulEaten,
&lpifq,
&ulAttribs) ;
lpsfDeskTop -> lpVtbl -> Release(lpsfDeskTop) ;
if( FAILED(hr))
return NULL;
return lpifq;
}
HWND CreateTreeView(HWND hwndParent, HINSTANCE hInstance, int iID, DWORD dwStyle)
{
RECT rc; // Client rect of parent
HWND hwnd; // Handle to TreeView
SHFILEINFO sfi;
HIMAGELIST hImageList; // Handle to systemn ImageList.
// This registers the TreeView class.
InitCommonControls() ;
// Get the client area of the parent.
GetClientRect(hwndParent, &rc) ;
// Create the TreeView control.
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, // Ex style
WC_TREEVIEW, // Class
"", // Dummy Text
dwStyle, // Style
0, 0, // Use all of
rc.right/2, rc.bottom, // client area.
hwndParent, // Parent
(HMENU)iID, // ID
hInstance, // Instance
NULL) ; // No extra
// Grab a handle to the system image list, for our icons
hImageList = (HIMAGELIST)SHGetFileInfo((LPCSTR)"C:\\",
0,
&sfi,
sizeof(SHFILEINFO),
SHGFI_SYSICONINDEX | SHGFI_SMALLICON) ;
// Attach ImageList to TreeView
if( hImageList && hwnd)
TreeView_SetImageList(hwnd, hImageList, 0) ;
// Return the window handle
return hwnd;
}
int GetIcon(LPITEMIDLIST lpi, UINT uFlags)
{
SHFILEINFO sfi;
SHGetFileInfo((LPCSTR)lpi,
0,
&sfi,
sizeof(SHFILEINFO),
uFlags) ;
return sfi.iIcon;
}
void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq,
LPTV_ITEM lptvitem)
{
//Note that we don't check the return value here because if GetIcon()
//fails, then we're in big trouble...
lptvitem -> iImage = GetIcon(lpifq, SHGFI_PIDL |
SHGFI_SYSICONINDEX |
SHGFI_SMALLICON) ;
lptvitem -> iSelectedImage = GetIcon(lpifq, SHGFI_PIDL |
SHGFI_SYSICONINDEX |
SHGFI_SMALLICON |
SHGFI_OPENICON) ;
return;
}
void FillTreeView( HWND hwndTreeView,
LPSHELLFOLDER lpsf,
LPITEMIDLIST lpifq,
HTREEITEM hParent)
{
TV_ITEM tvi; // TreeView Item.
TV_INSERTSTRUCT tvins; // TreeView Insert Struct.
HTREEITEM hPrev = NULL; // Previous Item Added.
LPSHELLFOLDER lpsf2=0;
LPENUMIDLIST lpe=0;
LPITEMIDLIST lpi=0, lpiTemp=0, lpifqThisItem;
LPTVITEMDATA lptvid=0;
LPMALLOC lpMalloc=0;
ULONG ulFetched;
UINT uCount=0;
HRESULT hr;
char szBuff[256];
HWND hwnd=GetParent(hwndTreeView) ;
hr=SHGetMalloc(&lpMalloc) ;
if( FAILED(hr))
return;
// Hourglass on!
SetCapture(GetParent(hwndTreeView)) ;
SetCursor(LoadCursor(NULL, IDC_WAIT)) ;
if( SUCCEEDED(hr))
{
hr=lpsf -> lpVtbl -> EnumObjects(lpsf,
hwnd,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
&lpe) ;
if( SUCCEEDED(hr))
{
while (S_OK==lpe -> lpVtbl -> Next(lpe,
1,
&lpi,
&ulFetched))
{
//Create a fully qualified path to the current item
//The SH* shell api's take a fully qualified path pidl,
//(see GetIcon above where I call SHGetFileInfo) whereas the
//interface methods take a relative path pidl.
ULONG ulAttrs = SFGAO_HASSUBFOLDER | SFGAO_FOLDER;
lpsf -> lpVtbl -> GetAttributesOf(lpsf, 1, &lpi, &ulAttrs) ;
if( ulAttrs & (SFGAO_HASSUBFOLDER | SFGAO_FOLDER))
{
//We need this next if statement so that we don't add things like
//the MSN to our tree. MSN is not a folder, but according to the
//shell is has subfolders....
if( ulAttrs & SFGAO_FOLDER)
{
tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE |
TVIF_PARAM;
if( ulAttrs & SFGAO_HASSUBFOLDER)
{
//This item has sub-folders, so let's put the + in the TreeView.
//The first time the user clicks on the item, we'll populate the
//sub-folders then.
tvi.cChildren=1;
tvi.mask |= TVIF_CHILDREN;
}
//OK, let's get some memory for our ITEMDATA struct
lptvid = (LPTVITEMDATA)lpMalloc -> lpVtbl -> Alloc(lpMalloc, sizeof(TVITEMDATA)) ;
if( !lptvid)
goto Done;
//Now get the friendly name that we'll put in the treeview...
if( !GetName(lpsf, lpi, SHGDN_NORMAL, szBuff))
goto Done;
tvi.pszText = szBuff;
tvi.cchTextMax = MAX_PATH;
lpifqThisItem=ConcatPidls(lpifq, lpi) ;
//Now, make a copy of the ITEMIDLIST
lptvid -> lpi=CopyITEMID(lpMalloc, lpi) ;
GetNormalAndSelectedIcons(lpifqThisItem, &tvi) ;
lptvid -> lpsfParent=lpsf; //Store the parent folders SF
lpsf -> lpVtbl -> AddRef(lpsf) ;
//So, you ask, what's the story here? Why to we have 2
//functions that apparently do the same thing? Well,
//ParseDisplayName() (used in GetFullyQualPidl) does not
//work well for non-file system objects such as the My
//Computer and Net Hood. So, since we know that these
//guy will only show up when we are enumerating the root
//of the namespace (as identified by an hParent of TVI_ROOT),
//we special case this here. You *could* use ConcatPidls()
//in ALL cases, but the GetFullyQualPidl() is shown for
//demonstration purposes, since it's the more intuative way.
if( hParent==TVI_ROOT)
lptvid -> lpifq=ConcatPidls(lpifq, lpi) ;
else
lptvid -> lpifq=GetFullyQualPidl(lpsf, lpi) ;
tvi.lParam = (LPARAM)lptvid;
// Populate the TreeVeiw Insert Struct
// The item is the one filled above.
// Insert it after the last item inserted at this level.
// And indicate this is a root entry.
tvins.item = tvi;
tvins.hInsertAfter = hPrev;
tvins.hParent = hParent;
// Add the item to the tree
hPrev = TreeView_InsertItem(hwndTreeView, &tvins) ;
}
lpMalloc -> lpVtbl -> Free(lpMalloc, lpifqThisItem) ;
lpifqThisItem=0;
}
lpMalloc -> lpVtbl -> Free(lpMalloc, lpi) ; //Finally, free the pidl that the shell gave us...
lpi=0;
}
}
}
else
return;
Done:
// Hourglass off!
ReleaseCapture() ;
SetCursor( LoadCursor( NULL, IDC_ARROW)) ;
if( lpe)
lpe -> lpVtbl -> Release( lpe) ;
//The following 2 if statements will only be TRUE if we got here on an
//error condition from the "goto" statement. Otherwise, we free this memory
//at the end of the while loop above.
if( lpi && lpMalloc)
lpMalloc -> lpVtbl -> Free(lpMalloc, lpi) ;
if( lpifqThisItem && lpMalloc)
lpMalloc -> lpVtbl -> Free(lpMalloc, lpifqThisItem) ;
if( lpMalloc)
lpMalloc -> lpVtbl -> Release(lpMalloc) ;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -