Page 1 of 2
How to print window contents?
Posted: Wed Jan 20, 2010 4:51 am
by WilliamL
It seems like this should be easy. (Hasn't this been asked before?)
How can I get the active window into an image so I can send it to the printer? It seems like I would read the Point(x,y) of the window and Plot(x,y) them to an image.. or maybe it is something entirely different.
There isn't any API here (on a Mac), so how do I do it with pb only?
Re: How to print window contents?
Posted: Wed Jan 20, 2010 7:15 pm
by WilliamL
Here is some code that will copy a section of a window and put it into a image (which can be sent to the printer). All code was written by luis but I cannot find which thread he posted it in. I do not profess to understand how the code works... many thanks luis!
Code: Select all
;this code will copy a part of the Window (not screen) into an image
;all code written by luis in thread (http://www.purebasic.fr/english/viewtopic.php?f=12&t=38975&hilit=rotate+image )
procedure CopyImageToMemory(image_no.l,w,h, *mem)
Protected x.l, y.l, mem_pos.l ; Mac only
mem_pos = 0
StartDrawing(WindowOutput(image_no))
For y = 0 To h - 1
For x = 0 To w - 1
PokeL(*mem + mem_pos,(Point(x, y)))
mem_pos + 4
Next
Next
StopDrawing()
EndProcedure
Procedure CopyMemoryToImage(*mem,w,h, image_no.l)
Protected x.l, y.l, mem_pos.l
mem_pos = 0
If CreateImage(image_no,w,h)
StartDrawing(ImageOutput(image_no))
For y = 0 To ImageHeight(image_no) - 1
For x = 0 To ImageWidth(image_no) - 1
Plot(x, y, (PeekL(*mem + mem_pos)))
mem_pos + 4
Next
Next
StopDrawing()
Else
MessageRequester("Image not created","")
EndIf
EndProcedure
#wndw=1
#imageid=2
#gadgetid=3
w=200
h=200
If OpenWindow(#wndw,0,0,400,400, "2D Drawing Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If StartDrawing(WindowOutput(#wndw))
Box(150,20,20,20,RGB(0,255,0))
Circle(100,100,50,RGB(0,0,255)) ; filled circle
DrawingMode(#PB_2DDrawing_Outlined)
Circle(110,110,50,RGB(0,0,255)) ; empty cirle
For k=0 To 20
LineXY(10,10+k*8,200, 0,RGB(k*10,0,k*10))
Next
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(10,50,"Hello, this is a test",$00FF00)
StopDrawing()
EndIf
mem_size = w * h << 2
*mem = AllocateMemory(mem_size)
If *mem = 0
MessageRequester("NO *mem","")
EndIf
CopyImageToMemory(#wndw,w,h, *mem)
CopyMemoryToImage(*mem,w,h,#imageid)
ImageGadget(#gadgetid, 0,200,w,h, ImageID(#imageid))
Repeat
EventID = WaitWindowEvent()
Until EventID = #PB_Event_CloseWindow
EndIf
End
Re: How to print window contents?
Posted: Wed Jan 20, 2010 8:07 pm
by luis
UH ? Maybe you got inspired in some way by that thread but honestly I don't think you have to thanks me, what you posted here it's not something "I" wrote, it's all yours.
Bye !
Re: How to print window contents?
Posted: Wed Jan 20, 2010 8:12 pm
by freak
There is GrabDrawingImage() in PB 4.40

Re: How to print window contents?
Posted: Wed Jan 20, 2010 8:39 pm
by jamirokwai
freak wrote:There is GrabDrawingImage() in PB 4.40

Great, I was going to post this... This Function copys the content of the current StartDrawing()-destination into an image using a memory buffer and Point()...
freak, You could have saved me about one hour or so to figure this out...

I needed this function for my newest project.
Do I have to read the manual??? :roll:
Code: Select all
Procedure CopyScreenToImage(Breite, Hoehe, Image_No) ; working on Mac OS X - yeah!
Protected x.l, y.l, mem_pos.l, *Cache
*Cache = AllocateMemory(Breite * Hoehe * 4)
Mem_Pos = 0
For y = 0 To Hoehe - 1
For x = 0 To Breite - 1
PokeL(*Cache + Mem_Pos, Point(x,y))
Mem_Pos + 4
Next x
Next y
StopDrawing()
CreateImage(Image_No, Breite, Hoehe, 32)
StartDrawing(ImageOutput(Image_No))
Mem_Pos = 0
For y = 0 To Hoehe - 1
For x = 0 To Breite - 1
Plot(x, y, PeekL(*Cache + Mem_Pos));Point(x,y))
Mem_Pos + 4
Next x
Next y
StopDrawing()
FreeMemory(*Cache)
EndProcedure
Re: How to print window contents?
Posted: Wed Jan 20, 2010 8:44 pm
by WilliamL
- Added: GrabDrawingImage(), DrawRotatedText()
Yep, I knew just as soon as I posted the code someone would have a much better solution.
I don't see GrabDrawingImage() in the manual so how about some info? Would it be GrabDrawingImage(WindowOutput(#wndid),w,h) or what?
@Freak - you should have let me enjoy the effort for a few minutes.. at least.

(wry humor)
@jamirokwai ยป Thanks for the effort. I appreciate it. Maybe I can repay you by getting an explanation of how the command works.
Re: How to print window contents?
Posted: Wed Jan 20, 2010 9:09 pm
by luis
WilliamL wrote:
I don't see GrabDrawingImage() in the manual so how about some info?
http://www.purebasic.com/documentation/ ... image.html
It's in the helpfile too, at least in the 4.41 RC1.
Re: How to print window contents?
Posted: Wed Jan 20, 2010 9:49 pm
by WilliamL
Thanks again luis,
I see it with your link. I'm really glad to have this info so I can 'get on with it'.. what a time saver.
Code: Select all
#wndw=1
#imageid=2
#gadgetid=3
w=200
h=200
If OpenWindow(#wndw,0,0,400,400, "2D Drawing Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If StartDrawing(WindowOutput(#wndw))
Box(150,20,20,20,RGB(0,255,0))
Circle(100,100,50,RGB(0,0,255)) ; filled circle
DrawingMode(#PB_2DDrawing_Outlined)
Circle(110,110,50,RGB(0,0,255)) ; empty cirle
For k=0 To 20
LineXY(10,10+k*8,200, 0,RGB(k*10,0,k*10))
Next
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(10,50,"Hello, this is a test",$00FF00)
GrabDrawingImage(#imageid,0,0,w,h)
StopDrawing()
EndIf
ImageGadget(#gadgetid, 0,200,w,h, ImageID(#imageid))
Repeat
EventID = WaitWindowEvent()
Until EventID = #PB_Event_CloseWindow
EndIf
End
Re: How to print window contents?
Posted: Wed Jan 20, 2010 10:32 pm
by WilliamL
Here is a stab at printing the window. This does not work and I get a black box in the print-out. (I use Preview in the Print dialoge to save paper) Any ideas why?
Code: Select all
>>>>. see the example below, by luis, that works!
[code]#wndw=1
#gadget1=2
Procedure PrintWindow(wndid.l)
Define imageid.l
w=WindowWidth(wndid)
h=WindowHeight(wndid)
If CreateImage(imageid,w,h)
If StartDrawing(WindowOutput(wndid))
GrabDrawingImage(ImageOutput(imageid),0,0,w,h)
StopDrawing()
EndIf
EndIf
If PrintRequester()
If StartPrinting("Print window")
If StartDrawing(PrinterOutput())
DrawImage(ImageID(imageid),0,0,w,h)
StopDrawing()
EndIf
StopPrinting()
EndIf
EndIf
EndProcedure
w=200
h=200
If OpenWindow(#wndw,0,0,w,h+64, "2D Drawing Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
If StartDrawing(WindowOutput(#wndw))
Box(150,20,20,20,RGB(0,255,0))
Circle(100,100,50,RGB(0,0,255)) ; filled circle
DrawingMode(#PB_2DDrawing_Outlined)
Circle(110,110,50,RGB(0,0,255)) ; empty cirle
For k=0 To 20
LineXY(10,10+k*8,200, 0,RGB(k*10,0,k*10))
Next
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(10,50,"Hello, this is a test",$00FF00)
StopDrawing()
EndIf
ListViewGadget(#gadget1,4,210,w-8,50)
AddGadgetItem(#gadget1,-1,"Line 1")
PrintWindow(#wndw)
Repeat
EventID = WaitWindowEvent()
Until EventID = #PB_Event_CloseWindow
EndIf
End
Re: How to print window contents?
Posted: Wed Jan 20, 2010 10:59 pm
by luis
I'm not sure what you are trying to accomplish, if to get an hard-copy of the window (with buttons, gui elements, etc.) or to print the content of graphic area (a bitmap on the window)
Anyway, for the example you posted probably it's better to use an image and draw to that...
Code: Select all
#wndw=1
#img=1
Procedure PrintWindow(nImage)
; Define imageid.l
;
; w=WindowWidth(wndid)
; h=WindowHeight(wndid)
; If CreateImage(imageid,w,h)
; If StartDrawing(ImageOutput(imageid))
; GrabDrawingImage(WindowOutput(wndid),0,0,w,h)
; StopDrawing()
; EndIf
; Else
;
; EndIf
If PrintRequester()
If StartPrinting("Print window")
If StartDrawing(PrinterOutput())
DrawImage(ImageID(nImage),ImageWidth(nImage),ImageHeight(nImage))
StopDrawing()
EndIf
StopPrinting()
EndIf
EndIf
EndProcedure
w=200
h=200
If OpenWindow(#wndw,0,0,w,h, "2D Drawing Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
nImage = CreateImage(#PB_Any, w,h)
ImageGadget(#img, 0,0,w,h,ImageID(nImage))
If StartDrawing(ImageOutput(nImage))
Box(150,20,20,20,RGB(0,255,0))
Circle(100,100,50,RGB(0,0,255)) ; filled circle
DrawingMode(#PB_2DDrawing_Outlined)
Circle(110,110,50,RGB(0,0,255)) ; empty cirle
For k=0 To 20
LineXY(10,10+k*8,200, 0,RGB(k*10,0,k*10))
Next
DrawingMode(#PB_2DDrawing_Transparent)
DrawText(10,50,"Hello, this is a test",$00FF00)
StopDrawing()
EndIf
PrintWindow(nImage)
Repeat
EventID = WaitWindowEvent()
Until EventID = #PB_Event_CloseWindow
EndIf
End
This *should* work... oh , maybe you have to fill the image white before drawing to it, I cannot test it right now.
Re: How to print window contents?
Posted: Wed Jan 20, 2010 11:03 pm
by WilliamL
luis,
Yes, that does work and I've used it before. I'm trying to get all the graphics and gadgets in the window to print (actually I'm more interested in gadgets at this point). I edited my code above.
Re: How to print window contents?
Posted: Wed Jan 20, 2010 11:08 pm
by luis
You are using GrabDrawingImage() the wrong way I believe. I never used before but I seee in the help the first param is an image number or #PB_Any, check your code
I imagine it works grabbing the area from the currently "open" output, you don't have to pass it as a param !
Re: How to print window contents?
Posted: Wed Jan 20, 2010 11:19 pm
by luis
Code: Select all
#wndw=1
#gadget1=1
#gadget2=2
Procedure PrintWindow(wndid.l)
Define imageid.l
w=WindowWidth(wndid)
h=WindowHeight(wndid)
If CreateImage(imageid,w,h)
If StartDrawing(WindowOutput(wndid))
imageid = GrabDrawingImage(#PB_Any,0,0,w,h)
StopDrawing()
EndIf
EndIf
If PrintRequester()
If StartPrinting("Print window")
If StartDrawing(PrinterOutput())
DrawImage(ImageID(imageid),w,h)
StopDrawing()
EndIf
StopPrinting()
EndIf
EndIf
EndProcedure
w=200
h=200
If OpenWindow(#wndw,0,0,w,h+64, "tes", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ButtonGadget(#gadget2, 10, 10, 100, 30, "print")
ListViewGadget(#gadget1,4,210,w-8,50)
AddGadgetItem(#gadget1,-1,"Line 1")
Repeat
EventID = WaitWindowEvent()
If EventID = #PB_Event_Gadget
If EventGadget() = #gadget2
PrintWindow(#wndw)
EndIf
EndIf
Until EventID = #PB_Event_CloseWindow
EndIf
End
Re: How to print window contents?
Posted: Wed Jan 20, 2010 11:21 pm
by luis
Your code was using the GrabDrawingImage() in the wrong way, see the code above.
Another problem was the fact you have to give time to the window to process the events to paint itself, you shouldn't try to print it while constructing it (adding the pieces).
Re: How to print window contents?
Posted: Wed Jan 20, 2010 11:30 pm
by WilliamL
luis,
Yes, that works! I'm studying your code to understand the event problem. I would normally use the print routine with a button anyway and my example was for brevity.
Thanks again and again for your help, I was about to give up.
