Windows Forms.NET 2.0: Как нарисовать значок PNG?

Примечание. Вопрос Использование значка 256 x 256 Vista в приложении использует значок "Vista" в качестве значка приложения. Этот вопрос касается ручной покраски значка Vista.

Примечание: Вопрос WinForms.NET 2.0: Как нарисовать значок нужного размера? имеет дело с рисованием значка Vista, загруженного из файла, Этот вопрос касается рисования значка Vista, загружаемого из .resource.


Я включил значок в мой проект Visual Studio, который имеет различные форматы:

  • 16х16
  • 32х32
  • 48х48
  • 256x256 (сжатый PNG)

Теперь вы хотите нарисовать версию 256x256. Ни одна из следующих вещей, которые я пробовал, работает.

Следующее рисует формат 32x32, растянутый до 256x256:

Icon ico = Properties.Resources.TestIconThatHasA256PNGFormat;
e.Graphics.DrawIcon(ico, new Rectangle(0, 0, 256, 256));

Следующее рисует формат 32x32 без растяжек:

Icon ico = Properties.Resources.TestIconThatHasA256PNGFormat;
e.Graphics.DrawIconUnstretched(ico, new Rectangle(0, 0, 256, 256));

Следующее рисует формат 32x32, растянутый до 256x256:

Icon ico = Properties.Resources.TestIconThatHasA256PNGFormat;
e.Graphics.DrawImage(ico.ToBitmap(), new Rectangle(0, 0, 256, 256));

Следующее рисует формат 48x48, растянутый до 256x256:

Icon ico = Properties.Resources.TestIconThatHasA256PNGFormat;
e.Graphics.DrawIcon(
      new Icon(ico, new Size(256, 256)),
      new Rectangle(0, 0, 256, 256));

Как нарисовать значок формата 256x256?


Примечания:

Ответ 1

ResourceManager загружает значок на основе бит, хранящихся в ресурсах. Однако способ обращения с загрузкой не позволит вам получить доступ к значку 256x256 (эта информация не попадает в System.Drawing.Icon, который вы возвращаете).

Мне жаль разочаровывать вас, но единственный способ, который я знаю, - загрузить значок через P/Invoke из LoadImage и работать с файлом (да, я знаю, это не то, что вы мы ищем). Итак, новый вопрос должен быть следующим: как извлечь биты данного ресурса, чтобы я мог хранить их в файле? Я боюсь, что это тоже невозможно, проделав несколько шагов через System.Resources.ResourceReader, поскольку данные ресурсов, похоже, представляют собой набор сериализованных .NET-объектов.

В любом случае, для тех, кто может позволить загрузить значок из файла .ICO(и для себя в качестве будущей справки о том, как загружать значки 256x256), вызовите IconConverter.LoadIcon:

using System.Runtime.InteropServices;

static class IconConverter
{
    public static System.Drawing.Icon LoadIcon(string path, int width, int height)
    {
        System.IntPtr hIcon;
        hIcon = LoadImage (System.IntPtr.Zero, path, IMAGE_ICON, width, height,
                           LR_LOADFROMFILE);
        if (hIcon == System.IntPtr.Zero)
        {
            return null;
        }
        return System.Drawing.Icon.FromHandle (hIcon);
    }

    const int IMAGE_ICON = 1;
    const int LR_LOADFROMFILE = 0x0010;

    [DllImport ("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
    static extern System.IntPtr LoadImage(System.IntPtr hInstance,
                                          string lpszName, uint uType,
                                          int cxDesired, int cyDesired,
                                          uint fuLoad);
}

Когда у вас есть System.Drawing.Icon в ожидаемом размере, просто нарисуйте его с помощью graphics.DrawIconUnstretched.

Ответ 2

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

Ответ 3

Сегодня я сделал очень приятную функцию для извлечения 256x256 растровых изображений из значков Vista​​strong > .

Я использую его для отображения большого значка в виде растрового изображения в поле "О программе".

Эта функция принимает объект Icon как параметр. Таким образом, вы можете использовать его с любыми значками - из ресурсов, из файлов, из потоков и т.д. Он работает на любой ОС, потому что он не использует любой Win32 API, это 100% управляемый код: -)

Bitmap ExtractVistaIcon(Icon icoIcon)

Я разместил здесь свою функцию: ExtractVistaIcon()