Как я могу заставить принтер работать на C в MS VC ++ Express edition? - PullRequest
2 голосов
/ 13 февраля 2010

Я использую VC ++ 2008 Express Edition для C. Когда я пытаюсь запустить это:

/* Demonstrates printer output. */

#include <stdio.h>

main()
{ 
 float f = 2.0134;

 fprintf(stdprn, "This message is printed.\n\n");
 fprintf(stdprn, "And now some numbers:\n\n");
 fprintf(stdprn, "The square of %f is %f.", f, f*f);

 /* Send a form feed */

 fprintf(stdprn, "\f");
}

Я получаю четыре из этих ошибок: ошибка C2065: 'stdprn': необъявленный идентификатор.

На этом форуме они написали, что он работает для определения принтера следующим образом:

FILE *printer;
printer = fopen("PRN", "w");

EDIT Он строит с предупреждением, что fopen небезопасен. При запуске появляется ошибка:

Отладочное утверждение не выполнено. Файл: f: \ dd \ vctools \ crt_bld \ self_x86 \ crt \ src \ fprintf.c Линия: 55

Выражение: (str! = NULL)

Ответы [ 4 ]

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

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

Нет. Это не привело бы к диалогу. Это потому, что вы сбрасываете данные в файл. И не проходя через обходное Win32 API.

Печать не работает, потому что данные не соответствуют PDL - что-то, что принтер может понять. Чтобы печать работала нормально, вам нужно вставить файл PDL с языковыми конструкциями. Это зависит от принтера, для принтера PS вам потребуется вставить фрагмент PostScript, PCL - набор команд PCL, а в случае MXDW вам придется написать разметку описания страницы на основе XML и создать zip-файл. (со всеми вложенными в него ресурсами), т.е. файл XPS для получения правильной распечатки.

Конструкции PDL важны, поскольку в противном случае принтер не знает, куда помещать данные, какой цвет для печати, какую ориентацию использовать, сколько копий для печати и т. Д. И т. Д.

Редактировать: Мне любопытно, почему вы это делаете. Я понимаю, что переносимость - это, вероятно, то, что вы пытаетесь решить. Но помимо этого, я хотел бы знать, что могут быть лучшие альтернативы. Win32 Print Subsytem API - это то, что вам следует искать, если вы пытаетесь печатать программно в Windows с любой степенью точности.

Изменить # 2:

РЕДАКТИРОВАТЬ Это строит с предупреждением, что fopen небезопасно.

Это потому, что MS предлагает вам использовать более безопасные версии fopen_s. См. Улучшения безопасности в CRT .

При запуске появляется ошибка:

Debug Assertion fails. File: f:\dd\vctools\crt_bld\self_x86\crt\src\fprintf.c Line: 55 Expression: (str != NULL)

Это потому, что fopen (возвращаемое значение которого вы не проверяете) возвращает нулевой указатель. Ошибка открытия файла. Кроме того, если это действительно удалось, вызывается соответствующий вызов fclose.

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

Поток stdprn был расширением, предоставленным компиляторами Borland - насколько я знаю, MS никогда его не поддерживал. Что касается использования fopen для открытия устройства принтера, я не думаю, что это будет работать с любыми последними версиями Windows, но есть пара вещей, которые нужно попробовать:

  • используйте PRN: в качестве имени вместо PRN (обратите внимание на двоеточие)
  • попробуйте открыть определенное устройство, используя (например) LPT1: (еще раз, обратите внимание на двоеточие). Это, конечно, не будет работать, если у вас нет подключенного принтера.
  • не зависит от появления диалогового окна принтера - вы на самом деле не используете систему печати WIndows, когда применяете этот подход (и поэтому она, вероятно, не решит вашу проблему, но стоит попробовать).
0 голосов
/ 13 февраля 2010

Вы можете заменить принтер с помощью этой команды на net use, см. Здесь на MSDN kb

NET USE LPT1 \\server_name\printer_name

Существует превосходная глава о печати в DOS с использованием BIOS, да, это немного устарело, но интересно читать только ради ностальгии.

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

HANDLE hFile;

hFile = CreateFile("LPT1", GENERIC_WRITE, 0,NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);

if (hFile == INVALID_HANDLE_VALUE) 
{
// handle error
}

OVERLAPPED ov = {};
ov.hEvent = CreateEvent(0, false, false, 0);

char szData[] = "1234567890";
DWORD p;

if (!WriteFile(hFile,szData, 10, &p, &ov))
{
if (GetLastError() != ERROR_IO_PENDING)
{
// handle error
}
}

// Wait for write op to complete (maximum 3 second)
DWORD dwWait = WaitForSingleObject(ov.hEvent, 3000);
if (dwWait == WAIT_TIMEOUT)
{
// it took more than 3 seconds
} else if (dwWait == WAIT_OBJECT_0)
{
// the write op completed, 
// call GetOverlappedResult(...)
}

CloseHandle(ov.hEvent);
CloseHandle(hFile);

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

FILE *prn = fopen("lpt1", "w");
fprintf(prn, "Hello World\n\f");
fclose(prn);

Надеюсь, это поможет, С наилучшими пожеланиями, Том.

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

В ANSI C нет такого понятия, как stdprn, это было нестандартное расширение, предоставленное некоторыми компиляторами много лет назад. Сегодня для печати вы должны использовать специальные API, предоставляемые на вашей платформе; для печати в Windows необходимо использовать API печати для управления печатью документа и получения DC для принтера и GDI API для фактического рисования на DC.

В UNIX-подобных ОС вместо этого обычно используется CUPS.

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