此任务的 C# 代码:
public static class PrinterIcons
{
public static Dictionary<string, Icon> GetPrintersWithIcons(IntPtr hwndOwner)
{
Dictionary<string, Icon> result = new Dictionary<string, Icon>();
Shell32.IShellFolder iDesktopFolder = Shell32.GetDesktopFolder();
try
{
IntPtr pidlPrintersFolder;
if (Shell32.SHGetFolderLocation(hwndOwner, (int)Shell32.CSIDL.CSIDL_PRINTERS, IntPtr.Zero, 0, out pidlPrintersFolder) == 0)
try
{
StringBuilder strDisplay = new StringBuilder(260);
Guid guidIShellFolder = Shell32.IID_IShellFolder;
IntPtr ptrPrintersShellFolder;
iDesktopFolder.BindToObject(pidlPrintersFolder, IntPtr.Zero, ref guidIShellFolder, out ptrPrintersShellFolder);
Object objPrintersShellFolder = Marshal.GetTypedObjectForIUnknown(ptrPrintersShellFolder, Shell32.ShellFolderType);
try
{
Shell32.IShellFolder printersShellFolder = (Shell32.IShellFolder)objPrintersShellFolder;
IntPtr ptrObjectsList;
printersShellFolder.EnumObjects(hwndOwner, Shell32.ESHCONTF.SHCONTF_NONFOLDERS, out ptrObjectsList);
Object objEnumIDList = Marshal.GetTypedObjectForIUnknown(ptrObjectsList, Shell32.EnumIDListType);
try
{
Shell32.IEnumIDList iEnumIDList = (Shell32.IEnumIDList)objEnumIDList;
IntPtr[] rgelt = new IntPtr[1];
IntPtr pidlPrinter;
int pceltFetched;
Shell32.STRRET ptrString;
while (iEnumIDList.Next(1, rgelt, out pceltFetched) == 0 && pceltFetched == 1)
{
printersShellFolder.GetDisplayNameOf(rgelt[0],
Shell32.ESHGDN.SHGDN_NORMAL, out ptrString);
if (Shell32.StrRetToBuf(ref ptrString, rgelt[0], strDisplay,
(uint)strDisplay.Capacity) == 0)
{
pidlPrinter = Shell32.ILCombine(pidlPrintersFolder, rgelt[0]);
string printerDisplayNameInPrintersFolder = strDisplay.ToString();
Shell32.SHFILEINFO shinfo = new Shell32.SHFILEINFO();
Shell32.SHGetFileInfo(pidlPrinter, 0, out shinfo, (uint)Marshal.SizeOf(shinfo), Shell32.SHGFI.PIDL | Shell32.SHGFI.AddOverlays | Shell32.SHGFI.Icon);
Icon printerIcon = (Icon)Icon.FromHandle(shinfo.hIcon).Clone();
Shell32.DestroyIcon(shinfo.hIcon);
result.Add(printerDisplayNameInPrintersFolder, printerIcon);
}
}
}
finally
{
Marshal.ReleaseComObject(objEnumIDList);
}
}
finally
{
Marshal.ReleaseComObject(objPrintersShellFolder);
}
}
finally
{
Shell32.ILFree(pidlPrintersFolder);
}
}
finally
{
Marshal.ReleaseComObject(iDesktopFolder);
}
return result;
}
}
请注意,结果字典中的打印机名称将是 Printers shell 文件夹中显示的打印机名称,并且它们可以与 PrinterSettings 类中使用的打印机名称不同(例如,Printers shell 文件夹中的网络打印机可以显示为“ on ",而单词 "on" 取决于 windows 本地化,不能是机器网络名称)。我还不知道如何从 IShellFolder 获取“真实”打印机名称以将其与标准 PrinterSettings 类一起使用。
无论如何,此代码会加载打印机系统图标,因此您可以将其用于您的任务。
更新:Shell32 类代码,此代码中使用的代码可在此处找到(答案太大):http://pastebin.com/thJuWx45