Можно ли получить значок, связанный с установленным принтером, через .Net? - PullRequest
5 голосов
/ 13 января 2011

Я знаю, как получить список всех установленных принтеров на машине с .Net:

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

InstalledPrinters - это просто список строк. Есть ли способ получить установленные объекты принтера, содержащие как имя, так и изображение значка, которое я обычно вижу в разделе «Устройства и принтеры» в проводнике Windows?

Ответы [ 2 ]

2 голосов
/ 13 января 2011

Значок обычно встраивается либо в один из файлов dll, либо в основной EXE, посмотрите на статические методы System.Drawing.Icon, ссылка ниже для WinForms, она немного отличается от WPF, так как вам нужно создать ImageSourceиз извлеченного потока значков.

Как: извлечь значок, связанный с файлом в Windows Forms

0 голосов
/ 29 сентября 2015

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 (Например, сетевые принтеры в папке оболочки «Принтеры» могут отображаться как «вкл.», а слово «вкл.» зависит от локализации Windows и может быть не сетевым именем машины).Я пока не знаю, как получить «настоящее» имя принтера из IShellFolder, чтобы использовать его со стандартным классом PrinterSettings.

В любом случае, этот код загружает системные значки принтеров, поэтому вы можете использовать его для своей задачи.

Upd: Код класса Shell32, используемый в этом коде, можно найти здесь (слишком большой для ответа): http://pastebin.com/thJuWx45

...