【问题标题】:Can I get the icon associated with an installed printer through .Net?我可以通过 .Net 获取与已安装打印机关联的图标吗?
【发布时间】:2011-06-08 12:46:01
【问题描述】:

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

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

InstalledPrinters 只是一个字符串列表。有什么方法可以获取包含名称和图标图像的已安装打印机对象,我通常会在 Windows 资源管理器的“设备和打印机”下看到这些对象?

【问题讨论】:

标签: c# .net windows printing


【解决方案1】:

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

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

【讨论】:

  • 但是,您会查询哪个 *.dll 来获取打印机的图标?我曾尝试查询 System.Printing.dll,它为其提供了 dll 的图标。不是打印机。
  • 要查找的dll是Windows\System32目录下的DDORes.dll。
【解决方案2】:

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

【讨论】:

  • 要枚举 IShellFolder 中的打印机,最好使用 IShellFolder.ParseDisplayName 方法,而不是 EnumObjects,并将打印机名称从 PrinterSettings.IntalledPrinters(例如网络打印机的“\ServerName\PrinterName”)发送到 IShellFolder.ParseDisplayName 参数 pszDisplayName , IShellFolder "设备和打印机" 很好地工作。因此,在此之后,我们可以枚举真实的打印机名称(“\ServerName\PrinterName”)、打印机显示名称(“ServerName 上的打印机名称”作为“设备和打印机”中列出的打印机)和打印机图标。
猜你喜欢
  • 1970-01-01
  • 2015-01-30
  • 2023-04-01
  • 2018-03-12
  • 1970-01-01
  • 2019-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多