Printing web content
-
- Enthusiast
- Posts: 536
- Joined: Mon Feb 16, 2009 10:42 am
- Location: sweden
- Contact:
Printing web content
Hi all.
When I want to print something in windows i can use the webgadget and then a code like this http://www.purebasic.fr/english/viewtop ... 7&p=116305
When I want ot print web content on the mac I use applescript wrapper:
COCOA_AppleScript("tell application "+Chr(34)+"Safari"+Chr(34)+Chr(13)+Chr(10)+"activate"+Chr(13)+Chr(10)+"end tell")
COCOA_AppleScript("tell application "+Chr(34)+"Safari"+Chr(34)+Chr(13)+Chr(10)+"make new document at end of documents"+Chr(13)+Chr(10)+"set url of document 1 to "+Chr(34)+universal_url+Chr(34)+Chr(13)+Chr(10)+"end tell")
and have <body onload=document.print> in the html code.
Is there any remote chance someone with a great deal of knowledge in xcode can do something to print without using applescript? It gives me popups etc that stay and my customers are printing hundreds of times per day...
Any ideas?
When I want to print something in windows i can use the webgadget and then a code like this http://www.purebasic.fr/english/viewtop ... 7&p=116305
When I want ot print web content on the mac I use applescript wrapper:
COCOA_AppleScript("tell application "+Chr(34)+"Safari"+Chr(34)+Chr(13)+Chr(10)+"activate"+Chr(13)+Chr(10)+"end tell")
COCOA_AppleScript("tell application "+Chr(34)+"Safari"+Chr(34)+Chr(13)+Chr(10)+"make new document at end of documents"+Chr(13)+Chr(10)+"set url of document 1 to "+Chr(34)+universal_url+Chr(34)+Chr(13)+Chr(10)+"end tell")
and have <body onload=document.print> in the html code.
Is there any remote chance someone with a great deal of knowledge in xcode can do something to print without using applescript? It gives me popups etc that stay and my customers are printing hundreds of times per day...
Any ideas?
Re: Printing web content
Well, I don't have any answers for you but I do have questions.
It would appear (haven't tried it) that you are putting both lines in your code to print with AppleScript and are printing with thru Safari. I would like to know if it is possible to send text, thru a string variable, in AppleScript, to the printer (and not thru Safari)? I would like to loop thru the lines of a listviewgadget, for example, and send them to the printer. Oh, right now I save the text to a file and then load the file into TextEdit and print from there. I don't do much printing so it isn't much of a problem right now.
..then the next step will be to change the font and size...

It would appear (haven't tried it) that you are putting both lines in your code to print with AppleScript and are printing with thru Safari. I would like to know if it is possible to send text, thru a string variable, in AppleScript, to the printer (and not thru Safari)? I would like to loop thru the lines of a listviewgadget, for example, and send them to the printer. Oh, right now I save the text to a file and then load the file into TextEdit and print from there. I don't do much printing so it isn't much of a problem right now.
..then the next step will be to change the font and size...
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
-
- Enthusiast
- Posts: 536
- Joined: Mon Feb 16, 2009 10:42 am
- Location: sweden
- Contact:
Re: Printing web content
Now we are on to something.. I will make your day 
Probably web content could be printed by doing something in applescript like:
open document x
set size of window to 10,10 px (so basicly hidden)
print using default printer without a dialogue
close document x
Anyone know how?

Code: Select all
a.s="tell application "+Chr(34)+"TextEdit"+Chr(34)+#CRLF$
a.s+"open (choose file)"+#CRLF$
;or a.s+"open "+chr(34)+"textfile.rtf"+chr(34)+#crlf$
a.s+"tell front document"+#CRLF$
a.s+"print"+#CRLF$
a.s+"close"+#CRLF$
a.s+"End tell"+#CRLF$
a.s+"End tell"+#CRLF$
COCOA_AppleScript(a.s)
open document x
set size of window to 10,10 px (so basicly hidden)
print using default printer without a dialogue
close document x
Anyone know how?
-
- Enthusiast
- Posts: 536
- Joined: Mon Feb 16, 2009 10:42 am
- Location: sweden
- Contact:
Re: Printing web content
Duh... "I think we are on to something"..
My status should be downgraded from "enthusiast" to "donkey"..
Try switch out tell application "texteditor" to tell application "safari".
Code in applescript would be:
My status should be downgraded from "enthusiast" to "donkey"..
Try switch out tell application "texteditor" to tell application "safari".
Code in applescript would be:
Code: Select all
tell application "Safari"
open "/tmp/temp40617.html"
tell front document
print
close
end tell
close
end tell
-
- Enthusiast
- Posts: 536
- Joined: Mon Feb 16, 2009 10:42 am
- Location: sweden
- Contact:
Re: Printing web content
That works for local files. If you want a URL this is the applescript code we need
Code: Select all
tell application "Safari"
make new document at end of documents
set URL of document 1 to "http://purebasic.com"
--check if page has loaded
try
repeat
delay 0.5
tell application "System Events" to ¬
tell application process "Safari"
if (name of static text 1 of group 1 of window 1 as text) ¬
begins with "Contacting" or (name of static text 1 of group 1 ¬
of window 1 as text) begins with "Loading" then
else
exit repeat
end if
end tell
end repeat
on error
-- not allowed to check
delay 3
end try
tell front document
print
close
end tell
close
end tell
Re: Printing web content
Thanks jasper!
I ran your first code and the file went off to Safari fine but then the printer has a problem (/Library/Printers/Xerox/Filters/xc6120pstops failed). I dunno what that means other than it won't print. Oh, I got the same response in TextEdit.. the printer refused to cooperate.
Would there be a way to have the text file just load into TextEdit so I could re-format and access the printer dialogue? This works but it is just a stab in the dark.
Take out * these two lines and it gets ugly. The debugger crashes!
I ran your first code and the file went off to Safari fine but then the printer has a problem (/Library/Printers/Xerox/Filters/xc6120pstops failed). I dunno what that means other than it won't print. Oh, I got the same response in TextEdit.. the printer refused to cooperate.
Would there be a way to have the text file just load into TextEdit so I could re-format and access the printer dialogue? This works but it is just a stab in the dark.
Code: Select all
a.s="tell application "+Chr(34)+"TextEdit"+Chr(34)+#CRLF$
a.s+"open (choose file)"+#CRLF$
;or a.s+"open "+chr(34)+"textfile.rtf"+chr(34)+#crlf$
a.s+"tell front document"+#CRLF$ ; *
; a.s+"print"+#CRLF$
; a.s+"close"+#CRLF$
a.s+"End tell"+#CRLF$ ; *
a.s+"End tell"+#CRLF$
COCOA_AppleScript(a.s)
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
-
- Enthusiast
- Posts: 536
- Joined: Mon Feb 16, 2009 10:42 am
- Location: sweden
- Contact:
Re: Printing web content
I think you should be able to do a keystroke P with command (similar to doing the CMD-P shortcut to print)
or maybe just throw in a
You can always put "TRY" and "END TRY" in the Applescript code AND you can see the output if doing
debug COCOA_APPLESCRIPT("activate")
Code: Select all
tell application "System Events"
tell process "ProcessName"
keystroke "p"
end tell
end tell
Code: Select all
keystroke "P" using {command down}
debug COCOA_APPLESCRIPT("activate")
-
- Enthusiast
- Posts: 536
- Joined: Mon Feb 16, 2009 10:42 am
- Location: sweden
- Contact:
Re: Printing web content
Final procedure for Print webcontent:
Code: Select all
Procedure Printurl(url.s)
a.s="tell application "+Chr(34)+"Safari"+Chr(34)+#CRLF$
a.s+"make new document at end of documents"+#CRLF$
a.s+"set URL of document 1 to "+Chr(34)+url+Chr(34)+#CRLF$
a.s+"try"+#CRLF$
a.s+"repeat"+#CRLF$
a.s+"delay 0.5"+#CRLF$
a.s+"tell application "+Chr(34)+"System Events"+Chr(34)+" to "
a.s+"tell application process "+Chr(34)+"Safari"+Chr(34)+#CRLF$
a.s+"if (name of static text 1 of group 1 of window 1 as text) begins with "+Chr(34)+"Contacting"+Chr(34)
a.s+" or (name of Static text 1 of group 1 of window 1 as text) begins with "+Chr(34)+"Loading"+Chr(34)+" then "+#CRLF$
a.s+"else"+#CRLF$
a.s+"exit repeat"+#CRLF$
a.s+"end if"+#CRLF$
a.s+"end tell"+#CRLF$
a.s+"end repeat"+#CRLF$
a.s+"on error"+#CRLF$
a.s+"delay 5"+#CRLF$
a.s+"end try"+#CRLF$
a.s+"tell front document"+#CRLF$
a.s+"print"+#CRLF$
a.s+"close"+#CRLF$
a.s+"end tell"+#CRLF$
a.s+"close"+#CRLF$
a.s+"end tell"+#CRLF$
Debug a.s
COCOA_AppleScript(a.s)
EndProcedure
Re: Printing web content
Does this help ?jesperbrannmark wrote:Is there any remote chance someone with a great deal of knowledge in xcode can do something to print without using applescript? It gives me popups etc that stay and my customers are printing hundreds of times per day...
Any ideas?
Code: Select all
ImportC ""
objc_getClass(name.s)
sel_registerName(str.s)
objc_msgSend(theReceiver, theSelector, arg1 = #Null, arg2 = #Null)
HIWebViewGetWebView(inView)
EndImport
Sel_mainFrame = sel_registerName("mainFrame")
Sel_frameView = sel_registerName("frameView")
Sel_printOperationWithPrintInfo = sel_registerName("printOperationWithPrintInfo:")
Sel_runOperation = sel_registerName("runOperation")
SharedPrintInfo = objc_msgSend(objc_getClass("NSPrintInfo"), sel_registerName("sharedPrintInfo"))
If OpenWindow(0, 0, 0, 600, 340, "WebPrint", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ButtonGadget(0, 10, 10, 100, 20, "Print")
PBWebView = WebGadget(#PB_Any, 10, 50, 580, 280, "http://www.purebasic.com")
WebView = HIWebViewGetWebView(GadgetID(PBWebView))
MainFrame = objc_msgSend(WebView, Sel_mainFrame)
Repeat
EventID = WaitWindowEvent()
If EventID = #PB_Event_Gadget
Select EventGadget()
Case 0; *** Print content ***
FrameView = objc_msgSend(MainFrame, Sel_frameView)
PrintOperation = objc_msgSend(FrameView, Sel_printOperationWithPrintInfo, SharedPrintInfo)
objc_msgSend(PrintOperation, Sel_runOperation)
EndSelect
EndIf
Until EventID = #PB_Event_CloseWindow
EndIf
-
- Enthusiast
- Posts: 536
- Joined: Mon Feb 16, 2009 10:42 am
- Location: sweden
- Contact:
Re: Printing web content
OMG
Amazing. Is there a way to have it print with default printer (no printerrequester)
Also I noticed that if I move the lines that does the printing
To just before the repeat (so like doing an autoprint), we can actually print before the entire page is loaded. I had a similar problem in windows http://www.purebasic.fr/english/viewtop ... 13&t=46816 where it was solved with
A funny thing with your code is that if i do a it is hidden until i press the print button.... then it becomes visible. I also tried moving the webgadget outside of the window and that works for hiding the webgadget.
Thanks
J
Amazing. Is there a way to have it print with default printer (no printerrequester)
Also I noticed that if I move the lines that does the printing
Code: Select all
FrameView = objc_msgSend(MainFrame, Sel_frameView)
PrintOperation = objc_msgSend(FrameView, Sel_printOperationWithPrintInfo, SharedPrintInfo)
objc_msgSend(PrintOperation, Sel_runOperation)
Code: Select all
Repeat ;check if page has begun to load
Delay(20)
While WindowEvent(): Wend
Until GetGadgetText(gadget)=url
Repeat ;check if page is done loading
WebObject\get_Busy(@IsBusy.l)
Delay(20)
While WindowEvent(): Wend
Until IsBusy = 0
Code: Select all
HideGadget(PBWebView,1)
Thanks

J
Re: Printing web content
You don't have to hide the gadget. You can simply set its size to zero.
Code: Select all
ImportC ""
objc_getClass(name.p-ascii)
sel_registerName(str.p-ascii)
objc_msgSend(theReceiver, theSelector, arg1 = #Null, arg2 = #Null)
HIWebViewGetWebView(inView)
EndImport
Procedure MsgSend(receiver, selector.s, arg1 = #Null, arg2 = #Null)
ProcedureReturn objc_msgSend(receiver, sel_registerName(selector), arg1, arg2)
EndProcedure
Procedure MsgSendF(receiver, selector.s, arg1.f)
objc_msgSend(receiver, sel_registerName(selector), PeekL(@arg1))
EndProcedure
Procedure ClassMsgSend(class.s, selector.s, arg1 = #Null, arg2 = #Null)
ProcedureReturn objc_msgSend(objc_getClass(class), sel_registerName(selector), arg1, arg2)
EndProcedure
Procedure NSString(string.s)
Length = Len(String)
UniString = AllocateMemory(Length * 2 + 2)
PokeS(UniString, string, Length, #PB_Unicode)
Result = ClassMsgSend("NSString", "stringWithCharacters:length:", UniString, Length)
FreeMemory(UniString)
ProcedureReturn Result
EndProcedure
; get a shared print info object and set it up
PrintInfo = ClassMsgSend("NSPrintInfo", "sharedPrintInfo")
MsgSend(PrintInfo, "setOrientation:", 0); // 0 = portrait, 1 = landscape
MsgSend(PrintInfo, "setHorizontallyCentered:", #False)
MsgSend(PrintInfo, "setVerticallyCentered:", #False)
MsgSendF(PrintInfo, "setTopMargin:", 56.7); // 56.7 point = about 2 cm
MsgSendF(PrintInfo, "setLeftMargin:", 70.9); // 70.9 point = about 2.5 cm
MsgSendF(PrintInfo, "setBottomMargin:", 56.7)
MsgSendF(PrintInfo, "setRightMargin:", 56.7)
; main code
If OpenWindow(0, 0, 0, 600, 340, "WebPrint", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ButtonGadget(0, 10, 10, 100, 20, "Print")
PBWebView = WebGadget(#PB_Any, 0, 0, 0, 0, "")
WebView = HIWebViewGetWebView(GadgetID(PBWebView))
MainFrame = MsgSend(WebView, "mainFrame")
Repeat
EventID = WaitWindowEvent()
If EventID = #PB_Event_Gadget
Select EventGadget()
Case 0; *** Print purebasic site content ***
AutoreleasePool = ClassMsgSend("NSAutoreleasePool", "new")
; *** Set URL content ***
MsgSend(WebView, "setMainFrameURL:", NSString("http://www.purebasic.com"))
; ***
FrameView = MsgSend(MainFrame, "frameView")
Repeat
Delay(100)
IsBusy = MsgSend(WebView, "isLoading")
While WindowEvent() : Wend
Until IsBusy = 0
PrintOperation = MsgSend(FrameView, "printOperationWithPrintInfo:", PrintInfo)
MsgSend(PrintOperation, "setShowsPrintPanel:", #False)
MsgSend(PrintOperation, "runOperation")
MsgSend(AutoreleasePool, "drain")
EndSelect
EndIf
Until EventID = #PB_Event_CloseWindow
EndIf
Last edited by wilbert on Wed Jul 06, 2011 1:02 pm, edited 2 times in total.
Re: Printing web content
It's also possible by the way to set HTML content directly instead of loading from a file.
Here's how that can be done
Here's how that can be done
Code: Select all
ImportC ""
objc_getClass(name.p-ascii)
sel_registerName(str.p-ascii)
objc_msgSend(theReceiver, theSelector, arg1 = #Null, arg2 = #Null)
HIWebViewGetWebView(inView)
EndImport
Procedure MsgSend(receiver, selector.s, arg1 = #Null, arg2 = #Null)
ProcedureReturn objc_msgSend(receiver, sel_registerName(selector), arg1, arg2)
EndProcedure
Procedure MsgSendF(receiver, selector.s, arg1.f)
objc_msgSend(receiver, sel_registerName(selector), PeekL(@arg1))
EndProcedure
Procedure ClassMsgSend(class.s, selector.s, arg1 = #Null, arg2 = #Null)
ProcedureReturn objc_msgSend(objc_getClass(class), sel_registerName(selector), arg1, arg2)
EndProcedure
Procedure NSString(string.s)
Length = Len(String)
UniString = AllocateMemory(Length * 2 + 2)
PokeS(UniString, string, Length, #PB_Unicode)
Result = ClassMsgSend("NSString", "stringWithCharacters:length:", UniString, Length)
FreeMemory(UniString)
ProcedureReturn Result
EndProcedure
; get a shared print info object and set it up
PrintInfo = ClassMsgSend("NSPrintInfo", "sharedPrintInfo")
MsgSend(PrintInfo, "setOrientation:", 0); // 0 = portrait, 1 = landscape
MsgSend(PrintInfo, "setHorizontallyCentered:", #False)
MsgSend(PrintInfo, "setVerticallyCentered:", #False)
MsgSendF(PrintInfo, "setTopMargin:", 56.7); // 56.7 point = about 2 cm
MsgSendF(PrintInfo, "setLeftMargin:", 70.9); // 70.9 point = about 2.5 cm
MsgSendF(PrintInfo, "setBottomMargin:", 56.7)
MsgSendF(PrintInfo, "setRightMargin:", 56.7)
; main code
If OpenWindow(0, 0, 0, 600, 340, "WebPrint", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ButtonGadget(0, 10, 10, 100, 20, "Print")
PBWebView = WebGadget(#PB_Any, 0, 0, 0, 0, "")
WebView = HIWebViewGetWebView(GadgetID(PBWebView))
MainFrame = MsgSend(WebView, "mainFrame")
Repeat
EventID = WaitWindowEvent()
If EventID = #PB_Event_Gadget
Select EventGadget()
Case 0
AutoreleasePool = ClassMsgSend("NSAutoreleasePool", "new")
; *** Set HTML content directly using a string
HTMLString = NSString("This is a <b>test</b><hr><i>Italic</i>")
MsgSend(MainFrame, "loadHTMLString:baseURL:", HTMLString, #Null)
; ***
FrameView = MsgSend(MainFrame, "frameView")
Repeat
Delay(100)
IsBusy = MsgSend(WebView, "isLoading")
While WindowEvent() : Wend
Until IsBusy = 0
PrintOperation = MsgSend(FrameView, "printOperationWithPrintInfo:", PrintInfo)
MsgSend(PrintOperation, "setShowsPrintPanel:", #False)
MsgSend(PrintOperation, "runOperation")
MsgSend(AutoreleasePool, "drain")
EndSelect
EndIf
Until EventID = #PB_Event_CloseWindow
EndIf
Re: Printing web content
One more example.
This one shows how to use inline svg to draw vector shapes.
This one shows how to use inline svg to draw vector shapes.
Code: Select all
ImportC ""
objc_getClass(name.p-ascii)
sel_registerName(str.p-ascii)
objc_msgSend(theReceiver, theSelector, arg1 = #Null, arg2 = #Null, arg3 = #Null, arg4 = #Null)
HIWebViewGetWebView(inView)
EndImport
Procedure MsgSend(receiver, selector.s, arg1 = #Null, arg2 = #Null, arg3 = #Null, arg4 = #Null)
ProcedureReturn objc_msgSend(receiver, sel_registerName(selector), arg1, arg2, arg3, arg4)
EndProcedure
Procedure MsgSendF(receiver, selector.s, arg1.f)
objc_msgSend(receiver, sel_registerName(selector), PeekL(@arg1))
EndProcedure
Procedure ClassMsgSend(class.s, selector.s, arg1 = #Null, arg2 = #Null)
ProcedureReturn objc_msgSend(objc_getClass(class), sel_registerName(selector), arg1, arg2)
EndProcedure
Procedure NSString(string.s)
Length = Len(String)
UniString = AllocateMemory(Length * 2 + 2)
PokeS(UniString, string, Length, #PB_Unicode)
Result = ClassMsgSend("NSString", "stringWithCharacters:length:", UniString, Length)
FreeMemory(UniString)
ProcedureReturn Result
EndProcedure
; get a shared print info object and set it up
PrintInfo = ClassMsgSend("NSPrintInfo", "sharedPrintInfo")
MsgSend(PrintInfo, "setOrientation:", 0); // 0 = portrait, 1 = landscape
MsgSend(PrintInfo, "setHorizontallyCentered:", #False)
MsgSend(PrintInfo, "setVerticallyCentered:", #False)
MsgSendF(PrintInfo, "setTopMargin:", 56.7); // 56.7 point = about 2 cm
MsgSendF(PrintInfo, "setLeftMargin:", 70.9); // 70.9 point = about 2.5 cm
MsgSendF(PrintInfo, "setBottomMargin:", 56.7)
MsgSendF(PrintInfo, "setRightMargin:", 56.7)
; main code
If OpenWindow(0, 0, 0, 600, 340, "WebPrint", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ButtonGadget(0, 10, 10, 100, 20, "Print")
PBWebView = WebGadget(#PB_Any, 0, 0, 0, 0, "")
WebView = HIWebViewGetWebView(GadgetID(PBWebView))
MainFrame = MsgSend(WebView, "mainFrame")
Repeat
EventID = WaitWindowEvent()
If EventID = #PB_Event_Gadget
Select EventGadget()
Case 0
AutoreleasePool = ClassMsgSend("NSAutoreleasePool", "new")
; *** Set content directly using a string
XML.s = "<html xmlns='http://www.w3.org/1999/xhtml'><head></head><body>"
XML = XML + "This is a <b>test</b><hr/><i>Italic</i><br/>"
XML = XML + "<svg xmlns='http://www.w3.org/2000/svg' width='500' height='400'>"
XML = XML + "<rect x='0' y='0' width='500' height='400' style='fill:yellow; stroke:blue; stroke-width:12;' />"
XML = XML + "<polygon points='50,50 50,300 300,300' style='fill:blue; stroke:black;' />"
XML = XML + "</svg>"
XML = XML + "</body></html>"
XMLData = MsgSend(NSString(XML), "dataUsingEncoding:", 10)
MsgSend(MainFrame, "loadData:MIMEType:textEncodingName:baseURL:", XMLData, NSString("image/svg+xml"), NSString("ISO-10646-UCS-2"), #Null)
; ***
FrameView = MsgSend(MainFrame, "frameView")
Repeat
Delay(100)
IsBusy = MsgSend(WebView, "isLoading")
While WindowEvent() : Wend
Until IsBusy = 0
PrintOperation = MsgSend(FrameView, "printOperationWithPrintInfo:", PrintInfo)
MsgSend(PrintOperation, "setShowsPrintPanel:", #False)
MsgSend(PrintOperation, "runOperation")
MsgSend(AutoreleasePool, "drain")
EndSelect
EndIf
Until EventID = #PB_Event_CloseWindow
EndIf
Re: Printing web content
I converted my solution to print web content into a userlib.
http://www.purebasic.fr/english/viewtop ... 19&t=46856
http://www.purebasic.fr/english/viewtop ... 19&t=46856