Screenshot getting multiple monitors

193 views
Skip to first unread message

Sean Tiley

unread,
Oct 3, 2016, 9:28:05 PM10/3/16
to wxPython-users
Hello,
I am trying to figure out how to grab a  screenshot of one of my 2 monitors.
Using wxPython 3 and python version 2.7.12 running on latest Ubuntu

I am relatively new to python so any help is certainly appreciated.

I found several code snippets and have cobbled together pieces
This is what I have so far

import wx

displays
= (wx.Display(i) for i in range(wx.Display.GetCount()))
sizes
= [display.GetGeometry().GetSize() for display in displays]

for (i,s) in enumerate(sizes):
 
print("Monitor{} size is {}".format(i,s))

screen
= wx.ScreenDC()

size
= screen.GetSize()
size1
=screen.GetSizeMMTuple()

print("Width = {}".format(size[0]))
print("Heigh = {}".format(size[1]))

width
=size[0]
height
=size[1]

bmp
= wx.EmptyBitmap(width, height)
mem
= wx.MemoryDC(bmp)
mem
.Blit(0,0, width, height, screen, 0,0)

del mem
bmp
.SaveFile("testimg.png", wx.BITMAP_TYPE_PNG)


When I run I see the following info printed out on the console

Monitor0 size is (1366, 768)
Monitor1 size is (1920, 1080)
Width = 3286
Height = 1080

When the screenshot is taken, I get is a snapshot of the entire viewing area (both monitors).
I don't understand how to limit to one monitor or the other.  
I'm certain the issue is when I say 

screen = wx.ScreenDC()

but I don't know how to narrow down the size of that Object to the size of either of my monitors

Any thoughts are appreciated

Thanks
Sean



Steve Barnes

unread,
Oct 4, 2016, 12:45:38 AM10/4/16
to wxpytho...@googlegroups.com


On 04/10/2016 01:44, Sean Tiley wrote:
> Hello,
> I am trying to figure out how to grab a screenshot of one of my 2 monitors.
> Using wxPython 3 and python version 2.7.12 running on latest Ubuntu
>
> I am relatively new to python so any help is certainly appreciated.
>
> I found several code snippets and have cobbled together pieces
> This is what I have so far
>
> |
> importwx
>
> displays =(wx.Display(i)fori inrange(wx.Display.GetCount()))
> sizes =[display.GetGeometry().GetSize()fordisplay indisplays]
>
> for(i,s)inenumerate(sizes):
> print("Monitor{} size is {}".format(i,s))
>
> screen =wx.ScreenDC()
>
> size =screen.GetSize()
> size1=screen.GetSizeMMTuple()
>
> print("Width = {}".format(size[0]))
> print("Heigh = {}".format(size[1]))
>
> width=size[0]
> height=size[1]
>
> bmp =wx.EmptyBitmap(width,height)
> mem =wx.MemoryDC(bmp)
> mem.Blit(0,0,width,height,screen,0,0)
>
> delmem
> bmp.SaveFile("testimg.png",wx.BITMAP_TYPE_PNG)
>
> |
>
>
> When I run I see the followinginfo printed out on the console
>
>
> Monitor0 size is (1366, 768) Monitor1 size is (1920, 1080) Width = 3286
> Height = 1080
>
>
> When the screenshot is taken, I get is a snapshot of the entire viewing
> area (both monitors).
>
> I don't understand how to limit to one monitor or the other.
>
> I'm certain the issue is when I say
>
>
> screen = wx.ScreenDC()
>
>
> but I don't know how to narrow down the size of that Object to the size
> of either of my monitors
>
>
> Any thoughts are appreciated
>
>
> Thanks
>
> Sean
>
>
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "wxPython-users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to wxpython-user...@googlegroups.com
> <mailto:wxpython-user...@googlegroups.com>.
> For more options, visit https://groups.google.com/d/optout.

Sean,

If you get the geometry of each screen at the same time as the sizes
using screen.GetGeometry() then you can use the screen Width, Height,
Top & Left values in your call to mem.Blit in place of the values for
width, height, xsrc & yscr respectively, (you will also need to set your
EmptyBitmap size up to be the Size of the specific screen).

Possibly the quickest way to do this is to set up your ScreenCD before
your loop and capture each screen into an array of screen shots within a
for loop.

Hope that helps.
--
Steve (Gadget) Barnes
Any opinions in this message are my personal opinions and do not reflect
those of my employer.

Sean Tiley

unread,
Oct 5, 2016, 7:37:04 PM10/5/16
to wxPython-users
Steve, thanks for the info, I am struggling still.
When I unplug my second monitor everything works as expected, no real surprise there.

My Laptop screen size is 1366 x 768

However when I plug the second monitor 1920 x 1080

The first screenshot, (of the smaller res monitor),  I get is again an image of the smaller screen but there is a black band at the top of that image, presumably the height of the difference between the heights of my screen resolution (1080-766) adn it is missing the bottom of the screen

The second screenshot is very similar to the first image but wider (1920 pixels) and but the capture is still starting at the 0,0 coordinate of both my monitors
I am confused about the 'screen' parameter in the call to Blit.
I was thinking to shift the coordinates of the screen using SetClippingRect() but I can't seem to figure out how to adjust the spot the image is captured from, its always at upper left of my screens

How can i shift the screen ot maybe I'm thinking about this all wrong (likely the case)

Sean



def onScreenShot2():
app = wx.App(False)

displays = (wx.Display(i) for i in range(wx.Display.GetCount()))

    for i,d in enumerate(displays):
geom = d.GetGeometry() # inspect this in debugger
size = geom.GetSize()
print("Monitor{} size is {}".format(i,size))
width=size[0] #Width of Monitor
height=size[1] # Height of monitor
bmp = wx.EmptyBitmap(width, height) # create empty bitmap same size as screen
mem = wx.MemoryDC(bmp)
screen = wx.ScreenDC() # What is this,
#rect = (1366,0,width,height)
#screen.SetClippingRect(rect)
mem.Blit(0, 0, width, height, screen, 0, 0)
bmp.SaveFile("myImage_{}.png".format(i), wx.BITMAP_TYPE_PNG)

Steve Barnes

unread,
Oct 6, 2016, 1:31:16 AM10/6/16
to wxpytho...@googlegroups.com
> importwx
>
> displays =(wx.Display(i)fori inrange(wx.Display.GetCount()))
> sizes =[display.GetGeometry().GetSize()fordisplay indisplays]
>
> for(i,s)inenumerate(sizes):
> print("Monitor{} size is {}".format(i,s))
>
> screen =wx.ScreenDC()
>
> size =screen.GetSize()
> size1=screen.GetSizeMMTuple()
>
> print("Width = {}".format(size[0]))
> print("Heigh = {}".format(size[1]))
>
> width=size[0]
> height=size[1]
>
> bmp =wx.EmptyBitmap(width,height)
> mem =wx.MemoryDC(bmp)
> mem.Blit(0,0,width,height,screen,0,0)
>
> delmem
> bmp.SaveFile("testimg.png",wx.BITMAP_TYPE_PNG)
>
> |
>
>
> When I run I see the followinginfo printed out on the console
>
>
> Monitor0 size is (1366, 768) Monitor1 size is (1920, 1080) Width =
> 3286 Height = 1080
>
>
> When the screenshot is taken, I get is a snapshot of the entire
> viewing area (both monitors).
>
> I don't understand how to limit to one monitor or the other.
>
> I'm certain the issue is when I say
>
>
> screen = wx.ScreenDC()
>
>
> but I don't know how to narrow down the size of that Object to the
> size of either of my monitors
>
>
> Any thoughts are appreciated
>
>
> Thanks
>
> Sean
>
>
Sean,

You are correct in thinking that it is a thinking issue - you keep
thinking of 2 screens - the physical world rather than 2 displays each
showing parts of a single big canvas.

______________________
| | ___________ |<- Canvas
| 1 || 2 ||
|______|| ||
|_______|___________||

So as well as a size being unique for each screen it has a position on
the canvas and a) your MemoryDC size needs to match the size of the
screen that you blit from and the position _within the canvas_ so the
size of the blit needs to match the size of the monitor and the start
point, (the last two parameters), needs to match the position of the top
left of the screen on the canvas. So in the example above screen 1 will
start at 0, 0 on the canvas and might have a size of 640x480 and screen
2 will start at maybe 640, 100 and have a size of 1024x768.

So you need to query each screen for size and position and use the size
for the MemoryDC and both for the blit.

Sean Tiley

unread,
Oct 12, 2016, 7:17:52 PM10/12/16
to wxPython-users
Steve, thanks for the helpful guidance.
I finally got it, currently hardcoded for my monitor size but that I can fix

Much appreciated
Sean


On Monday, 3 October 2016 21:28:05 UTC-4, Sean Tiley wrote:
Reply all
Reply to author
Forward
0 new messages