Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Sending commands directly to a printer

Status
Not open for further replies.

Schroeder

MIS
Sep 25, 2001
382
US
I'm trying to get a tractor-feed, dot matrix printer to do a few things that the regular VB Printer object won't allow me to do. Specifically, I'm trying to get the printer to reverse feed the paper a little bit.

The printer's manual lists commands in hex and decimal that I can send to the printer to make it do certain things, one of which is a reverse line feed. I have been unable to figure out how to send these commands to the printer. Obviously, I can't just send the hex codes through the Printer's Print method - the printer will just print the codes. I have been fiddling around with the WritePrinter API but I'm still doubtful as to whether this is the way to go. Besides, I haven't gotten it to work yet anyway.

The first question is: how might I send these commands to my printer so that it interprets them as commands and not text to be printed?

If I should use the WritePrinter API, can I just use the hDC property of the Printer object for the first argument of the function or do I really need to use OpenPrinter to acquire the correct handle?

My attempts at using WritePrinter have loaded Error.LastDllError with a value of 6. What does this error code mean?
 
This may be a shot in the dark, but the scale properties of a printer can be negative. This may reverse the printer feed.

For Each Printer_lobj In Printers
If Printer_lobj.DeviceName = "??" Then
Printer_lobj.ScaleLeft = 0
Printer_lobj.ScaleTop = -1
End If
Next Printer_lobj
Set Printer_lobj = Nothing

Anyway try taking a look at some of the printer objects properties.
 
Well, the printer does recognize the negative value for ScaleTop. The problem is, the printer seems to be keeping track of where it last printed and considering that to be the top of the page. Regardless of how low I set the ScaleTop value, it will not move up beyond the height of the previous print job.

My situation is, I'm printing three-across forms one at a time. When I was running this under Win98, the printer would begin each job by backfeeding until it found the top of the paper, then printing there. Now, under XP, it no longer works this way. I've tried using different printer drivers in an attempt to "dumb down" the interface between Windows and the printer. I've tried every setting on the printer that I could fathom. I just can't get the thing to forget where it last left off. I think that if I could slip this Reverse Line Feed command in the back door, I might be able to get it to lose track and start at the top every time.
 

There are a couple of ways to get the results of what you want to do, but first let me set the scenaro as I understand it.

You are basically printing labels, 3 wide x number of lines, lets say up to 5.

1st suggestion is to take the data from each first line and put it together to make one print line...
[tt]
Dim PrintLine As String

PrintLine = Aera1(LineX) & Space(XNumberOfSpaces - Len(Aera1(LineX))) & Aera2(LineX) & Space(XNumberOfSpaces = Len(Area2(LineX))) & Area3(LineX)

Printer.Print PrintLine
....
Printer.EndDoc
[/tt]
or something like that. Now this method would work well with a fixed width font like courier new, but if you are using a font like ariel then it gets a little more tricky. You would then need to use the textwidth property of say a form to calculate how many spaces you would need, to be able to place the first character of linex in the next section, and you would probably get undesirable results like...
this is line 1
and this is line 2
with this being line 3

So with that being said here is suggestion #2

Use the printers current X and Y properties to control where you print. This method is much easier to control and will give you the aligned results you want with using a non fixed width font like ariel, but it will not retract the paper.

So what you would do is print your 5 lines of section 1 then reset the currentY to where it was before you printed those 5 lines...

for this example start a new project and add a picture box to your form (picture1) and paste in the following code, run, and you will see what I am talking about.
[tt]
Option Explicit

Private Sub Form_Load()
Me.Width = 8000
Picture1.Width = 7800
Picture1.AutoRedraw = True
Picture1.Print "This Is A Test"
Picture1.Print "This is only a test."
Picture1.Print "Remember this is just a test."
Picture1.CurrentX = Picture1.TextWidth("This Is A Test")
Picture1.CurrentY = 0
Picture1.Print "."

Picture1.CurrentY = 0
Picture1.CurrentX = Picture1.TextWidth("Remember this is just a test.") + 500
Picture1.Print &quot;<Was missing peroid, looks like vbProperCase.&quot;
Picture1.CurrentX = Picture1.TextWidth(&quot;Remember this is just a test.&quot;) + 500
Picture1.Print &quot;<only a test of what?&quot;
Picture1.CurrentX = Picture1.TextWidth(&quot;Remember this is just a test.&quot;) + 500
Picture1.Print &quot;<shouldn't that have a comma after remember?&quot;

End Sub
[/tt]

I hope this helps, Good Luck

 
Thank you for the suggestions.

The situation, though, is this: The labels are indeed three across per page. We only print one at a time though. They're for shipping packages. A package will come along that needs one of these labels, the program will print the label and then, we may not need the next label until tomorrow. Under Win98, the printer, somewhat miraculously, began each job by backfeeding to the top of the form. My program kept track of which of the three labels on the current page had already been used and would print on the next label (incrementing .CurrentX accordingly). Life was good.

Now, the folks shipping packages must manually reset the paper after each label and I'm starting to receive angry looks when I walk by.
 
Your links led me to the Escape function which seems to be what I need. The trouble is, its a little over my head. The fourth parameter is &quot;a pointer to a block of data which contains in the first 16 bits the number of bytes of data to send. The remainder of the block contains the actual data buffer to send to the printer.&quot;

Well, I just don't know how to construct that block of data. I need to send the decimal values 27 and 93. By my calculations, that's two bytes of data. Am I correct that I need to calculate and store in a Long Integer variable (that I'll pass ByRef) a value that represents these three pieces of information?

This is where a formal computer science education would have come in handy.
 

Sorry I can't find the API or documentation you are referring to to be able to help. Please post a link of where you are and maybe someone can help.

Good Luck

 
Well, here's the function
That's for C though. I was quoting Appleman's book (hope that's not a big faux pas).

The declaration is:

Declare Function Escape Lib &quot;gdi32&quot; (ByVal hdc As Long, ByVal nEscape As Long, ByVal nCount As Long, lpInData As Any, lpOutData As Any) As Long
 

No its not. Did not think to look at Dan's book, but here is the Escape API from the API Viewer
[tt]
Public Declare Function Escape Lib &quot;gdi32&quot; (ByVal hdc As Long, ByVal nEscape As Long, ByVal nCount As Long, ByVal lpInData As String, lpOutData As Any) As Long
[/tt]
and here the fourth parameter is a string! (&quot;27 93&quot;) I'm am really doubtful that will work, but possibly, or maybe a byte array...
[tt]
Public Declare Function Escape Lib &quot;gdi32&quot; (ByVal hdc As Long, ByVal nEscape As Long, ByVal nCount As Long, ByRef lpInData As Byte, lpOutData As Any) As Long
[/tt]

Sorry, at this time I do not have access to a dot matrix to test this out on.

Maybe with my reply one of the other persons on this board may have some helpful input for you.

Good Luck

 
Sending the fourth parameter as a string seems to work.. inasmuch as the return value indicates the call was successful and Err.LastDllError returns 0. Unfortunately, the printer's reaction was not what I had hoped for. It started printing what we refer to around here as &quot;alien correspondence&quot;. Interestingly, among the gibberish were random pieces of code from the program itself.

I called the function thusly:

lngReturn = Escape(Printer.hdc, 19, 12, Chr(27) & Chr(93), 0)

19 being the Escape Type &quot;PASSTHROUGH&quot;. I also tried 2 for the third parameter.

I have yet to try sending a byte array. I was also thinking about defining a Type consisting of individual Bytes.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top