Printing directly to specialized LPT1: device in VB.NET

  • Thread starter Thread starter Tom
  • Start date Start date
T

Tom

I am converting an old application that was printing directly to a
specialized printer device (i.e. a special label printer). It was doing this
by opening a file with the file path of 'LPT1:' and then using PRINT # to
print directly to the printer device.

Obviously, this is not going to work under VB.NET - StreamWriter won't let
you open a device like LPT1: and such. I assume I am going to have to switch
to the System.Drawing.Printing namespace to do this? And if so, is this
going to work the same way? (i.e. this printer needs special codes and such
sent to it - which my code does, but it is not a general-purpose printer).
Or is there another way to do it? And, since the users default printer may
NOT be the LPT1: device (i.e. their default printer would probably be a
network printer, with the label printer as a locally attached printer), how
do I specify that I want it to print on the printer that is connected to
LPT1:?

Thanks in advance.

Tom
 
Chris: Yep, I saw that in another message after I sent my previous post.

Now my question is: Using the example to print raw data - do you know if you
can use a printer name like "LPT1:"? Or do you -HAVE- to use a specific
Windows driver/printer name?

Tom

Chris Podmore said:
Tom,

I don't know if this will help but Herfried posted the following link in a
topic with the subject 'Sending Control characters to a POS printer'.
 
Tom,

I'm not sure about talking directly to LPT1:, looking at the code it looks like it has to go through the printer driver. If you want to talk directly to LPT1: instead of the printer driver, I'm not sure how you would do that.

I did a quick search about talking to DOS devices but couldn't find anything. Sorry I wasn't much help, I hop you find an answer.

Chris.
 
Hi,

Perhaps a better solution would be to download my IONET IO control for .NET.
It is free, and permits both reading and writing to standard IO ports
(including the printer port, of course).

Dick

--
Richard Grier (Microsoft Visual Basic MVP)

See www.hardandsoftware.net for contact information.

Author of Visual Basic Programmer's Guide to Serial Communications, 3rd
Edition ISBN 1-890422-27-4 (391 pages) published February 2002.
 
Tom said:
I am converting an old application that was printing directly to a
specialized printer device (i.e. a special label printer). It was doing this
by opening a file with the file path of 'LPT1:' and then using PRINT # to
print directly to the printer device.

Obviously, this is not going to work under VB.NET - StreamWriter won't let
you open a device like LPT1: and such. I assume I am going to have to switch
to the System.Drawing.Printing namespace to do this? And if so, is this
going to work the same way? (i.e. this printer needs special codes and such
sent to it - which my code does, but it is not a general-purpose printer).
Or is there another way to do it? And, since the users default printer may
NOT be the LPT1: device (i.e. their default printer would probably be a
network printer, with the label printer as a locally attached printer), how
do I specify that I want it to print on the printer that is connected to
LPT1:?

Thanks in advance.

Tom

Hi Tom,

I'm just visiting this NG for the first time and I'm not yet a VS .NET
developer, but this is soon to change ;-)

At the moment I develop in CA-Visual Objects and have an app which, by
using several of the WinAPI functions, does some of what you need -
here is the CA-VO code to print to an UBI label-printer. The really
useful stuff is the bit entitled "Print this page" - here, the WinAPI
functions OpenPrinter, StartDocPrinter, WritePrinter, EndDocPrinter
and ClosePrinter are being used to send raw data to (in this case) a
printer attached locally to LPT1, and which has been assigned a name
via the Windows Printer setup Assistant.

If you don't wish to have to use such a name, but instead send raw
data to the port LPT1, I believe (but I haven't tried it!) that you
could use the winAPI function SetPrinter(hPrinter, dwLevel, pPrinter,
dwCommand), where the second argument (dwLevel) specifies the type of
data contained in the pPrinter argument. pPrinter is a pointer to an
array that contains one of the PRINTER_INFO_X structures, where X can
be one of 2, 3, 4, 5 or 6. Now, if dwLevel is equal to 2 (OK for Win
95 and NT+2K+XP), then the pPrinter array contains a PRINTER_INFO_2
structure and this structure contains a member pPortName, which is a
pointer to a null-terminated string that identifies the port (LPT1,
LPT2, etc.) used to transmit data to the printer. See, eg.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/prntspol_13ua.asp
for more info.

HTH, Robertino


CLASS WELabel_WAPI

PROTECT oOwner AS USUAL
PROTECT aWELData AS ARRAY

PROTECT cBkgCmd, cDataCmd AS STRING


METHOD Init(oOwner, aWELData) CLASS WELabel_WAPI

SELF:oOwner := oOwner
SELF:aWELData := aWELData


RETURN SELF

METHOD Print() CLASS WELabel_WAPI
LOCAL lResult AS LOGIC
LOCAL hPrinter AS PTR
LOCAL pszPrinter AS PSZ
LOCAL pBuffer AS PTR
LOCAL dwWritten AS DWORD
LOCAL pDocInfo IS _winDoc_Info_1
LOCAL cCmdString, cEinh AS STRING
LOCAL nTotalMenge, nPerPack, nInThisPack, nDiv AS FLOAT
LOCAL nLabelCount, nTotalLabels AS DWORD
LOCAL lHasSerNums AS LOGIC


lResult := FALSE
nTotalMenge := SELF:aWELData[4]
nPerPack := SELF:aWELData[5]
lHasSerNums := !Empty(SELF:aWELData[6])


// For fractional quantities (not actually needed!!)....
IF (cEinh $ "stkpcsea") // "st", "stk", "pc", "pcs", "ea".......
IF (((nTotalMenge - Floor(nTotalMenge)) != 0) .or. ((nPerPack -
Floor(nPerPack)) != 0))
// Do nothing...
ELSE
// ...ditto...
ENDIF
ELSE
ENDIF



nDiv := FLOAT(nTotalMenge) / FLOAT(nPerPack)
nTotalLabels := Ceil(nDiv)
//TEXTbox{SELF:oOwner, , "nTotalLabels = " +
NTrim(nTotalLabels)}:Show()

nLabelCount := 0
//nTotalLabels := 1 // Test...
DO WHILE (nLabelCount < nTotalLabels)
nLabelCount ++

IF (nTotalMenge >= nPerPack)
nInThisPack := nPerPack
ELSE
nInThisPack := nTotalMenge
ENDIF
nTotalMenge -= nInThisPack
//textbox{, , "nInThisPack = " + NTrim(nInThisPack)}:Show()

SELF:SetupFormBackground(nTotalLabels, nLabelCount)
SELF:SetupFormData(nInThisPack, nLabelCount)
cCmdString := SELF:cBkgCmd + SELF:cDataCmd


// Print this page.......
pszPrinter := StringAlloc(VL_PRINTER_NAME + _chr(0))
IF OpenPrinter(pszPrinter, @hPrinter, NULL)

pBuffer := StringAlloc(cCmdString + _chr(0))
pDocInfo.pDocName := String2Psz("Versand-Label")

IF StartDocPrinter(hPrinter, 1, @pDocInfo)<>0
IF WritePrinter(hPrinter, pBuffer, SLen(cCmdString), @dwWritten)
IF (dwWritten == SLen(cCmdString))
lResult := TRUE
END
ELSE
dwWritten := GetLastError()
END
EndDocPrinter(hPrinter)
ELSE
dwWritten := GetLastError()
END
MemFree(pBuffer)
ClosePrinter(hPrinter)

ELSE
dwWritten := GetLastError()
END
MemFree(pszPrinter)
// End print this page...

ENDDO


RETURN NIL

METHOD SetupFormBackground(nTotalLabels, nLabelCount) CLASS
WELabel_WAPI
LOCAL cBkg, cFarb, cXRef, cYRef, cQ, cFrmBkupMode AS STRING


cQ := _chr(34)
cFarb := "N," // N="N/W", R="W/N".......
cXRef := PadL(NTrim(Floor(Val(LABEL_X_ORIGIN) * 8)), 3, "0")
cYRef := PadL(NTrim(Floor(Val(LABEL_Y_ORIGIN) * -8)), 3, "0")

// "Form Backup" occurs when the paper is retracted at the start of a
label -
// for longer print runs (multiple labels), we want to turn this off
until
// the last label in the print run is reached. Then turn it back on
again,
// so that the last label will be in the correct "tear-off" position.
cFrmBkupMode := Iif((nLabelCount < (nTotalLabels)), "JB", "JF")


// Set up coordinates and Form (8 dots per mm.)................
cBkg := cLF // Start command
structure...
cBkg += "N"+cLF // Clear image memory...
cBkg += "M117,0,0"+cLF // All memory to Direct
Mode...
cBkg += cFrmBkupMode+cLF // Form backup-mode...
cBkg += "ZB"+cLF // Set print direction...
cBkg += "R" + cXRef + "," + cYRef +cLF // Set reference point (so
we can move whole form dynamically)...
cBkg += "q832"+cLF // Set label width
(paper-width) (104)...
cBkg += "Q440,16"+cLF // Set Form-length
(paper-height) (55) and gap-width (2)...
cBkg += "X0,0,3,800,408"+cLF // Border rectangle
(form-width and -height) (100 * 51) to leave 2mm free all round......
cBkg += "LO0,40,800,3"+cLF // Horizontal line 1......
cBkg += "LO0,184,800,1"+cLF // Horizontal line 2......
cBkg += "LO440,216,360,1"+cLF // Horizontal line 3......
cBkg += "LO640,40,1,144"+cLF // Vertical line 1....
cBkg += "LO440,184,1,224"+cLF // Vertical line 2....
cBkg += "I8,2,049"+cLF // Character-set....

//TEXTBox{, , "cBkg = " + cBkg}:Show()

// Print top headers..............................
cBkg += "A16,12,0,4,1,1,N," + cQ + "BlahBlah GmbH, Germany" + cQ +
cLF // Print text...
cBkg += "A704,12,0,4,1,1,N," + cQ + "C1572" + cQ + cLF
// Print text...
// Print mid headers..............................
cBkg += "A16,64,0,2,1,1,N,"+cQ+ "Part Number:"+cQ+cLF //
Print text...
cBkg += "A16,96,0,2,1,1,N,"+cQ+ "Part Name..:"+cQ+cLF //
Print text...
cBkg += "A16,128,0,2,1,1,N,"+cQ+ "Revision...:"+cQ+cLF // Print
text...
cBkg += "A16,160,0,2,1,1,N,"+cQ+ "Serial No..:"+cQ+cLF //
Print text...
cBkg += "A320,160,0,2,1,1,N,"+cQ+ "LBA Cert.:"+cQ+cLF // Print
text...
cBkg += "A648,160,0,2,1,1,N,"+cQ+ "Stamp"+cQ+cLF // Print
text...
// Print lower LH headers..............................
cBkg += "A16,270,0,2,1,1,N,"+cQ+ "WE-Number..:"+cQ+cLF // Print
text...
cBkg += "A16,302,0,2,1,1,N,"+cQ+ "Order No...:"+cQ+cLF // Print
text...
cBkg += "A16,334,0,2,1,1,N,"+cQ+ "Batch No...:"+cQ+cLF // Print
text...
cBkg += "A16,366,0,2,1,1,N,"+cQ+ "Charge No..:"+cQ+cLF // Print
text...
// Print lower RH headers..............................
cBkg += "A480,196,0,2,1,1,N,"+cQ+ "Limited Shelf-Life Part"+cQ+cLF
// Print text...
cBkg += "A456,248,0,2,1,1,N,"+cQ+ "Mfg Date....:"+cQ+cLF //
Print text...
cBkg += "A456,280,0,2,1,1,N,"+cQ+ "Shelf-Life..:"+cQ+cLF //
Print text...
cBkg += "A456,312,0,2,1,1,N,"+cQ+ "Expiry Date :"+cQ+cLF //
Print text...
cBkg += "A456,344,0,2,1,1,N,"+cQ+ "Storage Date:"+cQ+cLF //
Print text...

SELF:cBkgCmd := cBkg


RETURN NIL

METHOD SetupFormData(nInThisPack, nLabelCount) CLASS WELabel_WAPI
LOCAL cData, cFarb, cQ AS STRING
LOCAL cTKZ, cRev, cSNVon, cSerN, cWENum, cOrdNum, cBatch, cChargeNum,
cShLDate AS STRING
LOCAL cShLife, cMfDate, cCuDate, cWEDate, cBen AS STRING
LOCAL cZNum, cZTyp, cZJahr, cZert, cCure, cLSN, cPos AS STRING
LOCAL nDrkZahl AS BYTE


cQ := _chr(34)
cFarb := "N," // N="N/W", R="W/N".......
nDrkZahl := 1


cTKZ := SELF:aWELData[1]
cBen := SELF:aWELData[2]
cRev := SELF:aWELData[3]

cSNVon := SELF:aWELData[6]
IF !Empty(cSNVon)
cSerN := NTrim(Val(cSNVon) + nLabelCount - 1)
ELSE
cSerN := "N/A"
ENDIF

cZert := SELF:aWELData[7]
cWENum := SELF:aWELData[8]
cOrdNum := SELF:aWELData[9]
cBatch := SELF:aWELData[10]
cChargeNum := SELF:aWELData[11]
cMfDate := SELF:aWELData[12]
cShLife := AllTrim(SELF:aWELData[13])
cShLDate := AllTrim(SELF:aWELData[14])
cWEDate := AllTrim(SELF:aWELData[15])


// Print Part-Details.........................
cData += "A168,58,0,4,1,1,"+cFarb+cQ+cTKZ+cQ+cLF // Print text...
cData += "A168,90,0,4,1,1,"+cFarb+cQ+cBen+cQ+cLF // Print text...
cData += "A168,122,0,4,1,1,"+cFarb+cQ+cRev+cQ+cLF // Print text...
cData += "A168,154,0,4,1,1,"+cFarb+cQ+cSerN+cQ+cLF // Print
text...
cData += "A448,154,0,4,1,1,"+cFarb+cQ+cZert+cQ+cLF // Print
text...

cData += "A168,266,0,4,1,1,"+cFarb+cQ+cWENum+cQ+cLF // Print
text...
cData += "A168,298,0,4,1,1,"+cFarb+cQ+cOrdNum+cQ+cLF // Print
text...
cData += "A168,330,0,4,1,1,"+cFarb+cQ+cBatch+cQ+cLF // Print
text...
cData += "A168,362,0,4,1,1,"+cFarb+cQ+cChargeNum+cQ+cLF // Print
text...

cData += "A620,242,0,4,1,1,"+cFarb+cQ+cMfDate+cQ+cLF // Print
text...
cData += "A620,274,0,4,1,1,"+cFarb+cQ+cShLife+cQ+cLF // Print
text...
cData += "A620,306,0,4,1,1,"+cFarb+cQ+cShLDate+cQ+cLF // Print
text...
cData += "A620,338,0,4,1,1,"+cFarb+cQ+cWEDate+cQ+cLF // Print
text...


// Final command to printer to print.........
cData += "P1,"+LTrim(Str(nDrkZahl))+cLF // Print contents of image
buffer...

SELF:cDataCmd := cData


RETURN NIL
 
Back
Top