Karsten Hilbert
unread,Aug 11, 2019, 2:39:45 PM8/11/19Sign in to reply to author
Sign in to forward
You do not have permission to delete messages in this group
Sign in to report message
Either email addresses are anonymous for this group or you need the view member email addresses permission to view the original message
to wxPython-users
I am using code based on Andrea Gavana's screenshotting code
to take, well, screenshots of widgets of my application.
It worked fine on wxp3 but does not quite on wxp4.
The gist of the code is to
get the full screen coordinates of the widget to screenshot
get a wx.ScreenDC
get a wx.MemoryDC
tie the memory DC to a bitmap
Blit() the appopriate region of the screen DC into
the memory DC
save the bitmap
The first time this is applied to my maximized application
the proper image is created.
However, when I change what is shown inside my maximized
application and then re-screenshot the image will show the
exact same screenshot as when the wx.ScreenDC was first
created and screenshotted.
As if the wx.ScreenDC is a global singleton or else the same
memory region happens to be reused. Print()ing the DC's in
question shows that they are at different addresses :-/
I do take care the SelectObject(wx.NullBitmap) etc after
screenshotting but nothing seems to help. Here is the code I
am running:
#-------------------------------------------------------------------
def save_screenshot_to_file(filename=None, window=None):
assert (isinstance(window, wx.Window)), '<window> must be (sub)class of wx.Window'
print('widget to snap:', window)
widget_on_screen_rect = window.GetScreenRect()
print('getscreenrect:', widget_on_screen_rect)
x2snap_on_screen = max(0, widget_on_screen_rect.x)
y2snap_on_screen = max(0, widget_on_screen_rect.y)
print('sane (x,y) on screen to snap from:', x2snap_on_screen, y2snap_on_screen)
widget_rect = window.GetRect()
print('getrect:', widget_rect)
width2snap = widget_rect.width
height2snap = widget_rect.height
print('(w,h) to snap:', width2snap, height2snap)
# adjust for window decoration on Linux
if sys.platform == 'linux':
print('adjusting for widget decorations')
client_x, client_y = window.ClientToScreen((0, 0))
print('client2screen 0x0 coords:', client_x, client_y)
border_width_x = max(0, widget_rect.x)
border_width_y = max(0, widget_rect.y)
print('border (x,y):', border_width_x, border_width_y)
x2snap_on_screen = max(0, x2snap_on_screen - border_width_x)
y2snap_on_screen = max(0, y2snap_on_screen - border_width_y)
print('possibly adjusted (x,y) on screen to snap from:', x2snap_on_screen, y2snap_on_screen)
# get image from screen
screen_dc = wx.ScreenDC()
print('screen DC:', screen_dc)
widget_dc = wx.WindowDC(window)
print('widget DC:', widget_dc)
target_dc = wx.MemoryDC()
print('target DC:', target_dc)
wxbmp = wx.EmptyBitmap(width2snap, height2snap)
print(wxbmp)
target_dc.SelectObject(wxbmp)
target_dc.Blit ( # copy into this memory DC ...
0, 0, # ... to here in the memory DC (= target) ...
width2snap, height2snap, # ... that much ...
screen_dc, # ... from the screen DC ...
x2snap_on_screen, y2snap_on_screen # ... starting here
)
target_dc.SelectObject(wx.NullBitmap) # prevent ghosts ?
wxbmp.SaveFile(filename, wx.BITMAP_TYPE_PNG)
# cleanup
target_dc.Destroy()
del target_dc
screen_dc.Destroy()
del screen_dc
del widget_dc
del wxbmp
return filename
#-------------------------------------------------------------------
Anything obvious I am missing here ?
Thanks,
Karsten
--
GPG 40BE 5B0E C98E 1713 AFA6 5BC0 3BEA AC80 7D4F C89B