How to print window contents?

Mac OSX specific forum
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

How to print window contents?

Post 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?
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: How to print window contents?

Post 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
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: How to print window contents?

Post 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 !
"Have you tried turning it off and on again ?"
A little PureBasic review
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Re: How to print window contents?

Post by freak »

There is GrabDrawingImage() in PB 4.40 ;)
quidquid Latine dictum sit altum videtur
jamirokwai
Enthusiast
Enthusiast
Posts: 796
Joined: Tue May 20, 2008 2:12 am
Location: Cologne, Germany
Contact:

Re: How to print window contents?

Post 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... :shock: 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
Regards,
JamiroKwai
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: How to print window contents?

Post 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.
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: How to print window contents?

Post 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.
"Have you tried turning it off and on again ?"
A little PureBasic review
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: How to print window contents?

Post 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
Last edited by WilliamL on Thu Jan 21, 2010 1:38 am, edited 2 times in total.
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: How to print window contents?

Post 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
Last edited by WilliamL on Wed Jan 20, 2010 11:49 pm, edited 6 times in total.
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: How to print window contents?

Post 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.
"Have you tried turning it off and on again ?"
A little PureBasic review
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: How to print window contents?

Post 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.
Last edited by WilliamL on Thu Jan 21, 2010 12:00 am, edited 3 times in total.
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: How to print window contents?

Post 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 !
"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: How to print window contents?

Post 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

"Have you tried turning it off and on again ?"
A little PureBasic review
User avatar
luis
Addict
Addict
Posts: 3893
Joined: Wed Aug 31, 2005 11:09 pm
Location: Italy

Re: How to print window contents?

Post 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).
"Have you tried turning it off and on again ?"
A little PureBasic review
WilliamL
Addict
Addict
Posts: 1252
Joined: Mon Aug 04, 2008 10:56 pm
Location: Seattle, USA

Re: How to print window contents?

Post 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. :D
Last edited by WilliamL on Wed Jan 20, 2010 11:38 pm, edited 1 time in total.
MacBook Pro-M1 (2021), Sequoia 15.4, PB 6.20
Post Reply