Нужен быстрый язык программирования, который может управлять двумя принтерами - PullRequest
7 голосов
/ 18 декабря 2010

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

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

Концептуально все хорошо, но зависает довольно часто.Я получил проект в последнюю минуту, потому что оригинальный дизайнер застрял и не смог доставить, поэтому автор выставки спросил меня за день до открытия, могу ли я написать что-нибудь, что будет работать.

Я сделалэто в Word, так как я опытный программист VBA.Несколько других путей, которые я пытался сначала, все приводили в тупик - один не мог делать графику, другой не мог обрабатывать два принтера, а другой не мог менять шрифты и так далее.Проблема в том, что он просто недостаточно быстр - Word может одновременно управлять только одним принтером, а смена активного принтера занимает много времени.Не по офисным стандартам, когда секунда или две задержки до того, как принтер начинает работать с вашим документом, не являются проблемой, но здесь мне нужен более или менее мгновенный ответ.Если дети нажимают кнопку, и ничего не происходит, они нажимают ее снова и снова, пока что-то не происходит, в результате чего может быть отправлено полдюжины команд, прежде чем принтер начнет реагировать.Иногда это полностью блокирует программу, так как мальчики и девочки будут одновременно нажимать на две кнопки, и Word блокируется, и даже когда он не застревает, принтеры выплевывают поток билетов, создавая беспорядок.Дети начинают ссориться из-за чьего билета, вытаскивая их из принтеров, рыча бумажную ленту, заклинивая в принтере и вообще запутываясь в этом деле, часто требуя, чтобы смотрители выставки вынуждены были перезагрузить компьютер и очистить порванные кусочки.распечатайте принтеры.

Мне нужен какой-то быстрый язык программирования, который может работать на двух принтерах * - одновременно - *,не то, чтобы MSOffice не мог переключить активный принтер, который может реагировать на события нажатия левой и правой кнопки мыши, может печатать маленькое графическое изображение и может печатать шрифты с разными размерами и стилями,Мне не нужно много, но это не все в одной гарнитуре.

Может кто-нибудь предложить, что я мог бы использовать для этого?Я даже не знаю, возможно ли это вообще под Windows, является ли мусор «единственным активным принтером» артефактом Office или ограничением Windows.К моему маленькому Commodore-64 двадцать пять лет назад были прикреплены два принтера, и он без проблем работал на обоих одновременно - мне не кажется, что сегодня такое невыполнимое требование.

Ответы [ 6 ]

3 голосов
/ 24 декабря 2010

Будучи самим программистом на Python, я использовал бы что-то вроде MSWinPrint.py и отображал документы напрямую с помощью Python. Похоже, что он поддерживает текст и изображения, и вы можете легко выбрать любой принтер в системе по имени.

Вам потребуется:

  1. Установить Python .
  2. Установка Расширения Python для Windows .
  3. Установить PIL .
  4. Установка MSWinPrint .

Затем вам нужно написать программу для печати. Что-то вроде следующего.

#python
import sys
import Image, ImageWin
import MSWinPrint

# workaround for PIL namespace change
MSWinPrint.ImageWin = ImageWin

def print_name(name, printer_name):
    doc = MSWinPrint.document(printer_name)
    doc.begin_document('nametag for %s' % name)
    # print the name at position 20,20
    text_pos = 20, 20
    doc.text(text_pos, name)
    # add an image for this person
    img_pos = 40, 40
    img_size = 100, 100
    doc.image(img_pos, get_image(), img_size)
    doc.end_document()

def get_image():
    image_filename = 'my image.jpg'
    return Image.open(image_filename)

if __name__ == '__main__':
    name, printer_name = sys.argv[1:]
    print_name(name, printer_name)

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

print_tag.py Sally "EPSON Artisan 810"

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

Конечно, вы можете запускать программу столько раз, сколько захотите, на любом количестве принтеров. Конечно, вы можете сделать больше, чтобы настроить порядок выполнения задания на печать. Вы можете настроить код так, чтобы он всегда запускался и интерпретировал щелчки мыши (для этого вам может понадобиться wxPython), или у вас может быть другая программа, которая просто выполняет скрипт.

2 голосов
/ 24 декабря 2010

Как уже говорили другие, язык программирования не будет иметь большого значения.Однако (и это БОЛЬШОЙ), библиотеки печати, встроенные в большинство языков сценариев, таких как VBA и .NET, либо поддерживают печать только на системный принтер по умолчанию (наиболее распространенный, и не могут быть обойдены, если одновременно открыты два экземпляра)., поскольку системный принтер по умолчанию является глобальным параметром) или требуется настроить глобальную переменную для указания активного принтера (это влияет только на один процесс, поэтому можно обойти его с помощью двух экземпляров).

Вместо этого выпридется вызывать Windows API напрямую.Это, безусловно, позволяет печатать прямо на любом принтере в системе. Вот пример использования принтера по умолчанию. Обратите внимание, что только одна строка кода (вызывающая функцию GetDefaultPrinter) связывает это с принтером по умолчанию.Если указать другое имя принтера для CreateDC, вы получите другой принтер.

Если вы вместо этого вызовете функцию EnumPrinters, вы можете узнать ЛЮБОЕ или ВСЕ имена принтеров, а непросто по умолчанию.Или попросите администратора предварительно настроить имена принтеров для использования в настройках реестра или текстовом файле.

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

Все примеры приведены на C, что делает C ++ очевидным языком для печати на принтерах не по умолчанию, но до тех пор, пока вы знаете, какчтобы вызывать функции WinAPI с вашего языка, вы можете использовать его вместо этого.В VBA это потребует Declare Function XYZ Lib "gdi32" (params here)

1 голос
/ 16 июня 2011

http://www.microplex -usa.com /

http://www.microplex.co.uk/

Эти принтеры для парней имеют собственный контроллер печати, который выполняет функции диспетчера печати. ​​

0 голосов
/ 24 декабря 2010

Пит, ты считал, что принтер совсем другого типа? Команды установки, изменения и sendint PostSCript могут действительно занимать много времени.

Странное решение, как вы его называете, но наш мгновенный черно-белый лазерный принтер DYMO печатает мгновенно при нажатии кнопки. Их программное обеспечение может быть настроено.

Это быстро: при отпускании кнопки возврата, только когда мой палец достиг сантиметра, я уже год IIIIEEEUUUUUUU и примерно на 5 см вверх (через 1 секунду после отпускания клавиши возврата) вся этикетка исчезла. Альберит в черно-белом. Это наклейка.

СТОИМОСТЬ: 100 $ за единицу, включая программное обеспечение для проектирования и настройки соединений с базой данных

Я знаю, что EPSON производит COLOR-лазер, принтеры для моментальной печати. ​​
СТОИМОСТЬ: добавьте несколько нулей , так как они не только дороже, они обычно доставляются большими партиями, например, в парфюмерные магазины, больницы, супермаркеты и т. Д.

Perhaps this solves the speed problem if you do want to keep your Experienced VBA Skills, and change the part that is actually causing the delay. You can ALSO print from Word into this fast printers.

Максимальный размер: 60 мм х 200 мм.

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

Возможно, это приведет вас к новой идее.

0 голосов
/ 21 декабря 2010

Несколько лет назад я написал что-то (в VB6, так что, вероятно, можно было легко перенести его на VBA), чтобы обойти драйвер принтера (принтер должен быть настроен, но фактический используемый драйвер не имеет значения) и отправлял необработанные команды на принтер.В зависимости от того, какой тип принтера вы используете, это может или не может быть проблемой (некоторые используют сложные escape-последовательности).Если вы хотите напечатать графику, это может добавить еще один уровень сложности - хотя это можно сделать, если вы знаете, какие команды поддерживает принтер.Мне удалось распечатать растровые изображения на матричном принтере, но это не было 5-минутной задачей.Если это то, что вас интересует, я могу попробовать выкопать код?

Код выглядит следующим образом:

Public Type DOCINFO
          pDocName As String
          pOutputFile As String
          pDatatype As String
      End Type

Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long

Declare Function EndDocPrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long

Declare Function EndPagePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long

Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, ByVal pDefault As Long) As Long

Declare Function StartDocPrinter Lib "winspool.drv" Alias "StartDocPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pDocInfo As DOCINFO) As Long

Declare Function StartPagePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long

Declare Function WritePrinter Lib "winspool.drv" (ByVal hPrinter As Long, pBuf As Any, ByVal cdBuf As Long, pcWritten As Long) As Long

Public Function PrintRawData(ByVal sPrinter As String, ByVal sDocName As String, ByVal sData As String) As Boolean
On Error GoTo PrintErr:

          Dim lhPrinter As Long, lReturn As Long, lpcWritten As Long
          Dim lDoc As Long, sWrittenData As String
          Dim MyDocInfo As DOCINFO
          Dim pOutput As Printer
          Dim p As Printer

            For Each p In Printers
                If p.DeviceName = sPrinter Then
                    Set pOutput = p
                    GoTo StartPrinting
                End If
            Next p

            MsgBox "Unable to find the specified printer [" & sPrinter & _
            "] in the list of currently installed printers" & vbCrLf & _
            "Printing will be aborted", vbCritical
            Exit Function

StartPrinting:
          lReturn = OpenPrinter(pOutput.DeviceName, lhPrinter, 0)

          If lReturn = 0 Then
              MsgBox "Print was unsuccessful. Make sure there is a printer installed on the port you are trying to print to"
              Exit Function
          End If

          MyDocInfo.pDocName = sDocName
          MyDocInfo.pOutputFile = vbNullString
          MyDocInfo.pDatatype = vbNullString
          lDoc = StartDocPrinter(lhPrinter, 1, MyDocInfo)
          Call StartPagePrinter(lhPrinter)

          sWrittenData = sData

          lReturn = WritePrinter(lhPrinter, ByVal sWrittenData, Len(sWrittenData), lpcWritten)
          lReturn = EndPagePrinter(lhPrinter) 'need this??
          lReturn = EndDocPrinter(lhPrinter)
          lReturn = ClosePrinter(lhPrinter)

          Exit Function

PrintErr:
    MsgBox "Print was unsuccessful. Make sure there is a printer installed on the port you are trying to print to"
    Exit Function

End Function

Чтобы использовать его, вам необходимо установить принтер, который используетисправьте порт, используя любой драйвер (я обычно использую универсальный / текстовый драйвер), а затем вызовите его следующим образом, заменив Hello на данные, которые вы хотите отправить на принтер, включая управляющие символы и т. д .:

PrintRawData "Generic / Text Only", "My Document", "Hello"
0 голосов
/ 18 декабря 2010

Это не проблема с языком программирования, это всего лишь ограничение используемого вами стека принтеров.

Я не уверен, что .NET будет поддерживать его (или Windows в этом отношении) будет поддерживать отправку печати в потоке. Вы можете поместить каждый принтер в свой собственный поток и заблокировать пользовательский интерфейс от принятия большего количества запросов на печать.

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

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