none
Двусторонняя печать RRS feed

  • Вопрос

  • Не могу понять, как настроить 2-стороннюю печать.

    Устанавливаю свойство Duplex, но печать все равно идет постраничная. Может еще что-то надо сделать?

    Заранее спасибо.

    6 ноября 2012 г. 10:17

Ответы

  • Дайте теперь мне немножко ворчливо побрюзжать :)

    Логика работы с PrintDocument следующая:

    0. Создание объекта PrintDocument. Проверка возможности двусторонней печати и установка св-ва PrinterSettings.Duplex в нужное значение.

    1.Подготовка источника данных для печати: в вашем случае чтение картинок из файлов в объекты Image (хотя на данном этапе можно ограничиться просто списком файлов, а непосредственное чтение отложить на потом)

    2. Добавить обработчик события PrintPage для созданного PrintDocument.

    3. В теле обработчика: 

       3.1. реализовать чтение источника данных в ev.Graphics,

       3.2. установить ev.HasMorePages в зависимости от наличия данных в источнике.

    4. Не забыть добавить вызов Print().

    class PrintHelper
    {
       private System.Drawing.Printing.PrintDocument _pd;
    
       // Источник данных
       private Image[] images;
    
       private int index;
    
       // Функция двусторонней печати списка файлов картинок
       public void PrintDoubles(params string[] files)
       {
          _pd = new System.Drawing.Printing.PrintDocument();
    
          // Подготавливаем источник данных
          index = 0;
          images = new Image[files.Length];
          for( int i = 0; i<files.Length; ++i )
          {
             images[i] = Image.FromFile(files[i]);
          }
    
           // Добавляем обработчик события
          _pd.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pd_DoublesPrintPage);
    
          _pd.PrinterSettings.Duplex = System.Drawing.Printing.Duplex.Vertical;
    
          // Печатаем 
          _pd.Print();
       }
    
       // Обработчик события печати
       private void pd_DoublesPrintPage(Object sender, System.Drawing.Printing.PrintPageEventArgs ev)
       {
          // берем данные из источника
          ev.Graphics.DrawImage(images[index], new Point());
    
          // переходим к следующим данным
          index++;
    
          // если данные есть, то true, иначе - false
          ev.HasMorePages = (index != images.Length);
    }
    
    // Использование
    static void Main(string[] args)
    {
       PrintHelper ph = new PrintHelper();
    
       ph.PrintDoubles(@"C:\image1.png", @"C:\image2.png");
    }

    P.S. Если возникнут вопросы перевода кода с C# на VB, спрашивайте.

    P.P.S. Люди тут не на зарплате сидят, поэтому иногда приходится ждать ответа довольно долго, вплоть до того, что самому удается справиться.






    • Изменено tulosba 14 ноября 2012 г. 6:42
    • Помечено в качестве ответа Abolmasov Dmitry 20 ноября 2012 г. 7:03
    14 ноября 2012 г. 6:40

Все ответы

  • Это форум разработчиков. Ваш вопрос лучше задать на форумах Microsoft Answers.
    6 ноября 2012 г. 10:38
    Модератор
  • Так я при разработке приложения WinForms не могу это сделать.

    6 ноября 2012 г. 12:10
  • Так я при разработке приложения WinForms не могу это сделать.

    Тогда укажите какие классы используете, приведите пример кода. Ясновидящих тут нет.
    6 ноября 2012 г. 13:18
  • <ThreadStatic()> Private Shared _pd As Printing.PrintDocument
    
    
    'Автоматическая двухсторонняя печать файлов заявки
    Public Sub PrintDoubles(file as String)
    
    'Часть кода опущена...
    Do
    AddHandler _pd.PrintPage, AddressOf pd_DoublesPrintPage
    
    Dim newImage As Image = Image.FromFile(file)
    
    'Ориентация страницы
    If newImage.Width > newImage.Height Then
      _pd.DefaultPageSettings.Landscape = True
      _pd.PrinterSettings.Duplex = Printing.Duplex.Horizontal
    Else
      _pd.DefaultPageSettings.Landscape = False
      _pd.PrinterSettings.Duplex = Printing.Duplex.Vertical
    End If
    
    _pd.Print()
    Loop
    
    End Sub
    
    
    'Формирование задания для автоматической двухсторонней печати одного файла
    Private Sub pd_DoublesPrintPage(ByVal sender As Object, ByVal ev As Printing.PrintPageEventArgs)
    
    'Часть кода опущена...
    
    ev.Graphics.DrawImage(newImage, 0, 0, wd, hg)
    
    If two <> "A5" Then
      ev.HasMorePages = True
    Else
      ev.HasMorePages = False
    End If
    
    End Sub

    7 ноября 2012 г. 3:57
  • Вы проверяли свойство CanDuplex для PrinterSettings? Может принтер просто не умеет двустороннюю печать.


    7 ноября 2012 г. 6:52
  • Да, конечно. CanDuplex=True

    7 ноября 2012 г. 18:04
  • У вас какая идея вообще: печатать картинку на двух сторонах листа (по половине на каждой)? Мне, кстати, не очень понятно зачем цикл в функции PrintDoubles.
    8 ноября 2012 г. 6:49
  • У вас какая идея вообще: печатать картинку на двух сторонах листа (по половине на каждой)? Мне, кстати, не очень понятно зачем цикл в функции PrintDoubles.
    Поддерживаю вопрос. У вас стоит бесконечный цикл DoLoop и не совсем понятно зачем. опишите все таки задачу по конкретнее.

    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    8 ноября 2012 г. 7:53
    Отвечающий
  • Идея такая: есть список файлов, которые требуется напечатать на лицевой и оборотной стороне листа бумаги (чтобы сэкономить кол-во печатных страниц). Отсюда и цикл Do...Loop в функции PrintDouble (я перебираю все элементы списка). Цикл получился бесконечным, потому что убирая лишние части кода (проверка окончания списка файлов, повтор при разделении по копиям и проч.) слегка увлекся и цикл стал без выхода. Мне важно понять - принципиально я делаю все правильно? Или помимо объявления PrinterSettings.Duplex надо выполнить еще какие-либо действия для запуска двухсторонней печати...

    8 ноября 2012 г. 16:54
  • По идее - ответил выше. По коду - завтра постараюсь вычленить его более точно.
    8 ноября 2012 г. 16:58
  • Private _file As String
    Private _two As String
    Private _conti As Boolean
    Private _lv As New ListView
    'Формирование задания для автоматической двухсторонней печати
    Private Sub pd_DoublesPrintPage(ByVal sender As Object, ByVal ev As Printing.PrintPageEventArgs)
      Dim newImage As Image = Nothing
      'Выбор файла для печати
      If _conti = True Then
        newImage = Image.FromFile(_file)
      Else
        newImage = Image.FromFile(_two)
      End If
      'Печать
      ev.Graphics.DrawImage(newImage, 0, 0)
      If _two <> "A5" Then
        ev.HasMorePages = _conti
        _conti = False
      Else
        ev.HasMorePages = False
      End If
    End Sub
    'Автоматическая двухсторонняя печать файлов заявки
    Public Sub PrintDoubles()
      Dim fil As New Wrk_File
      Dim _index As Integer = 0
      Dim _count As Integer = _lv.Items.Count - 1
      'Перебор всех элементов списка для печати
      Do
       'Проверка существования и задание пути к файлу
        _file = fil.ExistsByID(CLng(_lv.Items(_index).Text))
        _two = "A5"
       'Второй файл
        _conti = True
        If _index < _count Then
          _index = _index + 1
          _two = fil.ExistsByID(CLng(_lv.Items(_index).Text))
        End If
        'Печать файлов
        _pd = New Printing.PrintDocument
        _pd.PrinterSettings.PrinterName = _lv.Items(_index).SubItems(6).Text
        AddHandler _pd.PrintPage, AddressOf pd_DoublesPrintPage
        'Проверка принтера и установка его настроек
        If _pd.PrinterSettings.IsValid = True Then
          Dim newImage As Image = Image.FromFile(_file)
          If newImage.Width > newImage.Height Then
            _pd.DefaultPageSettings.Landscape = True
            _pd.PrinterSettings.Duplex = Printing.Duplex.Horizontal
          Else
            _pd.DefaultPageSettings.Landscape = False
            _pd.PrinterSettings.Duplex = Printing.Duplex.Vertical
          End If
        End If
        _pd.Print()
        'Проверка перехода к следующему элементу списка
        If _index = _count Then
          Exit Do
        Else
          _index = _index + 1
        End If
      Loop
    End Sub
    Теперь код точнее.

    • Изменено Brianteo 10 ноября 2012 г. 18:59
    10 ноября 2012 г. 18:57
  • Жаль, что когда требуется реальный совет, а не ворчливое брюзжание, благородные помощники почему-то исчезают...

    13 ноября 2012 г. 15:07
  • Жаль, что когда требуется реальный совет, а не ворчливое брюзжание, благородные помощники почему-то исчезают...

    Не думаю, что называя отвечающих брюзжащими ворчунами вы ускорите решение проблемы.

    Если решение было бы очевидным его бы вам дали, к тому же не у всех есть под рукой принтер с поддержкой двусторонней печати для проверки вашего кода.

    Вы проверяли двустороннюю печать в пустом проекте, без лишних строчек кода? Взять текста на 2 страницы и отправили на принтер, потому что проблема может быть в приведенном коде, а может во взаимодействии с драйверами принтера.


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    13 ноября 2012 г. 15:29
    Отвечающий
  • Не хотел никого обидеть, но и Вы меня поймите. Вы попросили выложить код (найдя в первом варианте ошибки, не относящиеся к основной теме) и пропали на три дня... Я не прошу Вас проверки кода приложения, ответьте по сути: я правильно все делаю или нет? Меня, например, смущает, что для двухсторонней печати вроде как требуется лишь задание свойства Duplex, которое определяет способ двухсторонней печати (но на мой взгляд, не задает необходимость печати именно с двух сторон). Не нужны ли какие-либо активные действия/метод (чтобы указать, вот именно сейчас печатаем с двух сторон)?

    П.С. Да и конечно воспользуюсь Вашим советом, проверить двухстороннюю печать на пустом проекте.

    • Изменено Brianteo 13 ноября 2012 г. 18:31
    13 ноября 2012 г. 18:30
  • П.С. Да и конечно воспользуюсь Вашим советом, проверить двухстороннюю печать на пустом проекте.

    До того момента могу вас казать, что проверки CanDuplex и задания свойства Duplex достаточно для двусторонней печати. К слову в вашем коде проверки на CanDuplex я не увидел. Ее нужно делать непосредственно перед установкой свойства Duplex, так как принтер может дать отказ приложению непосредственно при настройке печати. Из моего опыта работы в полиграфии могу сказать, что даже крупные и известные программные продукты не всегда хорошо работают с рядом настроек принтеров.


    Женат на WPF. Тайно встречаюсь с WinRT. Не сложилось с C#!

    14 ноября 2012 г. 3:56
    Отвечающий
  • Дайте теперь мне немножко ворчливо побрюзжать :)

    Логика работы с PrintDocument следующая:

    0. Создание объекта PrintDocument. Проверка возможности двусторонней печати и установка св-ва PrinterSettings.Duplex в нужное значение.

    1.Подготовка источника данных для печати: в вашем случае чтение картинок из файлов в объекты Image (хотя на данном этапе можно ограничиться просто списком файлов, а непосредственное чтение отложить на потом)

    2. Добавить обработчик события PrintPage для созданного PrintDocument.

    3. В теле обработчика: 

       3.1. реализовать чтение источника данных в ev.Graphics,

       3.2. установить ev.HasMorePages в зависимости от наличия данных в источнике.

    4. Не забыть добавить вызов Print().

    class PrintHelper
    {
       private System.Drawing.Printing.PrintDocument _pd;
    
       // Источник данных
       private Image[] images;
    
       private int index;
    
       // Функция двусторонней печати списка файлов картинок
       public void PrintDoubles(params string[] files)
       {
          _pd = new System.Drawing.Printing.PrintDocument();
    
          // Подготавливаем источник данных
          index = 0;
          images = new Image[files.Length];
          for( int i = 0; i<files.Length; ++i )
          {
             images[i] = Image.FromFile(files[i]);
          }
    
           // Добавляем обработчик события
          _pd.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(pd_DoublesPrintPage);
    
          _pd.PrinterSettings.Duplex = System.Drawing.Printing.Duplex.Vertical;
    
          // Печатаем 
          _pd.Print();
       }
    
       // Обработчик события печати
       private void pd_DoublesPrintPage(Object sender, System.Drawing.Printing.PrintPageEventArgs ev)
       {
          // берем данные из источника
          ev.Graphics.DrawImage(images[index], new Point());
    
          // переходим к следующим данным
          index++;
    
          // если данные есть, то true, иначе - false
          ev.HasMorePages = (index != images.Length);
    }
    
    // Использование
    static void Main(string[] args)
    {
       PrintHelper ph = new PrintHelper();
    
       ph.PrintDoubles(@"C:\image1.png", @"C:\image2.png");
    }

    P.S. Если возникнут вопросы перевода кода с C# на VB, спрашивайте.

    P.P.S. Люди тут не на зарплате сидят, поэтому иногда приходится ждать ответа довольно долго, вплоть до того, что самому удается справиться.






    • Изменено tulosba 14 ноября 2012 г. 6:42
    • Помечено в качестве ответа Abolmasov Dmitry 20 ноября 2012 г. 7:03
    14 ноября 2012 г. 6:40
  • Спасибо за советы и пример кода! Я выполнил проверку на домашнем принтере - все заработало. Осталось теперь проверить печать в боевых условиях.

    Однако попутно возник вопрос со свойством DefaultPageSettings.Landscape для второго файла. Как его правильно задать?

    14 ноября 2012 г. 17:37
  • Однако попутно возник вопрос со свойством DefaultPageSettings.Landscape для второго файла. Как его правильно задать?

    Посмотрите, вроде бы это то, что Вам надо.
    15 ноября 2012 г. 6:37