我可以通过.Net获取与已安装打印机关联的图标吗?

时间:2011-01-13 14:08:16

标签: c# .net windows printing

我知道如何使用.Net获取所有已安装打印机的列表:

foreach (String printer in PrinterSettings.InstalledPrinters)
{        
    Console.WriteLine(printer.ToString());
}
Console.ReadLine();

InstalledPrinters只是一个字符串列表。有没有办法让安装的打印机对象包含我通常在Windows资源管理器中的“设备和打印机”下看到的名称和图标图像?

2 个答案:

答案 0 :(得分:2)

图标通常嵌入到其中一个dll文件或主EXE中,查看System.Drawing.Icon静态方法,下面的链接用于WinForms,它与WPF略有不同,因为你必须创建一个ImageSource来自提取的图标流。

How to: Extract the Icon Associated with a File in Windows Forms

答案 1 :(得分:0)

此任务的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;
    }
}

请注意,结果字典中的打印机名称将是打印机外壳文件夹中显示的打印机名称,它们可能与PrinterSettings类中使用的打印机名称不同(例如,Printers shell文件夹中的网络打印机可以显示为&# 34; on&#34;和word&#34; on&#34;取决于Windows本地化,可能不是机器网络名称)。我不知道如何获得真实的&#34; IShellFolder中的打印机名称,用于标准的PrinterSettings类。

无论如何,此代码会加载打印机系统图标,因此您可以将它用于任务。

Upd:此代码中使用的Shell32类代码可以在这里找到(对于答案来说太大了):http://pastebin.com/thJuWx45