using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace Wox.ShellContext
{
public class ShellAPI
{
#region API 导入
public const int MAX_PATH = 260;
public const int S_OK = 0;
public const int S_FALSE = 1;
public const uint CMD_FIRST = 1;
public const uint CMD_LAST = 30000;
public const Int32 MF_BYPOSITION = 0x400;
[DllImport("user32.dll")]
public static extern bool DeleteMenu(IntPtr hMenu, uint uPosition, uint uFlags);
[DllImport("user32.dll")]
public static extern int GetMenuItemCount(IntPtr hMenu);
[DllImport("user32.dll")]
public static extern int GetMenuString(IntPtr hMenu, uint uIDItem, [Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder lpString, int nMaxCount, uint uFlag);
[DllImport("shell32.dll")]
public static extern Int32 SHGetDesktopFolder(out IntPtr ppshf);
[DllImport("Shlwapi.Dll", CharSet = CharSet.Auto)]
public static extern Int32 StrRetToBuf(IntPtr pstr, IntPtr pidl, StringBuilder pszBuf, int cchBuf);
[DllImport("shell32.dll")]
public static extern int SHGetSpecialFolderLocation(IntPtr handle, CSIDL nFolder, out IntPtr ppidl);
[DllImport("shell32",
EntryPoint = "SHGetFileInfo",
ExactSpelling = false,
CharSet = CharSet.Auto,
SetLastError = true)]
public static extern IntPtr SHGetFileInfo(
IntPtr ppidl,
FILE_ATTRIBUTE dwFileAttributes,
ref SHFILEINFO sfi,
int cbFileInfo,
SHGFI uFlags);
[DllImport("user32",
SetLastError = true,
CharSet = CharSet.Auto)]
public static extern IntPtr CreatePopupMenu();
[DllImport("user32.dll",
ExactSpelling = true,
CharSet = CharSet.Auto)]
public static extern uint TrackPopupMenuEx(
IntPtr hmenu,
TPM flags,
int x,
int y,
IntPtr hwnd,
IntPtr lptpm);
#endregion
///
/// 获得桌面 Shell
///
public static IShellFolder GetDesktopFolder(out IntPtr ppshf)
{
SHGetDesktopFolder(out ppshf);
Object obj = Marshal.GetObjectForIUnknown(ppshf);
return (IShellFolder)obj;
}
///
/// 获取显示名称
///
public static string GetNameByIShell(IShellFolder Root, IntPtr pidlSub)
{
IntPtr strr = Marshal.AllocCoTaskMem(MAX_PATH * 2 + 4);
Marshal.WriteInt32(strr, 0, 0);
StringBuilder buf = new StringBuilder(MAX_PATH);
Root.GetDisplayNameOf(pidlSub, SHGNO.INFOLDER, strr);
ShellAPI.StrRetToBuf(strr, pidlSub, buf, MAX_PATH);
return buf.ToString();
}
///
/// 根据 PIDL 获取显示名称
///
public static string GetNameByPIDL(IntPtr pidl)
{
SHFILEINFO info = new SHFILEINFO();
ShellAPI.SHGetFileInfo(pidl, 0, ref info, Marshal.SizeOf(typeof(SHFILEINFO)),
SHGFI.PIDL | SHGFI.DISPLAYNAME | SHGFI.TYPENAME);
return info.szDisplayName;
}
public static PIDLShellFolder GetPIDLAndParentIShellFolder(string path)
{
if (Directory.Exists(path))
{
return GetPIDLAndParentIshellFolderForFolder(path);
}
else if (File.Exists(path))
{
return GetPIDLAndParentIshellFolderForFile(path);
}
return null;
}
private static PIDLShellFolder GetPIDLAndParentIshellFolderForFolder(string folderPath)
{
return null;
}
///
/// Get PIDL and parent shellfolder for given file path
///
///
///
private static PIDLShellFolder GetPIDLAndParentIshellFolderForFile(string filePath)
{
//get desktopPtr first
IntPtr desktopPtr;
IShellFolder desktop = GetDesktopFolder(out desktopPtr);
string fileName = Path.GetFileName(filePath);
IShellFolder parentShellFolder;
string FolderPath = Directory.GetParent(filePath).FullName;
IntPtr Pidl = IntPtr.Zero;
uint i, j = 0;
desktop.ParseDisplayName(IntPtr.Zero, IntPtr.Zero, FolderPath, out i, out Pidl, ref j);
desktop.BindToObject(Pidl, IntPtr.Zero, ref Guids.IID_IShellFolder, out parentShellFolder);
Marshal.ReleaseComObject(desktop);
IEnumIDList fileEnum = null;
IEnumIDList folderEnum = null;
IntPtr fileEnumPtr = IntPtr.Zero;
IntPtr folderEnumPtr = IntPtr.Zero;
IntPtr pidlSub;
int celtFetched;
if (parentShellFolder.EnumObjects(IntPtr.Zero, SHCONTF.NONFOLDERS | SHCONTF.INCLUDEHIDDEN, out folderEnumPtr) == ShellAPI.S_OK)
{
folderEnum = (IEnumIDList)Marshal.GetObjectForIUnknown(folderEnumPtr);
while (folderEnum.Next(1, out pidlSub, out celtFetched) == 0 && celtFetched == ShellAPI.S_FALSE)
{
string name = ShellAPI.GetNameByPIDL(pidlSub);
if (name == fileName)
{
PIDLShellFolder ps = new PIDLShellFolder { PIDL = pidlSub, ShellFolder = parentShellFolder };
Marshal.ReleaseComObject(parentShellFolder);
return ps;
}
}
}
Marshal.ReleaseComObject(parentShellFolder);
return null;
}
}
public class PIDLShellFolder
{
public IShellFolder ShellFolder { get; set; }
public IntPtr PIDL { get; set; }
}
}