I'm sure this has been raised before, but this is the first time I have tried printing from IWB!
My printer is an HP Desktop 2130, and it is set to default printer, and yet I cannot use the
WRITEPRINTER command.
I open the printer like this:
prtname = GETDEFAULTPRINTER
hPrinter = OPENPRINTER(prtname, "Job 1", "TEXT")
IF hPrinter
It's reading a simple text file, which I can confirm on screen, and yet nothing is printed, hPrinter returns 0 (zero) which means it failed to open the printer - does that mean my printer is not supported?
Thanks,
Andy.
Hi Andy
Struggling with a similar problem here. The only difference is that I am using a HP1210 printer.
I finally managed to print out plain text with the code below, but still have to find a way to set the margins.
The sub is coded with CB (a modified version of an example found in the old IB Std Archive). Just put an ENDSUB at the end, and it will work with IWB.
Maybe this can help you a little step further?
Egil
'
SUB PrintItem(wnd:window,ID:int)
'-------------------------------------------------------------------------------------
' Print selected Item
' ID = The Edit Control containing the text to print
'-------------------------------------------------------------------------------------
DEF buffer2[32766]:ISTRING
DEF printer:STRING
DEF startpg,endpg,copies,collate,hprinter:INT
startpg = 1 : endpg = 1 : copies = 1 : collate = 1
printer = PRTDIALOG(wnd,startpg,endpg,copies,collate)
hprinter = OPENPRINTER(printer,"Document","TEXT")
if(hprinter)
buffer2 = getcontroltext(wnd,ID)
WRITEPRINTER hprinter, buffer2
CLOSEPRINTER hprinter
endif
RETURN
Quote from: Andy on May 23, 2017, 11:56:26 PM
yet nothing is printed, hPrinter returns 0 (zero) which means it failed to open the printer - does that mean my printer is not supported?
It could mean your printer is configured for printing directly to the printer. That will cause the same thing. I duplicated that on my printer.
When I set it up to use the printers buffer then it returned the printers name and the printer command worked.
Larry,
Thanks for that, so is it a windows / printer setting somewhere? how do I change this?
Thanks
It COULD be a printer SETTING - in win7 it would be found START/Devices and Printers then select your printer. On my HP is was under the Advanced tab.
If it is not a SETTING it COULD be the DESIGN of your printer and you are just out of luck as for as I know.
Thanks Larry,
I will have a look now.
@Egil
When I was working on the module to to allow the IWBasic IDE user to printout code and preview it first and set the font, color, and margins I had to jump through all kinds of hoops to get it to work. I had to print it to hidden windows and use Listviews and such and it took around 1300 lines of code in one module(multiple subroutines) and there's probably some support routines scattered around outside that module.
It was so complicated and I haven't looked at it in so long I don't even know if I could figure out how it works right now. LOL.
Larry,
I found some of your code from this thread:
http://www.ionicwind.com/forums/index.php?topic=3044.msg25070#msg25070
It does indeed see my printer but there are 2 differences:
1. Does not return the printer's status.
2. On the output screen I get PrintProcessor as winprint not a hp one.
Quote from: LarryMc on May 24, 2017, 10:06:33 PM
@Egil
When I was working on the module to to allow the IWBasic IDE user to printout code and preview it first and set the font, color, and margins I had to jump through all kinds of hoops to get it to work. I had to print it to hidden windows and use Listviews and such and it took around 1300 lines of code in one module(multiple subroutines) and there's probably some support routines scattered around outside that module.
It was so complicated and I haven't looked at it in so long I don't even know if I could figure out how it works right now. LOL.
LarryMc,
That really sounds complicated. But at least the CB code I posted, prints to my rather cheap printer. The only thing I miss is being able to specify margins. But that is something I'll try to figure out.
On my machine the printer driver is winprint not HP's.
Done the usual things such as trying to change the driver to HP Deskjet 2130 - no joy.
Downloaded the HP driver for it (which is an exe file by the way), but when I browse to what I think is the USB driver for it, it says it's not for 32 bit machines - although you do not get an option for 32 bit machines.
Help / suggestions anyone please!
Andy,
Have you read the WRITEPRINTER page in the help file? WRITEPRINTER doesn't work with GDI-only printers
Brian
Hi Brian,
Yes I read that, maybe this one is a GDI only printer?, just thought I would try as LarryMc's example on this post was also a HP.
Notepad prints, the example editor program sees the printer so you can select it - but no joy.
But I can print from the IWB IDE!
Andy,
This example from peterpuk works for me. I'm printing the output to a PDF printer, to save ink and paper
Brian
Brian,
Thanks for the code, it actually printed! - shows up in the printer job queue and of it goes!
I'm going to have to study this one, but thanks again.
Andy. :)
I agree with that - it DOES need a lot of studying! How practical the code is in the
real world is debatable, but it does prove your printer works, I guess
Brian
Quote from: Brian Pugh on May 26, 2017, 02:27:24 AM
How practical the code is in the real world is debatable, but it does prove your printer works, I guess
Brian,
That code is full of good ideas, that ought to be be practical enough for most of us!
I have used most of my time this week trying to figure out how to set margins when printing text my own printer, and the code you posted showed me how. The API calls to
GetDeviceCaps produce exactly what I want!
Thanks for sharing.
Egil
I've made a few changes to the program Brian shipped over.
1. I've put the printing section into a sub routine PrintTheDoc.
2. The MakeFont sub routine has an optional value for italics.
That is:
bigfont=MakeFont("Arial",30,1) - where the 1 specifies use italics, otherwise use
bigfont=MakeFont("Arial",30) - no italics.
This program reads a text file, and prints the data line by line.
I would suggest you print to pdf and then open it to check how it's come out.
Please let me know how it looks on your machine - if the lines of data are not correct, change the
myx value to something else - the bigger the number, the further across the page it goes.
Attached is the program and the text file it reads.
Andy.
I noticed when playing around with this printing program that sometimes (for no reason) the output
could be printed at an angle, sometimes underlined, even upside down!
Then I spotted this line:
def fnt:logfont
It was buried inside a sub routine, so I moved it to just after logfont is declared (at the top of the code).
As far as I can see (on my PC) the printing is now behaving itself.
Would someone please test it for me!
Send the output to PDF to save ink.
Attached are the files.
Thanks.
Hi Andy,
This is how it prints here.
Egil
Egil,
Thanks for trying it, it's okay on my pc, but it looks like there is some difference between yours and mine.
Wonder why printing to a pdf would show a difference?
Anyway, in the PrintTheDoc sub routine - line 195, if you change the value of myx i.e. increase the value to say 800 or 1000 it should move the lines across the page.
Also, you could change the number of data lines per page say from 27 to 20?
Thanks,
Andy.
Andy,
Been experimenting with the x and y values to see what happened with the positioning of the printed text. Also used another textfile for testing.
It then appeared that all printed text was senter aligned, regardless of what alignment the original text had. Also printed to paper a couple of times, and the result was the same as with the PDF driver. (Bullzip PDF Printer).
I am also a little confused about the units used for the x and y values ( pixels or twips). I assume you mean pixels???
You posted while I was writing the above text. And your suggestions was exactly what I did for my experiments.
If I remember it right 1440 twips = 1 inch. So I'll experiment a little assuming the units should be i twips.
Egil
Copied my last post into NotePad to make a new test file.
Then I changed the x value and the font size before compiling and printing. The result is shown below.
Suggest that a variable specifying the maximum allowed length of any line, when considering the margins, and then fill the line with as many words there is room for, then print the line, and repeat this until the whole document is printed.
In MiniBasic the RichEdit controll class has a member doing just that. It is called with the margin value in twips. Very easy for the users.... ::)
Hi Egil,
Thanks again for testing!
I'd never heard of twips before, this printing business came about because the person who wanted the login program for the school wanted a print button on the screen so he could print off a log file.
In this instance, each line is short, but in view of the differences we are seeing, I've put in some fields so he can change the X offset, font sizes, and number of lines per page.
I will have to guide him with these values, and wait to see how he gets on with printing as I do not know what printers they have at the school.
Andy. :)
OK Andy,
Have you received the emails I sent you?
Egil
Hi Egil,
Partly my fault, forgot to tell you my new email address!
If you click on my name it shows the new one, however gone into the old ones and just reading them now.
Quote from: Andy on May 28, 2017, 04:34:30 AM
I'd never heard of twips before,
It's a typographical term, very often used when setting up printers. Maybe Brian know more about that.
Here is what Wikipedia says: https://en.wikipedia.org/wiki/Twip (https://en.wikipedia.org/wiki/Twip).
Egil
Just a thought, you could set up your output in an RTF document and then print from Word. Using CreateComObject, you should be able to adjust margins and other stuff and then print the RTF.
I have used the CreateComObject to read an Excel spread sheet and I know there is a way to work with Word files using this.
Of course, this brings up another question from me, can you put a picture in an RTF directly?
Bill
Bill,
Thanks for that, already had a button to open it in notepad but the person wanted it printing directly from the program I wrote for him.
Thanks,
Andy.
Andy,
Must be getting old here. Was out walking the dog, and all the fresh air usually clears my mind...
Many years ago I struggled when trying to make a print routine with EB, very similar to the printing job you are doing. Now I remember that it was solved by importing readings from an external sensor into a RichEdit Control, and sending the resulting list to a printer using @RTPRINT.
Can't find that source code, but look up @RTPRINT in the IWB user manual and use the example shown there when your "Print" button is clicked.
Egil
Andy
There is a way to get they x,y offsets of a printer without knowing the type of printer in advance.
Here is the subroutine I wrote for the IWBasic IDE that gets the User's default (selected) printer's info for setting of the print preview and printout functions. You might be able to study and use this.
TYPE SPRINTDLG,1
DEF lStructSize as UINT
DEF hwndOwner as UINT
DEF hDevMode as UINT
DEF hDevNames as UINT
DEF hDC as UINT
DEF Flags as UINT
DEF nFromPage as WORD
DEF nToPage as WORD
DEF nMinPage as WORD
DEF nMaxPage as WORD
DEF nCopies as WORD
DEF hInstance as UINT
DEF lCustData as UINT
DEF lpfnPrintHook as POINTER
DEF lpfnSetupHook as POINTER
DEF lpPrintTemplateName as POINTER
DEF lpSetupTemplateName as POINTER
DEF hPrintTemplate as UINT
DEF hSetupTemplate as UINT
ENDTYPE
sub getprinterdefault()
DEF strPrinter[32] as ISTRING
strPrinter[0] = NULL
SPRINTDLG pd
ZeroMemory(pd,LEN(SPRINTDLG))
pd.lStructSize = LEN(SPRINTDLG)
pd.nCopies=1
pd.Flags = PD_RETURNDC|PD_RETURNDEFAULT
PrintDlg(pd)
_fpreset()
IF pd.hDevNames
ppDZL = GetDeviceCaps(pd.hdc,PHYSICALOFFSETX) ' this is x offset - set to left margin
ppDZR = ppDZL ' set right margin to same as left
ppDZT = GetDeviceCaps(pd.hdc,PHYSICALOFFSETY) ' this is y offset - top margin
ppDZB = ppDZT ' set bottom margin to same as top
ppPrnPPI_x = GetDeviceCaps(pd.hdc,LOGPIXELSX) ' this is x pixels per inch
ppPrnPPI_y = GetDeviceCaps(pd.hdc,LOGPIXELSY) ' this is y pixels per inch
/* you don't need this part
pointer pString = GlobalLock(pd.hDevNames)
pointer pTemp = pString
pString += #<DEVNAMES>pString.wOutputOffset
strPrinter = #<STRING>pString
if(strPrinter[0] <> "\\")
pTemp += #<DEVNAMES>pTemp.wDeviceOffset
strPrinter = #<STRING>pTemp
endif
setcontroltext ppwin,ppwin_eSelectedPrinter,strPrinter
GlobalFree(pd.hDevNames)
*/
ENDIF
ENDSUB
Larry,
Got my head around the code - thanks.
I'm now trying to work out how many printable lines on an A4 page.
That is, for each line the font could be say.... 12.
Given the printable width and height (in inches) and the font (in points), how do you calculate how many lines you could actually print?
Quote from: Andy on May 29, 2017, 06:49:01 AM
how do you calculate how many lines you could actually print?
The easiest way will be to use
GETTEXTSIZE to get the height of the characters and divide available height with it.
Egil
Egil is right.
But you'll have to address word wrap.
I've used gettextsize and it returns a value of 22 pixels in height when using the same size font as printing.
The page height in inches is 11
In pixels the height is 6,600
Printable lines 300? - I could go for 30 but not 300? ???
Inches:
pphmm * 0.0393701 (where pphmm is height in millimeters)
Inches to pixels:
(pphmm * 0.0393701) * ydpi (where ydpi = 600)
Printable lines:
((pphmm * 0.0393701) * ydpi) / tHeight (where tHeight is 22)
I must be going wrong somewhere!
Andy,
Have a look at this code - it's from the master, Sapero. It might help you, or just confuse you!
The resulting box is the right dimension on my screen
Brian
Biran,
Thanks for finding the code - he was indeed the master.
Actually, I find it rather easy to understand - for once!
I'll play around with it.
Thanks,
Andy.
Well, still working on some aspects of printing.
With the code Brian and Larry have posted, I've cobbled together a library file called:
PrinterDetails.
Copy the lib file to the IWBDev\Libs folder and compile the iwb code.
Does anyone think this could be useful?
It may take a second or so to return some details.
Andy.
Andy,
It's "Jobs in the Garden" day today, so I will look at your lib later, but a SepFile is a string that specifies the name of the file used to create the separator page. This page is used to separate print jobs sent to the printer
Brian
Andy,
I haven't looked at your library, but IWBasic needs a printer library. Including a printer graphics library. All this could be included if there is a printer DC that is available, which it looks like there is. I would work on it, but the chemo messed my nerve endings up and its hurts to type very much. Can't tell when I'm pressing a key either so there is a lot of back spacing.
Later,
Clint
Brian,
Don't let those weeds grow too much.
Clint,
Glad to hear from you, take it easy!
I will look at adding more in tomorrow when l'll have more time including the DC.
Andy,
Here's a way of enumerating all printers, posted by Michael Hartlef about 10 years ago, I've tidied it up for use with IWB, and changed a few things
I've also added in the method of getting your Default Printer, as well, so you could ask for the default printer, and use the return string when setting up the printer DC
Brian
(Lawns cut, edges strimmed, weedkiller down, car vacuumed, tomato plants watered - Good boy!)
Brian,
All that and the gardening done, someone's going to get brownie points at home.
Enumerating printers begs the question - should we only be looking for physical printers?
In Devices and Printers (Control Panel) I have 4 printers listed, but only one is a physical printer, the HP, the others are:
Fax,
Microsoft print to PDF
Microsoft XPS document writer
Should we ignore these others?
I suppose the quick answer is: Depends where you want to print to!
I've been using the PDF driver lately
Brian
Well, I've got this far up to now....
OpenThePrinter("MyDocument") 'Also returns uint of printer DC
PrintLine(1000,800,"This is a line - Page 1","")
PrintLine(1000,900,"This is second line","")
NewPage()
PrintLine(1000,800,"This is first line - Page 2","")
PrintLine(1000,900,"And this is second line","")
CloseThePrinter()
Working on the fonts and sizes next.
Here is the next part.
Copy the lib folder to the IWBDev\libs folder.
In the IWB source file, read from ***** Part 2 *********
This is giving some basic line printing, and able to set fonts, and sizes.
You may have to play around with the X and Y's:
PrintLine(1000,800,"This is a line - Page 1","")
Where PrintLine is (X across, Y down, Text to print,"")
Again, I would suggest you print to PDF to save ink.
Keep up the good work Andy. The "lib" include and "External" lines could be put in an "inc" file. Then all you would have to do is "#include "Printer.inc".
Later,
Clint
Thanks for that Clint.
Yes I forgot about an include file, so that will be next on the list.
Cheers.
Andy,
Just been messing with changing font names, and I can't get it to change at all, even to common fonts like Times New Roman or Arial
Going out for the afternoon now - sorry
Brian
Enjoy the afternoon!
I will look at the font issue tomorrow.
Thanks for having a look.
Andy.
:)
I found the font problem.
1. I needed to return a UINT value instead of an INT.
2. The LOGFONT define is wrong!
I looked at all the examples and they all say:
CHAR lfFaceName[LF_FACESIZE]
I changed it to a string:
STRING lfFaceName
Now the fonts work.
So LOGFONT should look like this (just in case you use it):
TYPE LOGFONT
INT lfHeight
INT lfWidth
INT lfEscapement
INT lfOrientation
INT lfWeight
CHAR lfItalic
CHAR lfUnderline
CHAR lfStrikeOut
CHAR lfCharSet
CHAR lfOutPrecision
CHAR lfClipPrecision
CHAR lfQuality
CHAR lfPitchAndFamily
string lfFaceName
ENDTYPE
Here is the corrected version with fonts working.
Andy,
According to my Win 32 API book (1,500 pages, and counting), lfFaceName is indeed a string, which specifies the name of the typeface. If it is NULL, the GDI attempts to select the default device typeface
Brian
Brian,
Thanks for confirming that, it drove me stupid all yesterday.
Cheers,
Andy.
I've sine changed it to:
istring lfFaceName[32]
As MS state the string must not be longer than 32 characters.
TYPE LOGFONT
INT lfHeight
INT lfWidth
INT lfEscapement
INT lfOrientation
INT lfWeight
CHAR lfItalic
CHAR lfUnderline
CHAR lfStrikeOut
CHAR lfCharSet
CHAR lfOutPrecision
CHAR lfClipPrecision
CHAR lfQuality
CHAR lfPitchAndFamily
istring lfFaceName[32]
ENDTYPE