开发者

How can I make the printer work in C in MS VC++ Express edition?

开发者 https://www.devze.com 2022-12-19 21:34 出处:网络
I am using VC++ 2008 express edition for C. When I try to run this: /* Demonstrates printer output. */

I am using VC++ 2008 express edition for C. When I try to run this:

/* 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");
}

I get four of these errors: error C2065: 'stdprn' : undeclared identifier.

On this forum, they wrote that it works to define the printer as follows:

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

EDIT It builds with a warning that fopen is unsafe. When it runs the error appears:

Debug Assertion fails. File: f:\dd\vctools\crt_bld\self_x86\crt\src\fprintf.c Line: 55

Expression: (str != NULL)


The stdprn stream was an extension provided by Borland compilers - as far as I know, MS have never supported it. Regarding the use of fopen to open the printer device, I don't think this will work with any recent versions of Windows, but a couple of things to try:

  • use PRN: as the name instead of PRN (note the colon)
  • try opening the specific device using (for example) LPT1: (once again, note the colon). This will of course not work if you don't have a printer attached.
  • don't depend on a printer dialog coming up - you are not really using the WIndows printing system when you take this approach (and so it probably won't solve your problem, but is worth a try).


I do not have a printer attached, but I do have the Microsoft XPS document writer installed, s it shoulod at least bring up the standard Windows Print dialog from which one can choose the printer.

No. It wouldn't bring up a dialogue. This is because you are flushing data out to a file. And not going through the circuitous Win32 API.

The print doesn't work because the data is not proper PDL -- something that the printer could understand. For the print to work fine, you need to push in a PDL file, with language specific constructs. This varies from printer to printer, a PS printer will need you to push in a PostScript snippet, a PCL -- a PCL command-set and in case of MXDW you will have to write up XML based page description markup and create a zip file (with all resources embedded in it) i.e. an XPS file to get proper printout.

The PDL constructs are important because otherwise the printer doesn't know where to put the data, which color to print it on, what orientation to use, how many copies to print and so on and so forth.

Edit: I am curious why you are doing this. I understand portability is probably something you are trying to address. But apart from that, I'd like to know, there may be better alternatives available. Win32 Print Subsytem APIs are something that you ought to lookup if you are trying to print programmatically on Windows with any degree of fidelity.

Edit#2:

EDIT It builds with a warning that fopen is unsafe.

This is because MS suggests you use the safer versions nowadays fopen_s . See Security Enhancements in the CRT.

When it runs the error appears:

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

This is because fopen (whose return value you do not check) returns a NULL pointer. The file open failed. Also, if it did succeed a matching fclose call is called for.


There's no such thing as stdprn in ANSI C, it was a nonstandard extension provided by some compilers many years ago. Today to print you have to use the specific APIs provided on your platform; to print on Windows you have to use the printing APIs to manage the printing of the document and obtain a DC to the printer and the GDI APIs to perform the actual drawing on the DC.

On UNIX-like OSes, instead, usually CUPS is used.


You can substitute the printer using this command with net use, see here on the MSDN kb

NET USE LPT1 \\server_name\printer_name

There is an excellent chapter on printing in DOS using the BIOS, ok, its a bit antiquated but interesting to read purely for nostalgic sake.

Onto your problem, you may need to use CreateFile to open the LPT1 port, see here for an example, I have it duplicated it here, for your benefit.

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);

But if you insist on opening the LPT1 port directly, error checking is omitted...

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

Hope this helps, Best regards, Tom.

0

精彩评论

暂无评论...
验证码 换一张
取 消