Как мне перевести этот метод из Winforms в WPF? - PullRequest
4 голосов
/ 13 февраля 2010

У меня есть простая программа, которая создает серию изображений PNG на основе диапазона чисел, т.е. С 1 по 10. Я перебираю каждое число и создаю png-изображение этого числа разных размеров. Ниже приведена пустота, которую я использую для создания изображений.

private void CreatePNG(int number, string location, int width, int height)
        {
            string filename = number.ToString() + "-" + width.ToString() + "x" + height.ToString() + ".png";            
            Bitmap b = new Bitmap(width, height);

            Graphics g = Graphics.FromImage((System.Drawing.Image)b);
            g.FillRectangle(Brushes.White, 0f, 0f, width, height);

            StringFormat f = new StringFormat();
            f.Alignment = StringAlignment.Center;
            f.LineAlignment = StringAlignment.Center;
            g.DrawString(number.ToString(), new Font("Helvetica", 55), Brushes.Black, new RectangleF(0, 0, width, height), f);
            b.Save(location + "\\" + filename, ImageFormat.Png);    
        }

Я хотел бы перевести эту пустоту на работу с WPF. В настоящее время у меня нет опыта работы с WPF, отсюда и мой новый вопрос.

Целевая структура 4,0

Помощь очень ценится.

Ответы [ 2 ]

9 голосов
/ 13 февраля 2010

System.Drawing является частью WinForms НЕ WPF

Сначала я хочу устранить недоразумение.

System.Drawing, основанный на Win32 GDI +, действительно является компонентом WinForms. WPF не построен на нем, Silverlight и другие порты WPF для других платформ, вероятно, никогда не будут включать его, и существует множество несовместимостей между соглашениями, используемыми System.Drawing (WinForms), и соглашениями, используемыми System.Windows.Media (WPF). , Например, они используют разные единицы измерения (пиксели по сравнению с фиксированным 96 dpi), разные типы координат (int или double), разные правила рисования линий, разные повороты, разные кисти, режим немедленного и сохраненного состояния и т. Д.

Библиотеки WPF System.Windows.Media намного мощнее библиотеки System.Drawing (GDI +) WinForms. WPF включает в себя гораздо больше преобразований, улучшенную поддержку непрозрачности, 3D и другие функции, которые позволяют создавать очень сложные эффекты с System.Drawing (GDI +).

Но будет ли код, заданный в вопросе, работать с WPF в любом случае?

Да, будет. Пока вы работаете на WPF, а не на клоне, подобном Silverlight, вы все равно можете получить доступ к старым библиотекам WinForms. Таким образом, вы можете продолжать использовать System.Drawing звонки, чтобы нарисовать свою фигуру. Но вы не можете взять получившийся битовый образ и просто вставить его в свое приложение WPF: битовые карты несовместимы и, как обычно, битовые карты WPF более мощные. Есть способы преобразовать растровое изображение в растровое растровое изображение WPF или сохранить его в стандартном формате, например, .png, и перезагрузить его.

Поскольку код, заданный в вопросе, действительно сохраняет растровое изображение в файл .png, его можно использовать без изменений. Но если при создании растрового изображения требуются какие-либо новые функции WPF или если вы хотите использовать растровое изображение без сохранения в файл, вам понадобятся специальные приемы.

Так почему бы вам не использовать этот код как есть?

Возможно, вы бы: если вы делаете быстрое приложение и уже написали код, и вы действительно все равно хотите сохранить файлы на диске, тогда нет особых причин для преобразования вашего кода в WPF. Но если вы хотите использовать новые функции WPF или включить изображения непосредственно в пользовательский интерфейс WPF, используя привязку данных или другие динамические методы, вы можете преобразовать свою программу для использования библиотек WPF вместо использования WinForms. Это суждение, основанное на ваших потребностях.

В вашем вопросе спрашивалось, что нужно для того, чтобы этот код "работал с WPF". Ответ: ничего. Ваш код записывает обычные файлы .png, WPF читает обычные файлы .png. Так и будет работать.

То же самое можно сказать, если ваш код был написан на языке COBOL, Java или любом другом примитивном языке, который вызывал библиотеку рисования на основе Unix из 90-х. Пока код заканчивает записывать стандартный файл .png (или .gif или .jpg или ...), его вывод будет работать с WPF. Так же, как есть веские причины не оставлять ваш код на COBOL или Java, есть причины не оставлять ваш код с помощью System.Drawing:

  1. Зависимость от System.Drawing, которая со временем может присутствовать или не присутствовать везде, где может использоваться WPF.
  2. Ограничения на то, что вы можете нарисовать
  3. Модель рисования, отличная от остальной части вашего кода WPF

Так как бы я использовал WPF вместо WinForms?

Вы можете сделать растровое изображение из всего, что вы можете отобразить в WPF, используя три простых шага:

  1. Создайте свой WPF Visual с использованием XAML или кода.
  2. В коде создайте RenderTargetBitmap нужного размера, затем вызовите .Render (visual)
  3. Либо используйте полученное растровое изображение в другом месте вашего приложения, либо сохраните его с помощью PngBitmapEncoder или аналогичного.

Для вашего конкретного примера я мог бы использовать DataTemplate следующим образом:

<DataTempate x:Key="NumberTemplate">
  <TextBlock
    Background="White"
    HorizontalAlignment="Center" VerticalAlignment="Center"
    FontFamily="Helvetica" FontSize="55"
    Text="{Binding}"
  />
</DataTemplate>

Тогда ваш фактический код для записи файла будет:

void CreatePng(int number, string location, int width, int height)
{
  WritePng(location + "/" + number + "-" + width + "x" + height + ".png",
           new ContentPresenter  // Invokes a DataTemplate on its content
           {
             Content = number.ToString(),
             Template = NumberTemplate,
             Width = width, Height = height
           });
}

В качестве альтернативы вы можете опустить шаблон и просто создать TextBlock в коде вместо ContentPresenter. Но с помощью шаблона очень легко быстро изменить свой внешний вид и добавить такие необычные вещи, как непрозрачность, градиентные кисти, растровые эффекты и т. Д., Поэтому я бы рекомендовал использовать шаблон, если вы абсолютно не уверены, что ваш внешний вид никогда не изменится.

Метод WritePng () - это стандартный однофреймовый модуль записи файлов .png, который заключает в себе расширенные возможности WPF в простом интерфейсе. Было бы закодировано что-то вроде этого:

void WritePng(string path, UIElement element)
{
  // Create the bitmep specifying the size, pixel format and DPI
  var bitmap = new RenderTargetBitmap((int)element.Width, (int)element.Height,
                                      96, 96, PixelFormats.Pbgra32);
  bitmap.Render(element); // At this point the bitmap is usable within WPF

  // Write to a file:  WPF can write multiple frames but we need only one
  var encoder = new PngBitmapEncoder();
  encoder.Frames.Add(BitmapFrame.Create(bitmap));
  using(Stream stream = File.Create(path))
    encoder.Save(stream);  // Could be any stream, not just a file
}
0 голосов
/ 13 февраля 2010

Я полагаю, что в WPF это будет прекрасно работать. Используется System.Drawing, а не System.Windows.Forms.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...